mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-18 11:38:08 +00:00
Merge remote-tracking branch 'linphonemaster/master'
This commit is contained in:
commit
416aba3a2c
79 changed files with 5751 additions and 579 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -76,3 +76,4 @@ tools/lpc2xml_test
|
|||
tools/xml2lpc_test
|
||||
coreapi/help/filetransfer
|
||||
tester/receive_file.dump
|
||||
tester/tmp.db
|
||||
|
|
|
|||
|
|
@ -1,18 +1,102 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
project(LINPHONE C)
|
||||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
project(LINPHONE C CXX)
|
||||
|
||||
|
||||
set(LINPHONE_MAJOR_VERSION "3")
|
||||
set(LINPHONE_MINOR_VERSION "7")
|
||||
set(LINPHONE_MICRO_VERSION "0")
|
||||
set(LINPHONE_VERSION "${LINPHONE_MAJOR_VERSION}.${LINPHONE_MINOR_VERSION}.${LINPHONE_MICRO_VERSION}")
|
||||
set(LINPHONE_SO_VERSION "6")
|
||||
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
option(ENABLE_STATIC "Build static library (default is shared library)." NO)
|
||||
option(ENABLE_CONSOLE_UI "Turn on or off compilation of console interface." YES)
|
||||
option(ENABLE_DATE "Use build date in internal version number." NO)
|
||||
option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." YES)
|
||||
option(ENABLE_LDAP "Enable LDAP support." NO)
|
||||
option(ENABLE_MSG_STORAGE "Turn on compilation of message storage." YES)
|
||||
option(ENABLE_NOTIFY "Enable libnotify support." YES)
|
||||
option(ENABLE_RELATIVE_PREFIX "Find resources relatively to the installation directory." NO)
|
||||
option(ENABLE_TOOLS "Turn on or off compilation of console interface" YES)
|
||||
option(ENABLE_TUNNEL "Turn on compilation of tunnel support." NO)
|
||||
option(ENABLE_TUTORIALS "Enable compilation of tutorials." YES)
|
||||
option(ENABLE_UNIT_TESTS "Enable compilation of unit tests." YES)
|
||||
option(ENABLE_UPNP "Build with uPnP support." YES)
|
||||
option(ENABLE_VIDEO "Build with video support." YES)
|
||||
cmake_dependent_option(ENABLE_ASSISTANT "Turn on assistant compiling." YES "ENABLE_GTK_UI" NO)
|
||||
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_PREFIX_PATH}/share/cmake/Modules)
|
||||
|
||||
include(CheckIncludeFile)
|
||||
|
||||
if(MSVC)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_PREFIX_PATH}/include/MSVC)
|
||||
endif()
|
||||
|
||||
find_package(BelleSIP REQUIRED)
|
||||
find_package(MS2 REQUIRED)
|
||||
find_package(XML2 REQUIRED)
|
||||
|
||||
option(LINPHONE_ENABLE_VIDEO "Build linphone with video support." ON)
|
||||
|
||||
include_directories(
|
||||
include/
|
||||
coreapi/
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/coreapi/
|
||||
${BELLESIP_INCLUDE_DIRS}
|
||||
${MS2_INCLUDE_DIRS}
|
||||
${XML2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
${CMAKE_INSTALL_PREFIX}/include/libxml2
|
||||
)
|
||||
if(MSVC)
|
||||
include_directories(${CMAKE_PREFIX_PATH}/include/MSVC)
|
||||
endif()
|
||||
|
||||
|
||||
if(ENABLE_RELATIVE_PREFIX)
|
||||
set(LINPHONE_DATA_DIR ".")
|
||||
else()
|
||||
set(LINPHONE_DATA_DIR "${CMAKE_INSTALL_PREFIX}")
|
||||
endif()
|
||||
set(LINPHONE_PLUGINS_DIR "${LINPHONE_DATA_DIR}/lib/liblinphone/plugins")
|
||||
set(PACKAGE_LOCALE_DIR "${LINPHONE_DATA_DIR}/share/locale")
|
||||
set(PACKAGE_DATA_DIR "${LINPHONE_DATA_DIR}/share")
|
||||
set(PACKAGE_SOUND_DIR "${LINPHONE_DATA_DIR}/share/sounds/linphone")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/config.h PROPERTIES GENERATED ON)
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
|
||||
|
||||
add_subdirectory(coreapi)
|
||||
add_subdirectory(share)
|
||||
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/FindLinphone.cmake
|
||||
DESTINATION share/cmake/Modules
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
)
|
||||
|
|
|
|||
69
FindLinphone.cmake
Normal file
69
FindLinphone.cmake
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
############################################################################
|
||||
# FindLinphone.txt
|
||||
# Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# - Find the linphone include file and library
|
||||
#
|
||||
# LINPHONE_FOUND - system has linphone
|
||||
# LINPHONE_INCLUDE_DIRS - the linphone include directory
|
||||
# LINPHONE_LIBRARIES - The libraries needed to use linphone
|
||||
# LINPHONE_CPPFLAGS - The compilation flags needed to use linphone
|
||||
|
||||
find_package(ORTP REQUIRED)
|
||||
find_package(MS2 REQUIRED)
|
||||
find_package(XML2 REQUIRED)
|
||||
find_package(BelleSIP REQUIRED)
|
||||
|
||||
set(_LINPHONEROOT_PATHS
|
||||
${WITH_LINPHONE}
|
||||
${CMAKE_INSTALL_PREFIX}
|
||||
)
|
||||
|
||||
find_path(LINPHONE_INCLUDE_DIRS
|
||||
NAMES linphone/linphonecore.h
|
||||
HINTS _LINPHONE_ROOT_PATHS
|
||||
PATH_SUFFIXES include
|
||||
)
|
||||
|
||||
if(LINPHONE_INCLUDE_DIRS)
|
||||
set(HAVE_LINPHONE_LINPHONECORE_H 1)
|
||||
endif()
|
||||
|
||||
find_library(LINPHONE_LIBRARIES
|
||||
NAMES linphone
|
||||
HINTS ${_LINPHONE_ROOT_PATHS}
|
||||
PATH_SUFFIXES bin lib
|
||||
)
|
||||
|
||||
list(APPEND LINPHONE_INCLUDE_DIRS ${ORTP_INCLUDE_DIRS} ${MS2_INCLUDE_DIRS} ${XML2_INCLUDE_DIRS} ${BELLESIP_INCLUDE_DIRS})
|
||||
list(APPEND LINPHONE_LIBRARIES ${ORTP_LIBRARIES} ${MS2_LIBRARIES} ${XML2_LIBRARIES} ${BELLESIP_LIBRARIES})
|
||||
|
||||
list(REMOVE_DUPLICATES LINPHONE_INCLUDE_DIRS)
|
||||
list(REMOVE_DUPLICATES LINPHONE_LIBRARIES)
|
||||
set(LINPHONE_CPPFLAGS ${MS2_CPPFLAGS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Linphone
|
||||
DEFAULT_MSG
|
||||
LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS
|
||||
)
|
||||
|
||||
mark_as_advanced(LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS)
|
||||
15
README.mingw
15
README.mingw
|
|
@ -4,20 +4,20 @@ Software to install
|
|||
Download lastest mingw-get-setup.exe from http://www.mingw.org
|
||||
Run mingw-get-setup.exe.
|
||||
In the package list, select and install:
|
||||
* mingw32-developer-tool
|
||||
* mingw-developer-toolkit
|
||||
* mingw32-base
|
||||
* mingw32-gcc-g++
|
||||
* mingw32-pthreads-w32
|
||||
* msys-base
|
||||
* msys-zip
|
||||
* msys-unzip
|
||||
* msys-wget
|
||||
|
||||
For more information:
|
||||
http://www.mingw.org/wiki/Getting_Started
|
||||
|
||||
In mingw shell (also refered as msys), run
|
||||
|
||||
mingw-get install msys-zip
|
||||
mingw-get install msys-unzip
|
||||
mingw-get install msys-wget
|
||||
|
||||
mkdir -p /opt/perl/bin
|
||||
cp /bin/perl /opt/perl/bin/.
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ libintl.a libintl.la libintl.dll.a
|
|||
|
||||
* Download and install Inno Setup Compiler (required only if you run 'make setup.exe'). Add it to your windows Path environment variable.
|
||||
|
||||
* Install msys-git from (http://code.google.com/p/msysgit/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE.
|
||||
* Install msys-git from (http://msysgit.github.io/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE.
|
||||
|
||||
|
||||
General rules for compilation
|
||||
|
|
@ -98,7 +98,8 @@ Building plugins (optional)
|
|||
***************************
|
||||
|
||||
This the example for msx264 (H264 plugin), the same applies for other linphone plugins.
|
||||
$ cd mediastreamer2/plugins/msx264
|
||||
$ git clone git://git.linphone.org/msx264.git
|
||||
$ cd msx264
|
||||
$ ./autogen.sh
|
||||
$ PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
|
||||
#make a binary zip of this plugin
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ LOCAL_C_INCLUDES = $(common_C_INCLUDES)
|
|||
LOCAL_CFLAGS = -DIN_LINPHONE
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
ifeq ($(BUILD_MATROSKA), 1)
|
||||
LOCAL_CFLAGS += -DHAVE_MATROSKA
|
||||
endif
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := cunit liblinphone
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\belle-sip\include;$(ProjectDir)..\..\oRTP\include;$(ProjectDir)..\..\mediastreamer2\include;$(ProjectDIr)..\..\..\tunnel\include;$(ProjectDir)..\..\coreapi;$(ProjectDir)..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LINPHONE_VERSION="Devel";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR="";UNICODE;_XKEYCHECK_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LINPHONE_VERSION="Devel";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR=".";UNICODE;_XKEYCHECK_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
|
|
|
|||
32
config.h.cmake
Normal file
32
config.h.cmake
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/***************************************************************************
|
||||
* config.h.cmake
|
||||
* Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define LINPHONE_MAJOR_VERSION ${LINPHONE_MAJOR_VERSION}
|
||||
#define LINPHONE_MINOR_VERSION ${LINPHONE_MINOR_VERSION}
|
||||
#define LINPHONE_MICRO_VERSION ${LINPHONE_MICRO_VERSION}
|
||||
#define LINPHONE_VERSION "${LINPHONE_VERSION}"
|
||||
#define LIBLINPHONE_VERSION "${LINPHONE_VERSION}"
|
||||
|
||||
#define LINPHONE_PLUGINS_DIR "${LINPHONE_PLUGINS_DIR}"
|
||||
#define PACKAGE_LOCALE_DIR "${PACKAGE_LOCALE_DIR}"
|
||||
#define PACKAGE_DATA_DIR "${PACKAGE_DATA_DIR}"
|
||||
#define PACKAGE_SOUND_DIR "${PACKAGE_SOUND_DIR}"
|
||||
|
|
@ -537,7 +537,7 @@ fi
|
|||
|
||||
dnl conditionnal build of video support
|
||||
AC_ARG_ENABLE(video,
|
||||
[AS_HELP_STRING([--enable-video], [Turn on video support compiling])],
|
||||
[AS_HELP_STRING([--enable-video], [Turn on video support compiling (default=yes)])],
|
||||
[case "${enableval}" in
|
||||
yes) video=true ;;
|
||||
no) video=false ;;
|
||||
|
|
|
|||
|
|
@ -515,7 +515,7 @@ lpc_cmd_help(LinphoneCore *lc, char *arg)
|
|||
i=0;
|
||||
while (advanced_commands[i].help)
|
||||
{
|
||||
linphonec_out("%10.10s\t%s\n", advanced_commands[i].name,
|
||||
linphonec_out("%20.20s\t%s\n", advanced_commands[i].name,
|
||||
advanced_commands[i].help);
|
||||
i++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -747,7 +747,7 @@ linphonec_init(int argc, char **argv)
|
|||
linphone_core_enable_video_display(linphonec, display_enabled);
|
||||
if (display_enabled && window_id != 0)
|
||||
{
|
||||
printf ("Setting window_id: 0x%x\n", window_id);
|
||||
printf("Setting window_id: 0x%x\n", window_id);
|
||||
linphone_core_set_native_video_window_id(linphonec,window_id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,47 +1,30 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
if(MSVC)
|
||||
find_library(LIBGCC NAMES gcc)
|
||||
find_library(LIBMINGWEX NAMES mingwex)
|
||||
endif()
|
||||
find_library(LIBORTP NAMES ortp)
|
||||
find_library(LIBMEDIASTREAMER_BASE NAMES mediastreamer_base)
|
||||
find_library(LIBMEDIASTREAMER_VOIP NAMES mediastreamer_voip)
|
||||
find_library(LIBBELLESIP NAMES bellesip)
|
||||
find_library(LIBXML2 NAMES xml2)
|
||||
|
||||
find_program(GIT git)
|
||||
|
||||
set(GIT_VERSION "unknown")
|
||||
if(GIT)
|
||||
execute_process(
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${GIT} describe --always
|
||||
OUTPUT_VARIABLE GIT_DESCRIBE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${GIT} describe --abbrev=0
|
||||
OUTPUT_VARIABLE GIT_TAG
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${GIT} rev-parse HEAD
|
||||
OUTPUT_VARIABLE GIT_REVISION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(GIT_DESCRIBE)
|
||||
set(GIT_VERSION ${GIT_DESCRIBE})
|
||||
else(GIT_DESCRIBE)
|
||||
if(GIT_REVISION)
|
||||
set(GIT_VERSION ${GIT_REVISION})
|
||||
endif(GIT_REVISION)
|
||||
endif(GIT_DESCRIBE)
|
||||
endif(GIT)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_VERSION}\""
|
||||
OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
address.c
|
||||
|
|
@ -68,7 +51,6 @@ set(SOURCE_FILES
|
|||
info.c
|
||||
linphonecall.c
|
||||
linphonecore.c
|
||||
#linphone_tunnel.cc
|
||||
linphone_tunnel_stubs.c
|
||||
linphone_tunnel_config.c
|
||||
lpconfig.c
|
||||
|
|
@ -83,7 +65,6 @@ set(SOURCE_FILES
|
|||
sal.c
|
||||
siplogin.c
|
||||
sipsetup.c
|
||||
#TunnelManager.cc
|
||||
xml.c
|
||||
xml2lpc.c
|
||||
bellesip_sal/sal_impl.h
|
||||
|
|
@ -99,42 +80,63 @@ set(SOURCE_FILES
|
|||
sipsetup.h
|
||||
xml2lpc.h
|
||||
)
|
||||
if(ENABLE_TUNNEL)
|
||||
list(APPEND SOURCE_FILES
|
||||
linphone_tunnel.cc
|
||||
TunnelManager.cc
|
||||
)
|
||||
add_definitions(-DTUNNEL_ENABLED)
|
||||
endif()
|
||||
|
||||
set(GENERATED_SOURCE_FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
|
||||
)
|
||||
set_source_files_properties(${GENERATED_SOURCE_FILES} PROPERTIES GENERATED TRUE)
|
||||
find_package(Git)
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
|
||||
COMMAND ${CMAKE_COMMAND} -DGIT_EXECUTABLE=${GIT_EXECUTABLE} -DWORK_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/gitversion.cmake)
|
||||
|
||||
add_definitions(
|
||||
-D_TRUE_TIME
|
||||
-DIN_LINPHONE
|
||||
-DUSE_BELLESIP
|
||||
#-DTUNNEL_ENABLED
|
||||
-DLINPHONE_PACKAGE_NAME="linphone"
|
||||
-DLINPHONE_VERSION="Devel"
|
||||
-DLIBLINPHONE_EXPORTS
|
||||
-DLINPHONE_PLUGINS_DIR=""
|
||||
)
|
||||
|
||||
if(LINPHONE_ENABLE_VIDEO)
|
||||
if(ENABLE_VIDEO)
|
||||
add_definitions(-DVIDEO_ENABLED)
|
||||
endif(LINPHONE_ENABLE_VIDEO)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(
|
||||
-DWINDOW_NATIVE
|
||||
/FIliblinphone_gitversion.h
|
||||
set(LIBS
|
||||
${LIBGCC}
|
||||
${LIBMINGWEX}
|
||||
${BELLESIP_LIBRARIES}
|
||||
${MS2_LIBRARIES}
|
||||
${XML2_LIBRARIES}
|
||||
)
|
||||
|
||||
set(LIBS ws2_32)
|
||||
endif(WIN32)
|
||||
set(LIBS ${LIBS} ${LIBGCC} ${LIBMINGWEX} ${LIBORTP} ${LIBMEDIASTREAMER_BASE} ${LIBMEDIASTREAMER_VOIP} ${LIBBELLESIP} ${LIBXML2})
|
||||
|
||||
add_library(linphone SHARED ${SOURCE_FILES})
|
||||
set_target_properties(linphone PROPERTIES VERSION 3.7.0 SOVERSION 5)
|
||||
|
||||
target_link_libraries(linphone ${LIBS})
|
||||
if(ENABLE_STATIC)
|
||||
add_library(linphone STATIC ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
|
||||
target_link_libraries(linphone ${LIBS})
|
||||
else()
|
||||
add_library(linphone SHARED ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
|
||||
set_target_properties(linphone PROPERTIES VERSION ${LINPHONE_VERSION} SOVERSION ${LINPHONE_SO_VERSION} LINKER_LANGUAGE CXX)
|
||||
target_link_libraries(linphone ${LIBS})
|
||||
if(MSVC)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/linphone.pdb
|
||||
DESTINATION bin
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
install(TARGETS linphone
|
||||
RUNTIME DESTINATION bin
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
|
||||
|
||||
file(GLOB HEADER_FILES "*.h")
|
||||
|
|
@ -143,11 +145,5 @@ install(FILES ${HEADER_FILES}
|
|||
DESTINATION include/linphone
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
)
|
||||
if(WIN32)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/linphone.pdb
|
||||
DESTINATION bin
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
endif()
|
||||
endif(WIN32)
|
||||
|
||||
add_subdirectory(help)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@ GITDESCRIBE=`cd $(top_srcdir) && git describe --always`
|
|||
GIT_TAG=`cd $(top_srcdir) && git describe --abbrev=0`
|
||||
GITREVISION=`cd $(top_srcdir) && git rev-parse HEAD`
|
||||
|
||||
## This command is used to check if the sources are cloned in a git repo.
|
||||
## We can't only depend on the presence of the .git/ directory anymore,
|
||||
## because of gits submodule handling.
|
||||
## We now simply issue a git log on configure.ac and if the output is empty (error or file not tracked), then we are not in git.
|
||||
GITLOG=$(shell git log -1 $(top_srcdir)/configure.ac)
|
||||
|
||||
ECHO=/bin/echo
|
||||
|
||||
SUBDIRS=. help
|
||||
|
|
@ -130,7 +136,7 @@ test_numbers_LDADD=liblinphone.la $(liblinphone_la_LIBADD)
|
|||
endif
|
||||
|
||||
AM_CPPFLAGS=\
|
||||
-I$(top_srcdir) -I$(top_srcdir)/include
|
||||
-I$(top_srcdir) -I$(top_srcdir)/include -I$(builddir)
|
||||
|
||||
AM_CFLAGS=\
|
||||
$(STRICT_OPTIONS) -DIN_LINPHONE \
|
||||
|
|
@ -161,27 +167,27 @@ AM_CXXFLAGS=$(AM_CFLAGS)
|
|||
#the PACKAGE_VERSION given in configure.ac
|
||||
|
||||
make_gitversion_h:
|
||||
if test -d $(top_srcdir)/.git ; then \
|
||||
if test -n "$(GITLOG)" ; then \
|
||||
if test "$(GITDESCRIBE)" != "" ; then \
|
||||
if test "$(GIT_TAG)" != "$(PACKAGE_VERSION)" ; then \
|
||||
echo "*** PACKAGE_VERSION and git tag differ. Please put them identical."; \
|
||||
exit 1; \
|
||||
fi ; \
|
||||
$(ECHO) -n "#define LIBLINPHONE_GIT_VERSION \"$(GITDESCRIBE)\"" > $(GITVERSION_FILE_TMP) ; \
|
||||
$(ECHO) -n "#define LIBLINPHONE_GIT_VERSION \"$(GITDESCRIBE)\"" > $(builddir)/$(GITVERSION_FILE_TMP) ; \
|
||||
elif test "$(GITREVISION)" != "" ; then \
|
||||
$(ECHO) -n "#define LIBLINPHONE_GIT_VERSION \"$(LINPHONE_VERSION)_$(GITREVISION)\"" > $(GITVERSION_FILE_TMP) ; \
|
||||
$(ECHO) -n "#define LIBLINPHONE_GIT_VERSION \"$(LINPHONE_VERSION)_$(GITREVISION)\"" > $(builddir)/$(GITVERSION_FILE_TMP) ; \
|
||||
else \
|
||||
$(ECHO) -n "" > $(GITVERSION_FILE_TMP) ; \
|
||||
$(ECHO) -n "" > $(builddir)/$(GITVERSION_FILE_TMP) ; \
|
||||
fi ; \
|
||||
else \
|
||||
$(ECHO) -n "" > $(GITVERSION_FILE_TMP) ; \
|
||||
$(ECHO) -n "" > $(builddir)/$(GITVERSION_FILE_TMP) ; \
|
||||
fi
|
||||
if ! test -f $(srcdir)/$(GITVERSION_FILE) ; then \
|
||||
cp -f $(srcdir)/$(GITVERSION_FILE_TMP) $(srcdir)/$(GITVERSION_FILE) ; \
|
||||
if ! test -f $(builddir)/$(GITVERSION_FILE) ; then \
|
||||
cp -f $(builddir)/$(GITVERSION_FILE_TMP) $(builddir)/$(GITVERSION_FILE) ; \
|
||||
fi
|
||||
if test "`cat $(GITVERSION_FILE_TMP)`" != "`cat $(srcdir)/$(GITVERSION_FILE)`" ; then \
|
||||
cp -f $(GITVERSION_FILE_TMP) $(srcdir)/$(GITVERSION_FILE) ; \
|
||||
if test "`cat $(builddir)/$(GITVERSION_FILE_TMP)`" != "`cat $(builddir)/$(GITVERSION_FILE)`" ; then \
|
||||
cp -f $(builddir)/$(GITVERSION_FILE_TMP) $(builddir)/$(GITVERSION_FILE) ; \
|
||||
fi
|
||||
rm -f $(GITVERSION_FILE_TMP) ;
|
||||
rm -f $(builddir)/$(GITVERSION_FILE_TMP) ;
|
||||
|
||||
$(GITVERSION_FILE): make_gitversion_h
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddr
|
|||
|
||||
/**
|
||||
* Destroys a LinphoneAddress object (actually calls linphone_address_unref()).
|
||||
* @deprecated Use linphone_address_unref() instead
|
||||
**/
|
||||
void linphone_address_destroy(LinphoneAddress *u){
|
||||
sal_address_unref(u);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include "lpconfig.h"
|
||||
|
|
@ -31,20 +31,6 @@
|
|||
* @{
|
||||
**/
|
||||
|
||||
/**
|
||||
* Create a LinphoneAuthInfo object with supplied information.
|
||||
* The object can be created empty, that is with all arguments set to NULL.
|
||||
* Username, userid, password, realm and domain can be set later using specific methods.
|
||||
* At the end, username and passwd (or ha1) are required.
|
||||
* @param username the username that needs to be authenticated
|
||||
* @param userid the userid used for authenticating (use NULL if you don't know what it is)
|
||||
* @param passwd the password in clear text
|
||||
* @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. 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().
|
||||
**/
|
||||
LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain){
|
||||
LinphoneAuthInfo *obj=ms_new0(LinphoneAuthInfo,1);
|
||||
if (username!=NULL && (strlen(username)>0) ) obj->username=ms_strdup(username);
|
||||
|
|
@ -67,16 +53,10 @@ LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){
|
|||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns username.
|
||||
**/
|
||||
const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i){
|
||||
return i->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns password.
|
||||
**/
|
||||
const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i){
|
||||
return i->passwd;
|
||||
}
|
||||
|
|
@ -97,9 +77,6 @@ const char *linphone_auth_info_get_ha1(const LinphoneAuthInfo *i){
|
|||
return i->ha1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
**/
|
||||
void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd){
|
||||
if (info->passwd!=NULL) {
|
||||
ms_free(info->passwd);
|
||||
|
|
@ -108,9 +85,6 @@ void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd){
|
|||
if (passwd!=NULL && (strlen(passwd)>0)) info->passwd=ms_strdup(passwd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username.
|
||||
**/
|
||||
void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *username){
|
||||
if (info->username){
|
||||
ms_free(info->username);
|
||||
|
|
@ -119,9 +93,6 @@ void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *usernam
|
|||
if (username && strlen(username)>0) info->username=ms_strdup(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets userid.
|
||||
**/
|
||||
void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid){
|
||||
if (info->userid){
|
||||
ms_free(info->userid);
|
||||
|
|
@ -130,9 +101,6 @@ void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid){
|
|||
if (userid && strlen(userid)>0) info->userid=ms_strdup(userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set realm.
|
||||
**/
|
||||
void linphone_auth_info_set_realm(LinphoneAuthInfo *info, const char *realm){
|
||||
if (info->realm){
|
||||
ms_free(info->realm);
|
||||
|
|
@ -141,10 +109,6 @@ void linphone_auth_info_set_realm(LinphoneAuthInfo *info, const char *realm){
|
|||
if (realm && strlen(realm)>0) info->realm=ms_strdup(realm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set domain for which this authentication is valid. This should not be necessary because realm is supposed to be unique and sufficient.
|
||||
* However, many SIP servers don't set realm correctly, then domain has to be used to distinguish between several SIP account bearing the same username.
|
||||
**/
|
||||
void linphone_auth_info_set_domain(LinphoneAuthInfo *info, const char *domain){
|
||||
if (info->domain){
|
||||
ms_free(info->domain);
|
||||
|
|
@ -153,9 +117,6 @@ void linphone_auth_info_set_domain(LinphoneAuthInfo *info, const char *domain){
|
|||
if (domain && strlen(domain)>0) info->domain=ms_strdup(domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets ha1.
|
||||
**/
|
||||
void linphone_auth_info_set_ha1(LinphoneAuthInfo *info, const char *ha1){
|
||||
if (info->ha1){
|
||||
ms_free(info->ha1);
|
||||
|
|
@ -182,7 +143,7 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in
|
|||
char key[50];
|
||||
sprintf(key,"auth_info_%i",pos);
|
||||
lp_config_clean_section(config,key);
|
||||
|
||||
|
||||
if (obj==NULL || lp_config_get_int(config, "sip", "store_auth_info", 1) == 0){
|
||||
return;
|
||||
}
|
||||
|
|
@ -215,12 +176,12 @@ LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int
|
|||
char key[50];
|
||||
const char *username,*userid,*passwd,*ha1,*realm,*domain;
|
||||
LinphoneAuthInfo *ret;
|
||||
|
||||
|
||||
sprintf(key,"auth_info_%i",pos);
|
||||
if (!lp_config_has_section(config,key)){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
username=lp_config_get_string(config,key,"username",NULL);
|
||||
userid=lp_config_get_string(config,key,"userid",NULL);
|
||||
passwd=lp_config_get_string(config,key,"passwd",NULL);
|
||||
|
|
@ -260,7 +221,7 @@ static int realm_match(const char *realm1, const char *realm2){
|
|||
static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain){
|
||||
MSList *elem;
|
||||
const LinphoneAuthInfo *ret=NULL;
|
||||
|
||||
|
||||
for (elem=lc->auth_info;elem!=NULL;elem=elem->next) {
|
||||
LinphoneAuthInfo *pinfo = (LinphoneAuthInfo*)elem->data;
|
||||
if (username && pinfo->username && strcmp(username,pinfo->username)==0) {
|
||||
|
|
@ -279,7 +240,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user
|
|||
}
|
||||
} else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0) {
|
||||
return pinfo;
|
||||
} else if (!domain) {
|
||||
} else if (!domain) {
|
||||
return pinfo;
|
||||
}
|
||||
}
|
||||
|
|
@ -288,7 +249,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user
|
|||
}
|
||||
|
||||
/**
|
||||
* Find authentication info matching realm, username, domain criterias.
|
||||
* Find authentication info matching realm, username, domain criteria.
|
||||
* First of all, (realm,username) pair are searched. If multiple results (which should not happen because realm are supposed to be unique), then domain is added to the search.
|
||||
* @param lc the LinphoneCore
|
||||
* @param realm the authentication 'realm' (optional)
|
||||
|
|
@ -303,7 +264,7 @@ const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const cha
|
|||
if (ai==NULL && domain){
|
||||
ai=find_auth_info(lc,username,realm,domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ai == NULL && domain != NULL) {
|
||||
ai=find_auth_info(lc,username,NULL,domain);
|
||||
}
|
||||
|
|
@ -331,8 +292,8 @@ LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char *
|
|||
|
||||
/**
|
||||
* Adds authentication information to the LinphoneCore.
|
||||
*
|
||||
* This information will be used during all SIP transacations that require authentication.
|
||||
*
|
||||
* This information will be used during all SIP transactions that require authentication.
|
||||
**/
|
||||
void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){
|
||||
LinphoneAuthInfo *ai;
|
||||
|
|
@ -340,7 +301,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
|
|||
MSList *l;
|
||||
int restarted_op_count=0;
|
||||
bool_t updating=FALSE;
|
||||
|
||||
|
||||
if (info->ha1==NULL && info->passwd==NULL){
|
||||
ms_error("linphone_core_add_auth_info(): info supplied with empty password or ha1.");
|
||||
return;
|
||||
|
|
@ -410,7 +371,6 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
|
|||
r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
|
||||
if (r){
|
||||
lc->auth_info=ms_list_remove(lc->auth_info,r);
|
||||
/*printf("len=%i newlen=%i\n",len,newlen);*/
|
||||
linphone_auth_info_destroy(r);
|
||||
write_auth_infos(lc);
|
||||
}
|
||||
|
|
@ -418,6 +378,8 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
|
|||
|
||||
/**
|
||||
* Returns an unmodifiable list of currently entered LinphoneAuthInfo.
|
||||
* @param[in] lc The LinphoneCore object
|
||||
* @return \mslist{LinphoneAuthInfo}
|
||||
**/
|
||||
const MSList *linphone_core_get_auth_info_list(const LinphoneCore *lc){
|
||||
return lc->auth_info;
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ void sal_process_authentication(SalOp *op) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list)) {
|
||||
if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list,op->base.realm)) {
|
||||
if (is_within_dialog) {
|
||||
sal_op_send_request(op,new_request);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ static void add_initial_route_set(belle_sip_request_t *request, const MSList *li
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
route=belle_sip_header_route_create((belle_sip_header_address_t*)addr);
|
||||
uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route);
|
||||
belle_sip_uri_set_lr_param(uri,1);
|
||||
|
|
@ -180,11 +180,11 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
|
|||
belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity));
|
||||
}
|
||||
|
||||
|
||||
if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){
|
||||
add_initial_route_set(req,elem);
|
||||
}
|
||||
|
||||
|
||||
if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){
|
||||
belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new();
|
||||
if (op->privacy&SalPrivacyCritical)
|
||||
|
|
@ -332,7 +332,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
|
|||
if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION)
|
||||
&& !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) {
|
||||
/*hmm just in case we already have authentication param in cache*/
|
||||
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL);
|
||||
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL,op->base.realm);
|
||||
}
|
||||
result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/);
|
||||
|
||||
|
|
@ -608,7 +608,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp
|
|||
belle_sip_object_unref(op->refresher);
|
||||
}
|
||||
if ((op->refresher = belle_sip_client_transaction_create_refresher(op->pending_client_trans))) {
|
||||
/*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified
|
||||
/*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified
|
||||
* that it is terminated anymore.*/
|
||||
sal_op_unref(op);/*loose the reference that was given to the transaction when creating it*/
|
||||
/* Note that the refresher will replace our data with belle_sip_transaction_set_application_data().
|
||||
|
|
@ -617,6 +617,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp
|
|||
notify the user as a normal transaction*/
|
||||
belle_sip_refresher_set_listener(op->refresher,listener,op);
|
||||
belle_sip_refresher_set_retry_after(op->refresher,op->base.root->refresher_retry_after);
|
||||
belle_sip_refresher_set_realm(op->refresher,op->base.realm);
|
||||
belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher);
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceMo
|
|||
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE);
|
||||
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH);
|
||||
belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),NULL,0);
|
||||
|
||||
|
||||
if (content){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml")));
|
||||
|
|
@ -95,7 +95,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
|
|||
belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
int code = belle_sip_response_get_status_code(response);
|
||||
belle_sip_header_expires_t* expires;
|
||||
|
||||
|
||||
sal_op_set_error_info_from_response(op,response);
|
||||
|
||||
if (code>=300) {
|
||||
|
|
@ -127,6 +127,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
|
|||
if (expires>0){
|
||||
op->refresher=belle_sip_client_transaction_create_refresher(client_transaction);
|
||||
belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op);
|
||||
belle_sip_refresher_set_realm(op->refresher,op->base.realm);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -164,7 +165,7 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req
|
|||
return NULL;
|
||||
if (belle_sip_header_content_length_get_content_length(content_length) == 0)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (body==NULL) return NULL;
|
||||
|
||||
op->base.root->callbacks.parse_presence_requested(op,
|
||||
|
|
@ -181,7 +182,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){
|
|||
belle_sip_server_transaction_t* server_transaction=op->pending_server_trans;
|
||||
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
|
||||
SalSubscribeStatus sub_state;
|
||||
|
||||
|
||||
if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) {
|
||||
SalPresenceModel *presence_model = NULL;
|
||||
const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
|
||||
|
|
@ -194,7 +195,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){
|
|||
presence_model = process_presence_notification(op, req);
|
||||
if (presence_model != NULL || body==NULL) {
|
||||
/* Presence notification body parsed successfully. */
|
||||
|
||||
|
||||
resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */
|
||||
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
|
||||
} else if (body){
|
||||
|
|
@ -214,7 +215,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
|
|||
belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
|
||||
belle_sip_response_t* resp;
|
||||
const char *method=belle_sip_request_get_method(req);
|
||||
|
||||
|
||||
belle_sip_object_ref(server_transaction);
|
||||
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
|
||||
op->pending_server_trans=server_transaction;
|
||||
|
|
@ -256,7 +257,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
|
|||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
159
coreapi/chat.c
159
coreapi/chat.c
|
|
@ -46,12 +46,35 @@ const char *multipart_boundary=MULTIPART_BOUNDARY;
|
|||
static size_t linphone_chat_message_compute_filepart_header_size(const char *filename, const char *content_type) {
|
||||
return strlen(FILEPART_HEADER_1)+strlen(filename)+strlen(FILEPART_HEADER_2)+strlen(content_type)+strlen(FILEPART_HEADER_3);
|
||||
}
|
||||
static void process_io_error(void *data, const belle_sip_io_error_event_t *event){
|
||||
|
||||
static void process_io_error_upload(void *data, const belle_sip_io_error_event_t *event){
|
||||
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
|
||||
msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
|
||||
ms_error("I/O Error during file upload to %s - msg [%p] chat room[%p]", msg->chat_room->lc->file_transfer_server, msg, msg->chat_room);
|
||||
if (msg->cb) {
|
||||
msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
|
||||
}
|
||||
}
|
||||
static void process_auth_requested(void *data, belle_sip_auth_event_t *event){
|
||||
printf("We have a auth requested!\n");
|
||||
static void process_auth_requested_upload(void *data, belle_sip_auth_event_t *event){
|
||||
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
|
||||
ms_error("Error during file upload : auth requested to connect %s - msg [%p] chat room[%p]", msg->chat_room->lc->file_transfer_server, msg, msg->chat_room);
|
||||
if (msg->cb) {
|
||||
msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_io_error_download(void *data, const belle_sip_io_error_event_t *event){
|
||||
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
|
||||
ms_error("I/O Error during file download %s - msg [%p] chat room[%p]", msg->external_body_url, msg, msg->chat_room);
|
||||
if (msg->cb) {
|
||||
msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->chat_room->lc);
|
||||
}
|
||||
}
|
||||
static void process_auth_requested_download(void *data, belle_sip_auth_event_t *event){
|
||||
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
|
||||
ms_error("Error during file download : auth requested to get %s - msg [%p] chat room[%p]", msg->external_body_url, msg, msg->chat_room);
|
||||
if (msg->cb) {
|
||||
msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->chat_room->lc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -132,7 +155,9 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
|
|||
char *content_type=belle_sip_strdup_printf("%s/%s", msg->file_transfer_information->type, msg->file_transfer_information->subtype);
|
||||
|
||||
/* create a user body handler to take care of the file */
|
||||
belle_sip_user_body_handler_t *first_part_bh=belle_sip_user_body_handler_new(msg->file_transfer_information->size+linphone_chat_message_compute_filepart_header_size(msg->file_transfer_information->name, content_type), NULL, NULL, linphone_chat_message_file_transfer_on_send_body, msg);
|
||||
size_t body_size = msg->file_transfer_information->size+linphone_chat_message_compute_filepart_header_size(msg->file_transfer_information->name, content_type);
|
||||
|
||||
belle_sip_user_body_handler_t *first_part_bh=belle_sip_user_body_handler_new(body_size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg);
|
||||
/* insert it in a multipart body handler which will manage the boundaries of multipart message */
|
||||
belle_sip_multipart_body_handler_t *bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, (belle_sip_body_handler_t *)first_part_bh);
|
||||
|
||||
|
|
@ -152,13 +177,19 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
|
|||
belle_sip_free(content_type);
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req),BELLE_SIP_BODY_HANDLER(bh));
|
||||
cbs.process_response=linphone_chat_message_process_response_from_post_file;
|
||||
cbs.process_io_error=process_io_error;
|
||||
cbs.process_auth_requested=process_auth_requested;
|
||||
cbs.process_io_error=process_io_error_upload;
|
||||
cbs.process_auth_requested=process_auth_requested_upload;
|
||||
l=belle_http_request_listener_create_from_callbacks(&cbs,msg);
|
||||
msg->http_request=req; /* update the reference to the http request to be able to cancel it during upload */
|
||||
belle_http_provider_send_request(msg->chat_room->lc->http_provider,req,l);
|
||||
}
|
||||
if (code == 200 ) { /* file has been uplaoded correctly, get server reply and send it */
|
||||
const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
|
||||
if (code == 200 ) { /* file has been uploaded correctly, get server reply and send it */
|
||||
const char *body;
|
||||
/* TODO Check that the transfer has not been cancelled, note this shall be removed once the belle sip API will provide a cancel request as we shall never reach this part if the transfer is actually cancelled */
|
||||
if (msg->http_request == NULL) {
|
||||
return;
|
||||
}
|
||||
body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
|
||||
msg->message = ms_strdup(body);
|
||||
linphone_content_uninit(msg->file_transfer_information);
|
||||
ms_free(msg->file_transfer_information);
|
||||
|
|
@ -215,8 +246,8 @@ bool_t linphone_core_chat_enabled(const LinphoneCore *lc){
|
|||
|
||||
/**
|
||||
* Returns an list of chat rooms
|
||||
* @param lc #LinphoneCore object
|
||||
* @return A list of #LinphoneChatRoom
|
||||
* @param[in] lc #LinphoneCore object
|
||||
* @return \mslist{LinphoneChatRoom}
|
||||
**/
|
||||
MSList* linphone_core_get_chat_rooms(LinphoneCore *lc) {
|
||||
return lc->chatrooms;
|
||||
|
|
@ -270,7 +301,8 @@ LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const
|
|||
|
||||
static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) {
|
||||
if (cr->composing_idle_timer) {
|
||||
sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer);
|
||||
if(cr->lc->sal)
|
||||
sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer);
|
||||
belle_sip_object_unref(cr->composing_idle_timer);
|
||||
cr->composing_idle_timer = NULL;
|
||||
}
|
||||
|
|
@ -278,7 +310,8 @@ static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr)
|
|||
|
||||
static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr) {
|
||||
if (cr->composing_refresh_timer) {
|
||||
sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer);
|
||||
if(cr->lc->sal)
|
||||
sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer);
|
||||
belle_sip_object_unref(cr->composing_refresh_timer);
|
||||
cr->composing_refresh_timer = NULL;
|
||||
}
|
||||
|
|
@ -286,7 +319,8 @@ static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *
|
|||
|
||||
static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) {
|
||||
if (cr->remote_composing_refresh_timer) {
|
||||
sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer);
|
||||
if(cr->lc->sal)
|
||||
sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer);
|
||||
belle_sip_object_unref(cr->remote_composing_refresh_timer);
|
||||
cr->remote_composing_refresh_timer = NULL;
|
||||
}
|
||||
|
|
@ -333,9 +367,10 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
|
|||
NULL,
|
||||
NULL);
|
||||
cbs.process_response=linphone_chat_message_process_response_from_post_file;
|
||||
cbs.process_io_error=process_io_error;
|
||||
cbs.process_auth_requested=process_auth_requested;
|
||||
cbs.process_io_error=process_io_error_upload;
|
||||
cbs.process_auth_requested=process_auth_requested_upload;
|
||||
l=belle_http_request_listener_create_from_callbacks(&cbs,msg); /* give msg to listener to be able to start the actual file upload when server answer a 204 No content */
|
||||
msg->http_request = req; /* keep a reference on the request to be able to cancel it */
|
||||
belle_http_provider_send_request(cr->lc->http_provider,req,l);
|
||||
linphone_chat_message_unref(msg);
|
||||
return;
|
||||
|
|
@ -369,8 +404,8 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
|
|||
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);
|
||||
ms_free(content_type);
|
||||
} else {
|
||||
if (msg->content_type == NULL) {
|
||||
} else { /* the message is either text or have a file transfer using RCS recommendation */
|
||||
if (msg->content_type == NULL) { /* if no content type is specified, it is a text message */
|
||||
sal_text_send(op, identity, cr->peer,msg->message);
|
||||
} else {
|
||||
sal_message_send(op, identity, cr->peer, msg->content_type, msg->message);
|
||||
|
|
@ -448,7 +483,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
|
|||
/* create a new chat room */
|
||||
cr=linphone_core_create_chat_room(lc,cleanfrom);
|
||||
}
|
||||
if (sal_msg->content_type != NULL) { /* content_type field is, for now, used only for rcs file transfer bu twe shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */
|
||||
if (sal_msg->content_type != NULL) { /* content_type field is, for now, used only for rcs file transfer but we shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */
|
||||
xmlChar *file_url = NULL;
|
||||
xmlDocPtr xmlMessageBody;
|
||||
xmlNodePtr cur;
|
||||
|
|
@ -666,6 +701,7 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con
|
|||
msg->is_read=TRUE;
|
||||
msg->content_type = NULL; /* this property is used only when transfering file */
|
||||
msg->file_transfer_information = NULL; /* this property is used only when transfering file */
|
||||
msg->http_request = NULL;
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
|
@ -855,6 +891,7 @@ const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState
|
|||
case LinphoneChatMessageStateInProgress:return "LinphoneChatMessageStateInProgress";
|
||||
case LinphoneChatMessageStateDelivered:return "LinphoneChatMessageStateDelivered";
|
||||
case LinphoneChatMessageStateNotDelivered:return "LinphoneChatMessageStateNotDelivered";
|
||||
case LinphoneChatMessageStateFileTransferError:return "LinphoneChatMessageStateFileTransferError";
|
||||
default: return "Unknown state";
|
||||
}
|
||||
|
||||
|
|
@ -951,18 +988,44 @@ const LinphoneContent *linphone_chat_message_get_file_transfer_information(const
|
|||
}
|
||||
|
||||
static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *msg, void *data, size_t offset, const uint8_t *buffer, size_t size){
|
||||
//printf("Receive %ld bytes\n\n%s\n\n", size, (char *)buffer);
|
||||
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
|
||||
LinphoneCore *lc = chatMsg->chat_room->lc;
|
||||
/* TODO: while belle sip doesn't implement the cancel http request method, test if a request is still linked to the message before forwarding the data to callback */
|
||||
if (chatMsg->http_request == NULL) {
|
||||
return;
|
||||
}
|
||||
/* call back given by application level */
|
||||
if (lc->vtable.file_transfer_received != NULL) {
|
||||
lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size);
|
||||
if (lc->vtable.file_transfer_recv != NULL) {
|
||||
lc->vtable.file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size);
|
||||
}
|
||||
return;
|
||||
|
||||
/* feed the callback with the received data */
|
||||
}
|
||||
|
||||
|
||||
static LinphoneContent* linphone_chat_create_file_transfer_information_from_headers(const belle_sip_message_t* message ){
|
||||
LinphoneContent *content = ms_malloc0(sizeof(LinphoneContent));
|
||||
|
||||
belle_sip_header_content_length_t* content_length_hdr = BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(message, "Content-Length"));
|
||||
belle_sip_header_content_type_t* content_type_hdr = BELLE_SIP_HEADER_CONTENT_TYPE(belle_sip_message_get_header(message, "Content-Type"));
|
||||
const char* type = NULL,*subtype = NULL;
|
||||
|
||||
content->name = ms_strdup("");
|
||||
|
||||
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 ) content->type = ms_strdup(type);
|
||||
if( subtype ) content->type = ms_strdup(subtype);
|
||||
}
|
||||
|
||||
if( content_length_hdr ){
|
||||
content->size = belle_sip_header_content_length_get_content_length(content_length_hdr);
|
||||
ms_message("Extracted content length %i from header", (int)content->size);
|
||||
}
|
||||
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
static void linphone_chat_process_response_headers_from_get_file(void *data, const belle_http_response_event_t *event){
|
||||
|
|
@ -970,9 +1033,21 @@ static void linphone_chat_process_response_headers_from_get_file(void *data, con
|
|||
/*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*/
|
||||
LinphoneChatMessage *message=(LinphoneChatMessage *)belle_sip_object_data_get(BELLE_SIP_OBJECT(event->request),"message");
|
||||
belle_sip_message_t* response = BELLE_SIP_MESSAGE(event->response);
|
||||
size_t body_size = 0;
|
||||
|
||||
if( message->file_transfer_information == NULL ){
|
||||
ms_warning("No file transfer information for message %p: creating...", message);
|
||||
message->file_transfer_information = linphone_chat_create_file_transfer_information_from_headers(response);
|
||||
}
|
||||
|
||||
if( message->file_transfer_information ){
|
||||
body_size = message->file_transfer_information->size;
|
||||
}
|
||||
|
||||
belle_sip_message_set_body_handler(
|
||||
(belle_sip_message_t*)event->response,
|
||||
(belle_sip_body_handler_t*)belle_sip_user_body_handler_new(message->file_transfer_information->size, linphone_chat_message_file_transfer_on_progress,on_recv_body,NULL,message)
|
||||
(belle_sip_body_handler_t*)belle_sip_user_body_handler_new(body_size, linphone_chat_message_file_transfer_on_progress,on_recv_body,NULL,message)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -987,8 +1062,8 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
|
|||
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
|
||||
LinphoneCore *lc = chatMsg->chat_room->lc;
|
||||
/* file downloaded succesfully, call again the callback with size at zero */
|
||||
if (lc->vtable.file_transfer_received != NULL) {
|
||||
lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
|
||||
if (lc->vtable.file_transfer_recv != NULL) {
|
||||
lc->vtable.file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -998,8 +1073,9 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
|
|||
* Start the download of the file from remote server
|
||||
*
|
||||
* @param message #LinphoneChatMessage
|
||||
* @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when file is downloaded or could not be downloaded
|
||||
*/
|
||||
void linphone_chat_message_start_file_download(const LinphoneChatMessage *message) {
|
||||
void linphone_chat_message_start_file_download(LinphoneChatMessage *message, LinphoneChatMessageStateChangedCb status_cb) {
|
||||
belle_http_request_listener_callbacks_t cbs={0};
|
||||
belle_http_request_listener_t *l;
|
||||
belle_generic_uri_t *uri;
|
||||
|
|
@ -1018,12 +1094,31 @@ void linphone_chat_message_start_file_download(const LinphoneChatMessage *messag
|
|||
|
||||
cbs.process_response_headers=linphone_chat_process_response_headers_from_get_file;
|
||||
cbs.process_response=linphone_chat_process_response_from_get_file;
|
||||
cbs.process_io_error=process_io_error;
|
||||
cbs.process_auth_requested=process_auth_requested;
|
||||
cbs.process_io_error=process_io_error_download;
|
||||
cbs.process_auth_requested=process_auth_requested_download;
|
||||
l=belle_http_request_listener_create_from_callbacks(&cbs, (void *)message);
|
||||
belle_sip_object_data_set(BELLE_SIP_OBJECT(req),"message",(void *)message,NULL);
|
||||
message->http_request = req; /* keep a reference on the request to be able to cancel the download */
|
||||
message->cb = status_cb;
|
||||
message->state = LinphoneChatMessageStateInProgress; /* start the download, status is In Progress */
|
||||
belle_http_provider_send_request(message->chat_room->lc->http_provider,req,l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel an ongoing file transfer attached to this message.(upload or download)
|
||||
* @param msg #LinphoneChatMessage
|
||||
*/
|
||||
void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage *msg) {
|
||||
ms_message("Cancelled file transfer %s - msg [%p] chat room[%p]", (msg->external_body_url==NULL)?msg->chat_room->lc->file_transfer_server:msg->external_body_url, msg, msg->chat_room);
|
||||
/* TODO: here we shall call the cancel http request from bellesip API when it is available passing msg->http_request */
|
||||
/* waiting for this API, just set to NULL the reference to the request in the message and any request */
|
||||
msg->http_request = NULL;
|
||||
if (msg->cb) {
|
||||
msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set origin of the message
|
||||
*@param message #LinphoneChatMessage obj
|
||||
|
|
@ -1251,11 +1346,11 @@ LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneCha
|
|||
linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr));
|
||||
linphone_chat_message_set_from(msg, linphone_address_new(linphone_core_get_identity(cr->lc)));
|
||||
msg->content_type=NULL; /* this will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */
|
||||
msg->http_request=NULL; /* this will store the http request during file upload to the server */
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
|||
39
coreapi/gitversion.cmake
Normal file
39
coreapi/gitversion.cmake
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
if(GIT_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --always
|
||||
WORKING_DIRECTORY ${WORK_DIR}
|
||||
OUTPUT_VARIABLE GIT_REVISION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_REVISION}\""
|
||||
OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h
|
||||
)
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"unknown\""
|
||||
OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h
|
||||
)
|
||||
endif()
|
||||
37
coreapi/help/CMakeLists.txt
Normal file
37
coreapi/help/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
if(DOXYGEN_DOT_FOUND)
|
||||
set(top_srcdir ${CMAKE_SOURCE_DIR})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
add_custom_target(doc ALL
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html" "${CMAKE_CURRENT_BINARY_DIR}/doc/xml"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/doc/linphone-${LINPHONE_VERSION}")
|
||||
else()
|
||||
message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.")
|
||||
endif()
|
||||
endif()
|
||||
|
|
@ -34,7 +34,7 @@ DETAILS_AT_TOP = NO
|
|||
INHERIT_DOCS = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
TAB_SIZE = 8
|
||||
ALIASES =
|
||||
ALIASES = mslist{1}="A list of \ref \1 objects. \xmlonly <mslist>\1</mslist> \endxmlonly"
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
SUBGROUPING = YES
|
||||
|
|
|
|||
|
|
@ -115,16 +115,6 @@ static void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message,
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* Call back called when a message is received
|
||||
*/
|
||||
static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
|
||||
const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg);
|
||||
printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, (long int)file_transfer_info->size);
|
||||
|
||||
linphone_chat_message_start_file_download(msg);
|
||||
|
||||
}
|
||||
/*
|
||||
* Call back to get delivery status of a message
|
||||
* */
|
||||
|
|
@ -136,6 +126,16 @@ static void linphone_file_transfer_state_changed(LinphoneChatMessage* msg,Linpho
|
|||
free(to);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call back called when a message is received
|
||||
*/
|
||||
static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
|
||||
const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg);
|
||||
printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, (long int)file_transfer_info->size);
|
||||
|
||||
linphone_chat_message_start_file_download(msg, linphone_file_transfer_state_changed);
|
||||
|
||||
}
|
||||
|
||||
LinphoneCore *lc;
|
||||
int main(int argc, char *argv[]){
|
||||
|
|
@ -162,7 +162,7 @@ int main(int argc, char *argv[]){
|
|||
in order to get notifications about incoming file receive, file_transfer_send to feed file to be transfered
|
||||
and file_transfer_progress_indication to print progress.
|
||||
*/
|
||||
vtable.file_transfer_received=file_transfer_received;
|
||||
vtable.file_transfer_recv=file_transfer_received;
|
||||
vtable.file_transfer_send=file_transfer_send;
|
||||
vtable.file_transfer_progress_indication=file_transfer_progress_indication;
|
||||
vtable.message_received=message_received;
|
||||
|
|
|
|||
|
|
@ -60,16 +60,19 @@ void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
|
|||
|
||||
static char *linphone_tunnel_config_to_string(const LinphoneTunnelConfig *tunnel_config) {
|
||||
char *str = NULL;
|
||||
if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) {
|
||||
str = ms_strdup_printf("%s:%d:%d:%d",
|
||||
linphone_tunnel_config_get_host(tunnel_config),
|
||||
linphone_tunnel_config_get_port(tunnel_config),
|
||||
linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config),
|
||||
linphone_tunnel_config_get_delay(tunnel_config));
|
||||
} else {
|
||||
str = ms_strdup_printf("%s:%d",
|
||||
linphone_tunnel_config_get_host(tunnel_config),
|
||||
linphone_tunnel_config_get_port(tunnel_config));
|
||||
const char *host = linphone_tunnel_config_get_host(tunnel_config);
|
||||
if(host != NULL) {
|
||||
if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) {
|
||||
str = ms_strdup_printf("%s:%d:%d:%d",
|
||||
linphone_tunnel_config_get_host(tunnel_config),
|
||||
linphone_tunnel_config_get_port(tunnel_config),
|
||||
linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config),
|
||||
linphone_tunnel_config_get_delay(tunnel_config));
|
||||
} else {
|
||||
str = ms_strdup_printf("%s:%d",
|
||||
linphone_tunnel_config_get_host(tunnel_config),
|
||||
linphone_tunnel_config_get_port(tunnel_config));
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
|
@ -124,20 +127,21 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str)
|
|||
|
||||
|
||||
static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) {
|
||||
MSList *elem = tunnel->config_list;
|
||||
MSList *elem = NULL;
|
||||
char *tmp = NULL, *old_tmp = NULL, *tc_str = NULL;
|
||||
while(elem != NULL) {
|
||||
for(elem = tunnel->config_list; elem != NULL; elem = elem->next) {
|
||||
LinphoneTunnelConfig *tunnel_config = (LinphoneTunnelConfig *)elem->data;
|
||||
tc_str = linphone_tunnel_config_to_string(tunnel_config);
|
||||
if(tmp != NULL) {
|
||||
old_tmp = tmp;
|
||||
tmp = ms_strdup_printf("%s %s", old_tmp, tc_str);
|
||||
ms_free(old_tmp);
|
||||
ms_free(tc_str);
|
||||
} else {
|
||||
tmp = tc_str;
|
||||
if(tc_str != NULL) {
|
||||
if(tmp != NULL) {
|
||||
old_tmp = tmp;
|
||||
tmp = ms_strdup_printf("%s %s", old_tmp, tc_str);
|
||||
ms_free(old_tmp);
|
||||
ms_free(tc_str);
|
||||
} else {
|
||||
tmp = tc_str;
|
||||
}
|
||||
}
|
||||
elem = elem->next;
|
||||
}
|
||||
lp_config_set_string(config(tunnel), "tunnel", "server_addresses", tmp);
|
||||
if(tmp != NULL) {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig;
|
|||
/**
|
||||
* Create a new tunnel configuration
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new();
|
||||
LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new(void);
|
||||
|
||||
/**
|
||||
* Set address of server.
|
||||
|
|
|
|||
|
|
@ -236,6 +236,14 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
|
|||
for(it=codecs;it!=NULL;it=it->next){
|
||||
PayloadType *pt=(PayloadType*)it->data;
|
||||
if (pt->flags & PAYLOAD_TYPE_ENABLED){
|
||||
int sample_rate = payload_type_get_rate(pt);
|
||||
|
||||
if( strcasecmp("G722",pt->mime_type) == 0 ){
|
||||
/* G722 spec says 8000 but the codec actually requires 16000 */
|
||||
ms_debug("Correcting sample rate for G722");
|
||||
sample_rate = 16000;
|
||||
}
|
||||
|
||||
if (bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,bandwidth_limit)){
|
||||
ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s",
|
||||
pt->mime_type,pt->clock_rate,bandwidth_limit);
|
||||
|
|
@ -244,7 +252,7 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
|
|||
if (linphone_core_check_payload_type_usability(lc,pt)){
|
||||
l=ms_list_append(l,payload_type_clone(pt));
|
||||
nb++;
|
||||
if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt);
|
||||
if (max_sample_rate && sample_rate>*max_sample_rate) *max_sample_rate=sample_rate;
|
||||
}
|
||||
}
|
||||
if ((nb_codecs_limit > 0) && (nb >= nb_codecs_limit)) break;
|
||||
|
|
@ -305,7 +313,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
|
|||
for(i=0; i<md->nb_streams; i++) {
|
||||
if (!sal_stream_description_active(&md->streams[i])) continue;
|
||||
if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) {
|
||||
if (keep_srtp_keys && old_md && sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE){
|
||||
if (keep_srtp_keys && old_md && (sal_stream_description_active(&old_md->streams[i]) == TRUE) && (sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE)) {
|
||||
int j;
|
||||
ms_message("Keeping same crypto keys.");
|
||||
for(j=0;j<SAL_CRYPTO_ALGO_MAX;++j){
|
||||
|
|
@ -701,7 +709,6 @@ void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, c
|
|||
|
||||
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
|
||||
LinphoneCall *call=ms_new0(LinphoneCall,1);
|
||||
char *from_str;
|
||||
const SalMediaDescription *md;
|
||||
LinphoneFirewallPolicy fpol;
|
||||
|
||||
|
|
@ -721,11 +728,13 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
/*the following sends an option request back to the caller so that
|
||||
we get a chance to discover our nat'd address before answering.*/
|
||||
call->ping_op=sal_op_new(lc->sal);
|
||||
from_str=linphone_address_as_string_uri_only(from);
|
||||
|
||||
linphone_configure_op(lc, call->ping_op, from, NULL, FALSE);
|
||||
|
||||
sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
|
||||
sal_op_set_user_pointer(call->ping_op,call);
|
||||
sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from),from_str);
|
||||
ms_free(from_str);
|
||||
|
||||
sal_ping(call->ping_op,sal_op_get_from(call->ping_op), sal_op_get_to(call->ping_op));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1145,7 +1154,7 @@ const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call){
|
|||
*
|
||||
* return user_pointer an opaque user pointer that can be retrieved at any time
|
||||
**/
|
||||
void *linphone_call_get_user_pointer(LinphoneCall *call)
|
||||
void *linphone_call_get_user_data(LinphoneCall *call)
|
||||
{
|
||||
return call->user_pointer;
|
||||
}
|
||||
|
|
@ -1157,7 +1166,7 @@ void *linphone_call_get_user_pointer(LinphoneCall *call)
|
|||
*
|
||||
* the user_pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall
|
||||
**/
|
||||
void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer)
|
||||
void linphone_call_set_user_data(LinphoneCall *call, void *user_pointer)
|
||||
{
|
||||
call->user_pointer = user_pointer;
|
||||
}
|
||||
|
|
@ -1278,11 +1287,14 @@ void linphone_call_enable_camera (LinphoneCall *call, bool_t enable){
|
|||
/**
|
||||
* Request remote side to send us a Video Fast Update.
|
||||
**/
|
||||
void linphone_call_send_vfu_request(LinphoneCall *call)
|
||||
{
|
||||
void linphone_call_send_vfu_request(LinphoneCall *call) {
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (LinphoneCallStreamsRunning == linphone_call_get_state(call))
|
||||
sal_call_send_vfu_request(call->op);
|
||||
if (call->core->sip_conf.vfu_with_info) {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -1310,7 +1322,7 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){
|
|||
* Note that the snapshot is asynchronous, an application shall not assume that the file is created when the function returns.
|
||||
* @param call a LinphoneCall
|
||||
* @param file a path where to write the jpeg content.
|
||||
* @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported).
|
||||
* @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported).
|
||||
**/
|
||||
int linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file){
|
||||
#ifdef VIDEO_ENABLED
|
||||
|
|
@ -1338,17 +1350,17 @@ void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the audio codec used in the call, described as a PayloadType structure.
|
||||
* Returns the audio codec used in the call, described as a LinphonePayloadType structure.
|
||||
**/
|
||||
const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
|
||||
const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
|
||||
return cp->audio_codec;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the video codec used in the call, described as a PayloadType structure.
|
||||
* Returns the video codec used in the call, described as a LinphonePayloadType structure.
|
||||
**/
|
||||
const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
|
||||
const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
|
||||
return cp->video_codec;
|
||||
}
|
||||
|
||||
|
|
@ -1575,12 +1587,18 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u
|
|||
LinphoneCall* call = (LinphoneCall*) user_pointer;
|
||||
switch (event_id) {
|
||||
case MS_VIDEO_DECODER_DECODING_ERRORS:
|
||||
ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS");
|
||||
ms_warning("MS_VIDEO_DECODER_DECODING_ERRORS");
|
||||
if (call->videostream && (video_stream_is_decoding_error_to_be_reported(call->videostream, 5000) == TRUE)) {
|
||||
video_stream_decoding_error_reported(call->videostream);
|
||||
linphone_call_send_vfu_request(call);
|
||||
}
|
||||
break;
|
||||
case MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS:
|
||||
ms_message("MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS");
|
||||
if (call->videostream) {
|
||||
video_stream_decoding_error_recovered(call->videostream);
|
||||
}
|
||||
break;
|
||||
case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
|
||||
ms_message("First video frame decoded successfully");
|
||||
if (call->nextVideoFrameDecoded._func != NULL)
|
||||
|
|
@ -1669,6 +1687,7 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
|
|||
void linphone_call_init_audio_stream(LinphoneCall *call){
|
||||
LinphoneCore *lc=call->core;
|
||||
AudioStream *audiostream;
|
||||
const char *location;
|
||||
int dscp;
|
||||
|
||||
if (call->audiostream != NULL) return;
|
||||
|
|
@ -1692,6 +1711,13 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
else if (strcasecmp(type,"full")==0)
|
||||
audio_stream_enable_echo_limiter(audiostream,ELControlFull);
|
||||
}
|
||||
|
||||
/* equalizer location in the graph: 'mic' = in input graph, otherwise in output graph.
|
||||
Any other value than mic will default to output graph for compatibility */
|
||||
location = lp_config_get_string(lc->config,"sound","eq_location","hp");
|
||||
audiostream->eq_loc = (strcasecmp(location,"mic") == 0) ? MSEqualizerMic : MSEqualizerHP;
|
||||
ms_error("Equalizer location: %s", location);
|
||||
|
||||
audio_stream_enable_gain_control(audiostream,TRUE);
|
||||
if (linphone_core_echo_cancellation_enabled(lc)){
|
||||
int len,delay,framesize;
|
||||
|
|
@ -2761,7 +2787,9 @@ uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCa
|
|||
* The call recording can be started and paused after the call is established with
|
||||
* linphone_call_start_recording() and linphone_call_pause_recording().
|
||||
* @param cp the call parameters
|
||||
* @param path path and filename of the file where audio is written.
|
||||
* @param path path and filename of the file where audio/video streams are written.
|
||||
* The filename must have either .mkv or .wav extention. The video stream will be written
|
||||
* only if a MKV file is given.
|
||||
**/
|
||||
void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){
|
||||
if (cp->record_file){
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ static const char *liblinphone_version=
|
|||
LIBLINPHONE_VERSION
|
||||
#endif
|
||||
;
|
||||
static bool_t liblinphone_serialize_logs = FALSE;
|
||||
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
|
||||
static void linphone_core_run_hooks(LinphoneCore *lc);
|
||||
static void linphone_core_free_hooks(LinphoneCore *lc);
|
||||
|
|
@ -75,10 +76,10 @@ static void linphone_core_free_hooks(LinphoneCore *lc);
|
|||
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
|
||||
static void toggle_video_preview(LinphoneCore *lc, bool_t val);
|
||||
|
||||
#ifdef WINAPI_FAMILY_PHONE_APP
|
||||
#define SOUNDS_PREFIX "Assets/Sounds/"
|
||||
#else
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
#define SOUNDS_PREFIX
|
||||
#else
|
||||
#define SOUNDS_PREFIX "Assets/Sounds/"
|
||||
#endif
|
||||
/* relative path where is stored local ring*/
|
||||
#define LOCAL_RING SOUNDS_PREFIX "rings/oldphone.wav"
|
||||
|
|
@ -287,14 +288,14 @@ const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){
|
|||
/**
|
||||
* Assign a user pointer to the call log.
|
||||
**/
|
||||
void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up){
|
||||
void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *up){
|
||||
cl->user_pointer=up;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user pointer associated with the call log.
|
||||
**/
|
||||
void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl){
|
||||
void *linphone_call_log_get_user_data(const LinphoneCallLog *cl){
|
||||
return cl->user_pointer;
|
||||
}
|
||||
|
||||
|
|
@ -480,11 +481,15 @@ void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
|
|||
* @ingroup misc
|
||||
* @deprecated Use #linphone_core_set_log_level instead.
|
||||
**/
|
||||
void linphone_core_disable_logs(){
|
||||
void linphone_core_disable_logs(void){
|
||||
ortp_set_log_level_mask(ORTP_ERROR|ORTP_FATAL);
|
||||
sal_disable_logs();
|
||||
}
|
||||
|
||||
void linphone_core_serialize_logs(void) {
|
||||
liblinphone_serialize_logs = TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void net_config_read (LinphoneCore *lc)
|
||||
{
|
||||
|
|
@ -755,6 +760,8 @@ static void sip_config_read(LinphoneCore *lc)
|
|||
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);
|
||||
linphone_core_set_sip_transport_timeout(lc, lp_config_get_int(lc->config, "sip", "transport_timeout", 63000));
|
||||
}
|
||||
|
||||
static void rtp_config_read(LinphoneCore *lc)
|
||||
|
|
@ -893,7 +900,7 @@ static int codec_compare(const PayloadType *a, const PayloadType *b){
|
|||
rb=find_codec_rank(b->mime_type,b->clock_rate);
|
||||
if (ra>rb) return 1;
|
||||
if (ra<rb) return -1;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static MSList *add_missing_codecs(LinphoneCore *lc, SalStreamType mtype, MSList *l){
|
||||
|
|
@ -997,10 +1004,10 @@ static void video_config_read(LinphoneCore *lc){
|
|||
|
||||
linphone_core_set_preferred_video_size_by_name(lc,
|
||||
lp_config_get_string(lc->config,"video","size","cif"));
|
||||
|
||||
|
||||
linphone_core_set_preview_video_size_by_name(lc,
|
||||
lp_config_get_string(lc->config,"video","preview_size",NULL));
|
||||
|
||||
|
||||
linphone_core_set_preferred_framerate(lc,lp_config_get_float(lc->config,"video","framerate",0));
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
|
|
@ -1114,6 +1121,16 @@ void linphone_core_set_upload_bandwidth(LinphoneCore *lc, int bw){
|
|||
if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"net","upload_bw",bw);
|
||||
}
|
||||
|
||||
void linphone_core_set_sip_transport_timeout(LinphoneCore *lc, int timeout_ms) {
|
||||
sal_set_transport_timeout(lc->sal, 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);
|
||||
}
|
||||
|
||||
void linphone_core_enable_dns_srv(LinphoneCore *lc, bool_t enable) {
|
||||
sal_enable_dns_srv(lc->sal, enable);
|
||||
if (linphone_core_ready(lc))
|
||||
|
|
@ -1319,6 +1336,9 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
|
||||
linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
|
||||
ortp_init();
|
||||
if (liblinphone_serialize_logs == TRUE) {
|
||||
ortp_set_log_thread_id(ortp_thread_self());
|
||||
}
|
||||
lc->dyn_pt=96;
|
||||
lc->default_profile=rtp_profile_new("default profile");
|
||||
linphone_core_assign_payload_type(lc,&payload_type_pcmu8000,0,NULL);
|
||||
|
|
@ -1405,7 +1425,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
remote_provisioning_uri = linphone_core_get_provisioning_uri(lc);
|
||||
if (remote_provisioning_uri == NULL) {
|
||||
linphone_configuring_terminated(lc, LinphoneConfiguringSkipped, NULL);
|
||||
} // else linphone_core_start will be called after the remote provisioining (see linphone_core_iterate)
|
||||
} // else linphone_core_start will be called after the remote provisioning (see linphone_core_iterate)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1446,6 +1466,8 @@ LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, st
|
|||
|
||||
/**
|
||||
* Returns the list of available audio codecs.
|
||||
* @param[in] lc The LinphoneCore object
|
||||
* @return \mslist{PayloadType}
|
||||
*
|
||||
* This list is unmodifiable. The ->data field of the MSList points a PayloadType
|
||||
* structure holding the codec information.
|
||||
|
|
@ -1460,6 +1482,8 @@ const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc)
|
|||
|
||||
/**
|
||||
* Returns the list of available video codecs.
|
||||
* @param[in] lc The LinphoneCore object
|
||||
* @return \mslist{PayloadType}
|
||||
*
|
||||
* This list is unmodifiable. The ->data field of the MSList points a PayloadType
|
||||
* structure holding the codec information.
|
||||
|
|
@ -1611,6 +1635,9 @@ LinphoneAddress *linphone_core_get_primary_contact_parsed(LinphoneCore *lc){
|
|||
|
||||
/**
|
||||
* Sets the list of audio codecs.
|
||||
* @param[in] lc The LinphoneCore object
|
||||
* @param[in] codecs \mslist{PayloadType}
|
||||
* @return 0
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
* The list is taken by the LinphoneCore thus the application should not free it.
|
||||
|
|
@ -1626,6 +1653,9 @@ int linphone_core_set_audio_codecs(LinphoneCore *lc, MSList *codecs)
|
|||
|
||||
/**
|
||||
* Sets the list of video codecs.
|
||||
* @param[in] lc The LinphoneCore object
|
||||
* @param[in] codecs \mslist{PayloadType}
|
||||
* @return 0
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
* The list is taken by the LinphoneCore thus the application should not free it.
|
||||
|
|
@ -1743,24 +1773,53 @@ bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc){
|
|||
return lc->rtp_conf.rtp_no_xmit_on_audio_mute;
|
||||
}
|
||||
|
||||
static void apply_jitter_value(LinphoneCore *lc, int value, MSFormatType stype){
|
||||
LinphoneCall *call;
|
||||
MSList *it;
|
||||
for (it=lc->calls;it!=NULL;it=it->next){
|
||||
MediaStream *ms;
|
||||
call=(LinphoneCall*)it->data;
|
||||
ms = stype==MSAudio ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream;
|
||||
if (ms){
|
||||
RtpSession *s=ms->sessions.rtp_session;
|
||||
if (s){
|
||||
if (value>0){
|
||||
ms_message("Jitter buffer size set to [%i] ms on call [%p]",value,call);
|
||||
rtp_session_set_jitter_compensation(s,value);
|
||||
rtp_session_enable_jitter_buffer(s,TRUE);
|
||||
}else if (value==0){
|
||||
ms_warning("Jitter buffer is disabled per application request on call [%p]",call);
|
||||
rtp_session_enable_jitter_buffer(s,FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nominal audio jitter buffer size in milliseconds.
|
||||
* The value takes effect immediately for all running and pending calls, if any.
|
||||
* A value of 0 disables the jitter buffer.
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
void linphone_core_set_audio_jittcomp(LinphoneCore *lc, int value)
|
||||
{
|
||||
lc->rtp_conf.audio_jitt_comp=value;
|
||||
apply_jitter_value(lc, value, MSAudio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nominal video jitter buffer size in milliseconds.
|
||||
* The value takes effect immediately for all running and pending calls, if any.
|
||||
* A value of 0 disables the jitter buffer.
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
void linphone_core_set_video_jittcomp(LinphoneCore *lc, int value)
|
||||
{
|
||||
lc->rtp_conf.video_jitt_comp=value;
|
||||
apply_jitter_value(lc, value, MSVideo);
|
||||
}
|
||||
|
||||
void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc,bool_t rtp_no_xmit_on_audio_mute){
|
||||
|
|
@ -2339,7 +2398,7 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
#endif //BUILD_UPNP
|
||||
linphone_core_start_invite(lc,call, NULL);
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
if (call->state==LinphoneCallIncomingReceived || call->state==LinphoneCallIncomingEarlyMedia){
|
||||
if (one_second_elapsed) ms_message("incoming call ringing for %i seconds",elapsed);
|
||||
if (elapsed>lc->sip_conf.inc_timeout){
|
||||
LinphoneReason decline_reason;
|
||||
|
|
@ -2383,6 +2442,10 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
lp_config_sync(lc->config);
|
||||
}
|
||||
}
|
||||
|
||||
if (liblinphone_serialize_logs == TRUE) {
|
||||
ortp_logv_flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2812,6 +2875,7 @@ void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *d
|
|||
sal_op_set_to_address(op,dest);
|
||||
sal_op_set_from(op,identity);
|
||||
sal_op_set_sent_custom_header(op,headers);
|
||||
sal_op_set_realm(op,linphone_proxy_config_get_realm(proxy));
|
||||
if (with_contact && proxy && proxy->op){
|
||||
const SalAddress *contact;
|
||||
if ((contact=sal_op_get_contact_address(proxy->op))){
|
||||
|
|
@ -3225,6 +3289,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
|
|||
#ifdef VIDEO_ENABLED
|
||||
if ((call->videostream != NULL) && (call->state == LinphoneCallStreamsRunning)) {
|
||||
video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
|
||||
video_stream_set_fps(call->videostream, linphone_core_get_preferred_framerate(lc));
|
||||
if (call->camera_enabled && call->videostream->cam!=lc->video_conf.device){
|
||||
video_stream_change_camera(call->videostream,lc->video_conf.device);
|
||||
}else video_stream_update_video_params(call->videostream);
|
||||
|
|
@ -3617,6 +3682,8 @@ int linphone_core_terminate_all_calls(LinphoneCore *lc){
|
|||
|
||||
/**
|
||||
* Returns the current list of calls.
|
||||
* @param[in] lc The LinphoneCore object
|
||||
* @return \mslist{LinphoneCall}
|
||||
*
|
||||
* Note that this list is read-only and might be changed by the core after a function call to linphone_core_iterate().
|
||||
* Similarly the LinphoneCall objects inside it might be destroyed without prior notice.
|
||||
|
|
@ -4759,6 +4826,8 @@ LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc)
|
|||
|
||||
/**
|
||||
* Get the list of call logs (past calls).
|
||||
* @param[in] lc The LinphoneCore object
|
||||
* @return \mslist{LinphoneCallLog}
|
||||
*
|
||||
* @ingroup call_logs
|
||||
**/
|
||||
|
|
@ -5334,11 +5403,13 @@ static void update_preview_size(LinphoneCore *lc, MSVideoSize oldvsize, MSVideoS
|
|||
void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize){
|
||||
if (video_size_supported(vsize)){
|
||||
MSVideoSize oldvsize=lc->video_conf.preview_vsize;
|
||||
|
||||
if (oldvsize.width==0){
|
||||
oldvsize=lc->video_conf.vsize;
|
||||
update_preview_size(lc,oldvsize,vsize);
|
||||
}
|
||||
lc->video_conf.vsize=vsize;
|
||||
update_preview_size(lc,oldvsize,vsize);
|
||||
|
||||
if (linphone_core_ready(lc))
|
||||
lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize));
|
||||
}
|
||||
|
|
@ -5424,6 +5495,7 @@ void linphone_core_set_preferred_framerate(LinphoneCore *lc, float fps){
|
|||
}
|
||||
/**
|
||||
* Returns the preferred video framerate, previously set by linphone_core_set_preferred_framerate().
|
||||
* @ingroup media_parameters
|
||||
* @param lc the linphone core
|
||||
* @return frame rate in number of frames per seconds.
|
||||
**/
|
||||
|
|
@ -6022,6 +6094,9 @@ static void linphone_core_uninit(LinphoneCore *lc)
|
|||
linphone_core_message_storage_close(lc);
|
||||
ms_exit();
|
||||
linphone_core_set_state(lc,LinphoneGlobalOff,"Off");
|
||||
if (liblinphone_serialize_logs == TRUE) {
|
||||
ortp_set_log_thread_id(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){
|
||||
|
|
@ -6200,8 +6275,8 @@ static PayloadType* find_payload_type_from_list(const char* type, int rate, int
|
|||
}
|
||||
|
||||
|
||||
PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
|
||||
PayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc));
|
||||
LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
|
||||
LinphonePayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc));
|
||||
if (result) {
|
||||
return result;
|
||||
} else {
|
||||
|
|
@ -6654,3 +6729,20 @@ bool_t linphone_core_sdp_200_ack_enabled(const LinphoneCore *lc) {
|
|||
void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url) {
|
||||
core->file_transfer_server=ms_strdup(server_url);
|
||||
}
|
||||
|
||||
|
||||
int linphone_payload_type_get_type(const LinphonePayloadType *pt) {
|
||||
return pt->type;
|
||||
}
|
||||
|
||||
int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt) {
|
||||
return pt->normal_bitrate;
|
||||
}
|
||||
|
||||
char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt) {
|
||||
return pt->mime_type;
|
||||
}
|
||||
|
||||
int linphone_payload_type_get_channels(const LinphonePayloadType *pt) {
|
||||
return pt->channels;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ LINPHONE_PUBLIC const char *linphone_error_info_get_details(const LinphoneErrorI
|
|||
LINPHONE_PUBLIC int linphone_error_info_get_protocol_code(const LinphoneErrorInfo *ei);
|
||||
|
||||
/* linphone dictionary */
|
||||
LINPHONE_PUBLIC LinphoneDictionary* linphone_dictionary_new();
|
||||
LINPHONE_PUBLIC LinphoneDictionary* linphone_dictionary_new(void);
|
||||
LinphoneDictionary * linphone_dictionary_clone(const LinphoneDictionary* src);
|
||||
LinphoneDictionary * linphone_dictionary_ref(LinphoneDictionary* obj);
|
||||
void linphone_dictionary_unref(LinphoneDictionary* obj);
|
||||
|
|
@ -247,6 +247,48 @@ LinphoneDictionary* lp_config_section_to_dict( const LpConfig* lpconfig, const c
|
|||
void lp_config_load_dict_to_section( LpConfig* lpconfig, const char* section, const LinphoneDictionary* dict);
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup media_parameters
|
||||
* @{
|
||||
**/
|
||||
|
||||
/**
|
||||
* Object representing an RTP payload type.
|
||||
*/
|
||||
typedef PayloadType LinphonePayloadType;
|
||||
|
||||
/**
|
||||
* Get the type of payload.
|
||||
* @param[in] pt LinphonePayloadType object
|
||||
* @return The type of payload.
|
||||
*/
|
||||
LINPHONE_PUBLIC int linphone_payload_type_get_type(const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* Get the normal bitrate in bits/s.
|
||||
* @param[in] pt LinphonePayloadType object
|
||||
* @return The normal bitrate in bits/s.
|
||||
*/
|
||||
LINPHONE_PUBLIC int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* Get the mime type.
|
||||
* @param[in] pt LinphonePayloadType object
|
||||
* @return The mime type.
|
||||
*/
|
||||
LINPHONE_PUBLIC char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* Get the number of channels.
|
||||
* @param[in] pt LinphonePayloadType object
|
||||
* @return The number of channels.
|
||||
*/
|
||||
LINPHONE_PUBLIC int linphone_payload_type_get_channels(const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* @}
|
||||
**/
|
||||
|
||||
#ifdef IN_LINPHONE
|
||||
#include "linphonefriend.h"
|
||||
#include "event.h"
|
||||
|
|
@ -356,8 +398,12 @@ LINPHONE_PUBLIC bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl);
|
|||
LINPHONE_PUBLIC time_t linphone_call_log_get_start_date(LinphoneCallLog *cl);
|
||||
LINPHONE_PUBLIC int linphone_call_log_get_duration(LinphoneCallLog *cl);
|
||||
LINPHONE_PUBLIC float linphone_call_log_get_quality(LinphoneCallLog *cl);
|
||||
LINPHONE_PUBLIC void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up);
|
||||
LINPHONE_PUBLIC void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl);
|
||||
/** @deprecated Use linphone_call_log_set_user_data() instead. */
|
||||
#define linphone_call_log_set_user_pointer(cl, ud) linphone_call_log_set_user_data(cl, ud)
|
||||
LINPHONE_PUBLIC void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *up);
|
||||
/** @deprecated Use linphone_call_log_get_user_data() instead. */
|
||||
#define linphone_call_log_get_user_pointer(cl) linphone_call_log_get_user_data(cl)
|
||||
LINPHONE_PUBLIC void *linphone_call_log_get_user_data(const LinphoneCallLog *cl);
|
||||
void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey);
|
||||
const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl);
|
||||
LINPHONE_PUBLIC const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl);
|
||||
|
|
@ -379,8 +425,8 @@ struct _LinphoneCallParams;
|
|||
**/
|
||||
typedef struct _LinphoneCallParams LinphoneCallParams;
|
||||
|
||||
LINPHONE_PUBLIC const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp);
|
||||
LINPHONE_PUBLIC const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp);
|
||||
LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp);
|
||||
LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp);
|
||||
LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp);
|
||||
LINPHONE_PUBLIC void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled);
|
||||
LINPHONE_PUBLIC bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp);
|
||||
|
|
@ -717,8 +763,12 @@ LINPHONE_PUBLIC const char* linphone_call_get_authentication_token(LinphoneCall
|
|||
LINPHONE_PUBLIC bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified);
|
||||
LINPHONE_PUBLIC void linphone_call_send_vfu_request(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC void *linphone_call_get_user_pointer(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
|
||||
/** @deprecated Use linphone_call_get_user_data() instead. */
|
||||
#define linphone_call_get_user_pointer(call) linphone_call_get_user_data(call)
|
||||
LINPHONE_PUBLIC void *linphone_call_get_user_data(LinphoneCall *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_user_data(LinphoneCall *call, void *user_data);
|
||||
LINPHONE_PUBLIC void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data);
|
||||
LINPHONE_PUBLIC LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy);
|
||||
|
|
@ -917,6 +967,20 @@ LINPHONE_PUBLIC bool_t linphone_proxy_config_is_registered(const LinphoneProxyCo
|
|||
**/
|
||||
LINPHONE_PUBLIC const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg);
|
||||
|
||||
/**
|
||||
* Get the realm of the given proxy config.
|
||||
* @param[in] cfg #LinphoneProxyConfig object.
|
||||
* @returns The realm of the proxy config.
|
||||
**/
|
||||
LINPHONE_PUBLIC const char *linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg);
|
||||
/**
|
||||
* Set the realm of the given proxy config.
|
||||
* @param[in] cfg #LinphoneProxyConfig object.
|
||||
* @param[in] realm New realm value.
|
||||
* @returns The realm of the proxy config.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char * realm);
|
||||
|
||||
LINPHONE_PUBLIC const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj);
|
||||
LINPHONE_PUBLIC const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj);
|
||||
LINPHONE_PUBLIC bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj);
|
||||
|
|
@ -1067,7 +1131,8 @@ void linphone_account_creator_destroy(LinphoneAccountCreator *obj);
|
|||
struct _LinphoneAuthInfo;
|
||||
|
||||
/**
|
||||
* @ingroup authentication
|
||||
* @addtogroup authentication
|
||||
* @{
|
||||
* Object holding authentication information.
|
||||
*
|
||||
* @note The object's fields should not be accessed directly. Prefer using
|
||||
|
|
@ -1092,33 +1157,131 @@ struct _LinphoneAuthInfo;
|
|||
**/
|
||||
typedef struct _LinphoneAuthInfo LinphoneAuthInfo;
|
||||
|
||||
/**
|
||||
* Creates a #LinphoneAuthInfo object with supplied information.
|
||||
* The object can be created empty, that is with all arguments set to NULL.
|
||||
* Username, userid, password, realm and domain can be set later using specific methods.
|
||||
* At the end, username and passwd (or ha1) are required.
|
||||
* @param username The username that needs to be authenticated
|
||||
* @param userid The userid used for authenticating (use NULL if you don't know what it is)
|
||||
* @param passwd The password in clear text
|
||||
* @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
|
||||
* 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);
|
||||
const char *passwd, const char *ha1,const char *realm, const char *domain);
|
||||
|
||||
/**
|
||||
* @addtogroup authentication
|
||||
* Instanciate a new auth info with values from source
|
||||
* @param source auth info object to be cloned
|
||||
* @return newly created auth info
|
||||
* Instantiates a new auth info with values from source.
|
||||
* @param[in] source The #LinphoneAuthInfo object to be cloned
|
||||
* @return The newly created #LinphoneAuthInfo object.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo* source);
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @param[in] passwd The password.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd);
|
||||
|
||||
/**
|
||||
* Sets the username.
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @param[in] username The username.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *username);
|
||||
|
||||
/**
|
||||
* Sets the userid.
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @param[in] userid The userid.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid);
|
||||
|
||||
/**
|
||||
* Sets the realm.
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @param[in] realm The realm.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_auth_info_set_realm(LinphoneAuthInfo *info, const char *realm);
|
||||
|
||||
/**
|
||||
* Sets the domain for which this authentication is valid.
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @param[in] domain The domain.
|
||||
* This should not be necessary because realm is supposed to be unique and sufficient.
|
||||
* However, many SIP servers don't set realm correctly, then domain has to be used to distinguish between several SIP account bearing the same username.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_auth_info_set_domain(LinphoneAuthInfo *info, const char *domain);
|
||||
|
||||
/**
|
||||
* Sets the ha1.
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @param[in] ha1 The ha1.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_auth_info_set_ha1(LinphoneAuthInfo *info, const char *ha1);
|
||||
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i);
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i);
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i);
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_realm(const LinphoneAuthInfo *i);
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_domain(const LinphoneAuthInfo *i);
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_ha1(const LinphoneAuthInfo *i);
|
||||
/**
|
||||
* Gets the username.
|
||||
*
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @return The username.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_username(const LinphoneAuthInfo *info);
|
||||
|
||||
/**
|
||||
* Gets the password.
|
||||
*
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @return The password.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *info);
|
||||
|
||||
/**
|
||||
* Gets the userid.
|
||||
*
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @return The userid.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *info);
|
||||
|
||||
/**
|
||||
* Gets the realm.
|
||||
*
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @return The realm.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_realm(const LinphoneAuthInfo *info);
|
||||
|
||||
/**
|
||||
* Gets the domain.
|
||||
*
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @return The domain.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_domain(const LinphoneAuthInfo *info);
|
||||
|
||||
/**
|
||||
* Gets the ha1.
|
||||
*
|
||||
* @param[in] info The #LinphoneAuthInfo object
|
||||
* @return The ha1.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char *linphone_auth_info_get_ha1(const LinphoneAuthInfo *info);
|
||||
|
||||
/* you don't need those function*/
|
||||
LINPHONE_PUBLIC void linphone_auth_info_destroy(LinphoneAuthInfo *info);
|
||||
LINPHONE_PUBLIC LinphoneAuthInfo * linphone_auth_info_new_from_config_file(LpConfig *config, int pos);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
struct _LinphoneChatRoom;
|
||||
/**
|
||||
|
|
@ -1145,7 +1308,8 @@ typedef enum _LinphoneChatMessageState {
|
|||
LinphoneChatMessageStateIdle, /**< Initial state */
|
||||
LinphoneChatMessageStateInProgress, /**< Delivery in progress */
|
||||
LinphoneChatMessageStateDelivered, /**< Message succesffully delivered an acknoleged by remote end point */
|
||||
LinphoneChatMessageStateNotDelivered /**< Message was not delivered */
|
||||
LinphoneChatMessageStateNotDelivered, /**< Message was not delivered */
|
||||
LinphoneChatMessageStateFileTransferError /**< Message was received(and acknowledged) but cannot get file from server */
|
||||
} LinphoneChatMessageState;
|
||||
|
||||
/**
|
||||
|
|
@ -1183,9 +1347,24 @@ LINPHONE_PUBLIC MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int
|
|||
LINPHONE_PUBLIC void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr);
|
||||
LINPHONE_PUBLIC void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
|
||||
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);
|
||||
|
||||
/**
|
||||
* Notify the destination of the chat message being composed that the user is typing a new 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 \mslist{LinphoneChatMessage}
|
||||
*/
|
||||
LINPHONE_PUBLIC MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
|
@ -1218,7 +1397,8 @@ LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to(const Linpho
|
|||
LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
|
||||
LINPHONE_PUBLIC const LinphoneContent* linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage* message);
|
||||
LINPHONE_PUBLIC void linphone_chat_message_start_file_download(const LinphoneChatMessage*message);
|
||||
LINPHONE_PUBLIC void linphone_chat_message_start_file_download(LinphoneChatMessage* message, LinphoneChatMessageStateChangedCb status_cb);
|
||||
LINPHONE_PUBLIC void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage* msg);
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message);
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data);
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_text(const LinphoneChatMessage* message);
|
||||
|
|
@ -1489,7 +1669,7 @@ typedef struct _LinphoneCoreVTable{
|
|||
DisplayUrlCb display_url; /**< @deprecated */
|
||||
ShowInterfaceCb show; /**< @deprecated Notifies the application that it should show up*/
|
||||
LinphoneCoreTextMessageReceivedCb text_received; /** @deprecated, use #message_received instead <br> A text message has been received */
|
||||
LinphoneCoreFileTransferRecvCb file_transfer_received; /** Callback to store file received attached to a #LinphoneChatMessage */
|
||||
LinphoneCoreFileTransferRecvCb file_transfer_recv; /** Callback to store file received attached to a #LinphoneChatMessage */
|
||||
LinphoneCoreFileTransferSendCb file_transfer_send; /** Callback to collect file chunk to be sent for a #LinphoneChatMessage */
|
||||
LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**Callback to indicate file transfer progress*/
|
||||
} LinphoneCoreVTable;
|
||||
|
|
@ -1559,6 +1739,14 @@ LINPHONE_PUBLIC void linphone_core_set_log_level(OrtpLogLevel loglevel);
|
|||
LINPHONE_PUBLIC void linphone_core_enable_logs(FILE *file);
|
||||
LINPHONE_PUBLIC void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc);
|
||||
LINPHONE_PUBLIC void linphone_core_disable_logs(void);
|
||||
|
||||
/**
|
||||
* Enable logs serialization (output logs from either the thread that creates the linphone core or the thread that calls linphone_core_iterate()).
|
||||
* Must be called before creating the linphone core.
|
||||
* @ingroup misc
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_core_serialize_logs(void);
|
||||
|
||||
LINPHONE_PUBLIC const char *linphone_core_get_version(void);
|
||||
LINPHONE_PUBLIC const char *linphone_core_get_user_agent(LinphoneCore *lc);
|
||||
/**
|
||||
|
|
@ -1712,6 +1900,22 @@ LINPHONE_PUBLIC void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime)
|
|||
|
||||
LINPHONE_PUBLIC int linphone_core_get_upload_ptime(LinphoneCore *lc);
|
||||
|
||||
/**
|
||||
* Set the SIP transport timeout.
|
||||
* @param[in] lc #LinphoneCore object.
|
||||
* @param[in] timeout_ms The SIP transport timeout in milliseconds.
|
||||
* @ingroup media_parameters
|
||||
*/
|
||||
void linphone_core_set_sip_transport_timeout(LinphoneCore *lc, int timeout_ms);
|
||||
|
||||
/**
|
||||
* Get the SIP transport timeout.
|
||||
* @param[in] lc #LinphoneCore object.
|
||||
* @return The SIP transport timeout in milliseconds.
|
||||
* @ingroup media_parameters
|
||||
*/
|
||||
int linphone_core_get_sip_transport_timeout(LinphoneCore *lc);
|
||||
|
||||
/**
|
||||
* Enable or disable DNS SRV resolution.
|
||||
* @param[in] lc #LinphoneCore object.
|
||||
|
|
@ -1740,48 +1944,48 @@ LINPHONE_PUBLIC int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *cod
|
|||
/**
|
||||
* Tells whether the specified payload type is enabled.
|
||||
* @param[in] lc #LinphoneCore object.
|
||||
* @param[in] pt The #PayloadType we want to know is enabled or not.
|
||||
* @param[in] pt The #LinphonePayloadType we want to know is enabled or not.
|
||||
* @returns TRUE if the payload type is enabled, FALSE if disabled.
|
||||
* @ingroup media_parameters
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt);
|
||||
LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* Tells whether the specified payload type represents a variable bitrate codec.
|
||||
* @param[in] lc #LinphoneCore object.
|
||||
* @param[in] pt The #PayloadType we want to know
|
||||
* @param[in] pt The #LinphonePayloadType we want to know
|
||||
* @returns TRUE if the payload type represents a VBR codec, FALSE if disabled.
|
||||
* @ingroup media_parameters
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt);
|
||||
LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s.
|
||||
* @param[in] lc the #LinphoneCore object
|
||||
* @param[in] pt the #PayloadType to modify.
|
||||
* @param[in] pt the #LinphonePayloadType to modify.
|
||||
* @param[in] bitrate the IP bitrate in kbit/s.
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate);
|
||||
LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate);
|
||||
|
||||
/**
|
||||
* Get the bitrate explicitely set with linphone_core_set_payload_type_bitrate().
|
||||
* @param[in] lc the #LinphoneCore object
|
||||
* @param[in] pt the #PayloadType to modify.
|
||||
* @param[in] pt the #LinphonePayloadType to modify.
|
||||
* @return bitrate the IP bitrate in kbit/s, or -1 if an error occured.
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt);
|
||||
LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* Enable or disable the use of the specified payload type.
|
||||
* @param[in] lc #LinphoneCore object.
|
||||
* @param[in] pt The #PayloadType to enable or disable. It can be retrieved using #linphone_core_find_payload_type
|
||||
* @param[in] pt The #LinphonePayloadType to enable or disable. It can be retrieved using #linphone_core_find_payload_type
|
||||
* @param[in] enable TRUE to enable the payload type, FALSE to disable it.
|
||||
* @return 0 if successful, any other value otherwise.
|
||||
* @ingroup media_parameters
|
||||
*/
|
||||
LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enable);
|
||||
LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enable);
|
||||
|
||||
/**
|
||||
* Wildcard value used by #linphone_core_find_payload_type to ignore rate in search algorithm
|
||||
|
|
@ -1803,7 +2007,7 @@ LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadT
|
|||
* @param channels number of channels, can be #LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS
|
||||
* @return Returns NULL if not found.
|
||||
*/
|
||||
LINPHONE_PUBLIC PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) ;
|
||||
LINPHONE_PUBLIC LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) ;
|
||||
|
||||
LINPHONE_PUBLIC int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt);
|
||||
|
||||
|
|
@ -1980,7 +2184,7 @@ LINPHONE_PUBLIC const char * linphone_core_get_stun_server(const LinphoneCore *l
|
|||
*
|
||||
* @return true if uPnP is available otherwise return false.
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_core_upnp_available();
|
||||
LINPHONE_PUBLIC bool_t linphone_core_upnp_available(void);
|
||||
|
||||
/**
|
||||
* @ingroup network_parameters
|
||||
|
|
|
|||
|
|
@ -77,6 +77,23 @@ extern "C" void libmswebrtc_init();
|
|||
}
|
||||
|
||||
|
||||
#define RETURN_PROXY_CONFIG_USER_DATA_OBJECT(javaclass, funcprefix, cobj) \
|
||||
{ \
|
||||
jclass jUserDataObjectClass; \
|
||||
jmethodID jUserDataObjectCtor; \
|
||||
jobject jUserDataObj; \
|
||||
jUserDataObj = (jobject)funcprefix ## _get_user_data(cobj); \
|
||||
if (jUserDataObj == NULL) { \
|
||||
jUserDataObjectClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/" javaclass)); \
|
||||
jUserDataObjectCtor = env->GetMethodID(jUserDataObjectClass,"<init>", "(J)V"); \
|
||||
jUserDataObj = env->NewObject(jUserDataObjectClass, jUserDataObjectCtor,(jlong) cobj); \
|
||||
jUserDataObj = env->NewGlobalRef(jUserDataObj); \
|
||||
funcprefix ## _set_user_data(cobj, jUserDataObj); \
|
||||
env->DeleteGlobalRef(jUserDataObjectClass); \
|
||||
} \
|
||||
return jUserDataObj; \
|
||||
}
|
||||
|
||||
|
||||
static JavaVM *jvm=0;
|
||||
static const char* LogDomain = "Linphone";
|
||||
|
|
@ -880,24 +897,32 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDefaultProxyConfig( J
|
|||
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc) {
|
||||
|
||||
LinphoneProxyConfig *config=0;
|
||||
linphone_core_get_default_proxy((LinphoneCore*)lc,&config);
|
||||
return (jlong)config;
|
||||
}
|
||||
|
||||
extern "C" jlongArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigList(JNIEnv* env, jobject thiz, jlong lc) {
|
||||
static jobject getOrCreateProxy(JNIEnv* env,LinphoneProxyConfig* proxy){
|
||||
RETURN_PROXY_CONFIG_USER_DATA_OBJECT("LinphoneProxyConfigImpl", linphone_proxy_config, proxy);
|
||||
}
|
||||
|
||||
extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigList(JNIEnv* env, jobject thiz, jlong lc) {
|
||||
const MSList* proxies = linphone_core_get_proxy_config_list((LinphoneCore*)lc);
|
||||
int proxyCount = ms_list_size(proxies);
|
||||
jlongArray jProxies = env->NewLongArray(proxyCount);
|
||||
jlong *jInternalArray = env->GetLongArrayElements(jProxies, NULL);
|
||||
jclass cls = env->FindClass("org/linphone/core/LinphoneProxyConfigImpl");
|
||||
jobjectArray jProxies = env->NewObjectArray(proxyCount,cls,NULL);
|
||||
|
||||
for (int i = 0; i < proxyCount; i++ ) {
|
||||
jInternalArray[i] = (unsigned long) (proxies->data);
|
||||
LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data;
|
||||
jobject jproxy = getOrCreateProxy(env,proxy);
|
||||
if(jproxy != NULL){
|
||||
env->SetObjectArrayElement(jProxies, i, jproxy);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
proxies = proxies->next;
|
||||
}
|
||||
|
||||
env->ReleaseLongArrayElements(jProxies, jInternalArray, 0);
|
||||
|
||||
return jProxies;
|
||||
}
|
||||
|
||||
|
|
@ -1247,6 +1272,13 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isPayloadTypeEnabled
|
|||
return (jboolean) linphone_core_payload_type_enabled((LinphoneCore*)lc, (PayloadType*)pt);
|
||||
}
|
||||
|
||||
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_payloadTypeIsVbr(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jlong pt) {
|
||||
return (jboolean) linphone_core_payload_type_is_vbr((LinphoneCore*)lc, (PayloadType*)pt);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPayloadTypeBitrate(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
|
|
@ -1262,6 +1294,20 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getPayloadTypeBitrate(JN
|
|||
return (jint)linphone_core_get_payload_type_bitrate((LinphoneCore*)lc,(PayloadType*)pt);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableAdaptiveRateControl(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jboolean enable) {
|
||||
linphone_core_enable_adaptive_rate_control((LinphoneCore*)lc, enable);
|
||||
}
|
||||
|
||||
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isAdaptiveRateControlEnabled(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
) {
|
||||
return (jboolean)linphone_core_adaptive_rate_control_enabled((LinphoneCore*)lc);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableEchoCancellation(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
|
|
@ -1457,12 +1503,11 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_needsEchoCalibration
|
|||
const char *card=linphone_core_get_capture_device((LinphoneCore*)lc);
|
||||
sndcard=ms_snd_card_manager_get_card(m,card);
|
||||
if (sndcard == NULL){
|
||||
ms_error("Could not get soundcard.");
|
||||
ms_error("Could not get soundcard %s", card);
|
||||
return TRUE;
|
||||
}
|
||||
if (ms_snd_card_get_capabilities(sndcard) & MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER) return FALSE;
|
||||
if (ms_snd_card_get_minimal_latency(sndcard)==0) return TRUE;
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getMediaEncryption(JNIEnv* env
|
||||
|
|
@ -1705,6 +1750,15 @@ extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_getErrorInfo(JNI
|
|||
return (jlong)linphone_proxy_config_get_error_info((LinphoneProxyConfig *) ptr);
|
||||
}
|
||||
|
||||
extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getPublishExpires(JNIEnv* env,jobject thiz,jlong ptr) {
|
||||
return (jint)linphone_proxy_config_get_publish_expires((LinphoneProxyConfig *) ptr);
|
||||
}
|
||||
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setPublishExpires(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr
|
||||
,jint jval) {
|
||||
linphone_proxy_config_set_publish_expires((LinphoneProxyConfig *) ptr, jval);
|
||||
}
|
||||
//Auth Info
|
||||
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneAuthInfoImpl_newLinphoneAuthInfo(JNIEnv* env
|
||||
|
|
@ -2371,12 +2425,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getFriendByAddress(JNIE
|
|||
env->ReleaseStringUTFChars(jaddress, address);
|
||||
return (jlong) lf;
|
||||
}
|
||||
//LinphoneChatRoom
|
||||
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNIEnv* env
|
||||
|
||||
extern "C" jlongArray _LinphoneChatRoomImpl_getHistory(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr
|
||||
,jint limit) {
|
||||
MSList* history = linphone_chat_room_get_history((LinphoneChatRoom*)ptr, limit);
|
||||
,MSList* history) {
|
||||
int historySize = ms_list_size(history);
|
||||
jlongArray jHistory = env->NewLongArray(historySize);
|
||||
jlong *jInternalArray = env->GetLongArrayElements(jHistory, NULL);
|
||||
|
|
@ -2392,6 +2445,21 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNI
|
|||
|
||||
return jHistory;
|
||||
}
|
||||
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistoryRange(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr
|
||||
,jint start
|
||||
,jint end) {
|
||||
MSList* history = linphone_chat_room_get_history_range((LinphoneChatRoom*)ptr, start, end);
|
||||
return _LinphoneChatRoomImpl_getHistory(env, thiz, ptr, history);
|
||||
}
|
||||
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr
|
||||
,jint limit) {
|
||||
MSList* history = linphone_chat_room_get_history((LinphoneChatRoom*)ptr, limit);
|
||||
return _LinphoneChatRoomImpl_getHistory(env, thiz, ptr, history);
|
||||
}
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
|
|
@ -2430,6 +2498,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatM
|
|||
|
||||
return (jlong) chatMessage;
|
||||
}
|
||||
extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getHistorySize (JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
return (jint) linphone_chat_room_get_history_size((LinphoneChatRoom*)ptr);
|
||||
}
|
||||
extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getUnreadMessagesCount(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
|
|
@ -2535,6 +2608,12 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getFrom(JNIEnv*
|
|||
return (jlong) linphone_chat_message_get_from((LinphoneChatMessage*)ptr);
|
||||
}
|
||||
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getTo(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
return (jlong) linphone_chat_message_get_to((LinphoneChatMessage*)ptr);
|
||||
}
|
||||
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getPeerAddress(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
|
|
@ -2969,6 +3048,50 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getAvpfRRI
|
|||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
if (jcollector){
|
||||
const char *collector=env->GetStringUTFChars(jcollector, NULL);
|
||||
linphone_proxy_config_set_quality_reporting_collector((LinphoneProxyConfig *)ptr, collector);
|
||||
env->ReleaseStringUTFChars(jcollector,collector);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL 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) {
|
||||
if (jrealm){
|
||||
const char *realm=env->GetStringUTFChars(jrealm, NULL);
|
||||
linphone_proxy_config_set_realm((LinphoneProxyConfig *)ptr, realm);
|
||||
env->ReleaseStringUTFChars(jrealm,realm);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getRealm(JNIEnv *env, jobject thiz, jlong ptr) {
|
||||
jstring jvalue = env->NewStringUTF(linphone_proxy_config_get_realm((LinphoneProxyConfig *)ptr));
|
||||
return jvalue;
|
||||
}
|
||||
|
||||
extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getDuration(JNIEnv* env,jobject thiz,jlong ptr) {
|
||||
return (jint)linphone_call_get_duration((LinphoneCall *) ptr);
|
||||
}
|
||||
|
|
@ -3308,6 +3431,14 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setCpuCountNative(JNIEnv
|
|||
ms_set_cpu_count(count);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioJittcomp(JNIEnv *env, jobject thiz, jlong lc, jint value) {
|
||||
linphone_core_set_audio_jittcomp((LinphoneCore *)lc, value);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoJittcomp(JNIEnv *env, jobject thiz, jlong lc, jint value) {
|
||||
linphone_core_set_video_jittcomp((LinphoneCore *)lc, value);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioPort(JNIEnv *env, jobject thiz, jlong lc, jint port) {
|
||||
linphone_core_set_audio_port((LinphoneCore *)lc, port);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ typedef struct _LinphoneFriend LinphoneFriend;
|
|||
* Contructor
|
||||
* @return a new empty #LinphoneFriend
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneFriend * linphone_friend_new();
|
||||
LINPHONE_PUBLIC LinphoneFriend * linphone_friend_new(void);
|
||||
|
||||
/**
|
||||
* Contructor same as linphone_friend_new() + linphone_friend_set_address()
|
||||
|
|
@ -356,7 +356,8 @@ LINPHONE_PUBLIC void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneF
|
|||
|
||||
/**
|
||||
* Get Buddy list of LinphoneFriend
|
||||
* @param lc #LinphoneCore object
|
||||
* @param[in] lc #LinphoneCore object
|
||||
* @return \mslist{LinphoneFriend}
|
||||
*/
|
||||
LINPHONE_PUBLIC const MSList * linphone_core_get_friend_list(const LinphoneCore *lc);
|
||||
|
||||
|
|
|
|||
|
|
@ -752,7 +752,7 @@ LINPHONE_PUBLIC void linphone_presence_model_set_user_data(LinphonePresenceModel
|
|||
* @param[in] model The #LinphonePresenceModel object for which to get the user data.
|
||||
* @return A pointer to the user data.
|
||||
*/
|
||||
LINPHONE_PUBLIC void * linphone_presence_model_get_user_data(LinphonePresenceModel *model);
|
||||
LINPHONE_PUBLIC void * linphone_presence_model_get_user_data(const LinphonePresenceModel *model);
|
||||
|
||||
/**
|
||||
* Increase the reference count of the #LinphonePresenceService object.
|
||||
|
|
@ -780,7 +780,7 @@ LINPHONE_PUBLIC void linphone_presence_service_set_user_data(LinphonePresenceSer
|
|||
* @param[in] service The #LinphonePresenceService object for which to get the user data.
|
||||
* @return A pointer to the user data.
|
||||
*/
|
||||
LINPHONE_PUBLIC void * linphone_presence_service_get_user_data(LinphonePresenceService *service);
|
||||
LINPHONE_PUBLIC void * linphone_presence_service_get_user_data(const LinphonePresenceService *service);
|
||||
|
||||
/**
|
||||
* Increase the reference count of the #LinphonePresencePerson object.
|
||||
|
|
@ -808,7 +808,7 @@ LINPHONE_PUBLIC void linphone_presence_person_set_user_data(LinphonePresencePers
|
|||
* @param[in] person The #LinphonePresencePerson object for which to get the user data.
|
||||
* @return A pointer to the user data.
|
||||
*/
|
||||
LINPHONE_PUBLIC void * linphone_presence_person_get_user_data(LinphonePresencePerson *person);
|
||||
LINPHONE_PUBLIC void * linphone_presence_person_get_user_data(const LinphonePresencePerson *person);
|
||||
|
||||
/**
|
||||
* Increase the reference count of the #LinphonePresenceActivity object.
|
||||
|
|
@ -836,7 +836,7 @@ LINPHONE_PUBLIC void linphone_presence_activity_set_user_data(LinphonePresenceAc
|
|||
* @param[in] activity The #LinphonePresenceActivity object for which to get the user data.
|
||||
* @return A pointer to the user data.
|
||||
*/
|
||||
LINPHONE_PUBLIC void * linphone_presence_activity_get_user_data(LinphonePresenceActivity *activity);
|
||||
LINPHONE_PUBLIC void * linphone_presence_activity_get_user_data(const LinphonePresenceActivity *activity);
|
||||
|
||||
/**
|
||||
* Increase the reference count of the #LinphonePresenceNote object.
|
||||
|
|
@ -864,7 +864,7 @@ LINPHONE_PUBLIC void linphone_presence_note_set_user_data(LinphonePresenceNote *
|
|||
* @param[in] note The #LinphonePresenceNote object for which to get the user data.
|
||||
* @return A pointer to the user data.
|
||||
*/
|
||||
LINPHONE_PUBLIC void * linphone_presence_note_get_user_data(LinphonePresenceNote *note);
|
||||
LINPHONE_PUBLIC void * linphone_presence_note_get_user_data(const LinphonePresenceNote *note);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, u
|
|||
static void create_chat_message(char **argv, void *data){
|
||||
LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
|
||||
LinphoneAddress *from;
|
||||
LinphoneAddress *to;
|
||||
|
||||
unsigned int storage_id = atoi(argv[0]);
|
||||
|
||||
|
|
@ -65,12 +66,18 @@ static void create_chat_message(char **argv, void *data){
|
|||
if(atoi(argv[3])==LinphoneChatMessageIncoming){
|
||||
new_message->dir=LinphoneChatMessageIncoming;
|
||||
from=linphone_address_new(argv[2]);
|
||||
to=linphone_address_new(argv[1]);
|
||||
} else {
|
||||
new_message->dir=LinphoneChatMessageOutgoing;
|
||||
from=linphone_address_new(argv[1]);
|
||||
to=linphone_address_new(argv[2]);
|
||||
}
|
||||
linphone_chat_message_set_from(new_message,from);
|
||||
linphone_address_destroy(from);
|
||||
if (to){
|
||||
linphone_chat_message_set_to(new_message,to);
|
||||
linphone_address_destroy(to);
|
||||
}
|
||||
|
||||
if( argv[9] != NULL ){
|
||||
new_message->time = (time_t)atol(argv[9]);
|
||||
|
|
@ -105,7 +112,7 @@ void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom
|
|||
int ret;
|
||||
ret=sqlite3_exec(db,stmt,callback,cr,&errmsg);
|
||||
if(ret != SQLITE_OK) {
|
||||
ms_error("Error in creation: %s.\n", errmsg);
|
||||
ms_error("Error in creation: %s.", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
}
|
||||
}
|
||||
|
|
@ -115,7 +122,7 @@ int linphone_sql_request(sqlite3* db,const char *stmt){
|
|||
int ret;
|
||||
ret=sqlite3_exec(db,stmt,NULL,NULL,&errmsg);
|
||||
if(ret != SQLITE_OK) {
|
||||
ms_error("linphone_sql_request: error sqlite3_exec(): %s.\n", errmsg);
|
||||
ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
}
|
||||
return ret;
|
||||
|
|
@ -127,7 +134,7 @@ void linphone_sql_request_all(sqlite3* db,const char *stmt, LinphoneCore* lc){
|
|||
int ret;
|
||||
ret=sqlite3_exec(db,stmt,callback_all,lc,&errmsg);
|
||||
if(ret != SQLITE_OK) {
|
||||
ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.\n", errmsg);
|
||||
ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
}
|
||||
}
|
||||
|
|
@ -210,14 +217,14 @@ void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *ms
|
|||
sqlite3_free(buf);
|
||||
}
|
||||
|
||||
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
|
||||
static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){
|
||||
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
|
||||
int numrows=0;
|
||||
|
||||
if (lc->db==NULL) return 0;
|
||||
|
||||
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
|
||||
char *buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q AND read = 0;",peer);
|
||||
char *buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?"AND read = 0":"");
|
||||
sqlite3_stmt *selectStatement;
|
||||
int returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL);
|
||||
if (returnValue == SQLITE_OK){
|
||||
|
|
@ -231,6 +238,14 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
|
|||
return numrows;
|
||||
}
|
||||
|
||||
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
|
||||
return linphone_chat_room_get_messages_count(cr, TRUE);
|
||||
}
|
||||
|
||||
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
|
||||
return linphone_chat_room_get_messages_count(cr, FALSE);
|
||||
}
|
||||
|
||||
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
|
||||
LinphoneCore *lc=cr->lc;
|
||||
|
||||
|
|
@ -253,31 +268,52 @@ void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
|
|||
ms_free(peer);
|
||||
}
|
||||
|
||||
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
|
||||
MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){
|
||||
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
|
||||
MSList *ret;
|
||||
char *buf;
|
||||
char *peer;
|
||||
uint64_t begin,end;
|
||||
int buf_max_size = 512;
|
||||
|
||||
if (lc->db==NULL) return NULL;
|
||||
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
|
||||
peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
|
||||
|
||||
cr->messages_hist = NULL;
|
||||
if (nb_message > 0)
|
||||
buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC LIMIT %i ;",peer,nb_message);
|
||||
else
|
||||
buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC;",peer);
|
||||
|
||||
/*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/
|
||||
buf=ms_malloc(buf_max_size);
|
||||
buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer);
|
||||
|
||||
if (startm<0) startm=0;
|
||||
|
||||
if (endm>0&&endm>=startm){
|
||||
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT %i ",buf,endm+1-startm);
|
||||
}else if(startm>0){
|
||||
ms_message("%s(): end is lower than start (%d < %d). No end assumed.",__FUNCTION__,endm,startm);
|
||||
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT -1",buf);
|
||||
}
|
||||
|
||||
if (startm>0){
|
||||
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s OFFSET %i ",buf,startm);
|
||||
}
|
||||
|
||||
begin=ortp_get_cur_time_ms();
|
||||
linphone_sql_request_message(lc->db,buf,cr);
|
||||
end=ortp_get_cur_time_ms();
|
||||
ms_message("linphone_chat_room_get_history(): completed in %i ms",(int)(end-begin));
|
||||
sqlite3_free(buf);
|
||||
ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
|
||||
ms_free(buf);
|
||||
ret=cr->messages_hist;
|
||||
cr->messages_hist=NULL;
|
||||
ms_free(peer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
|
||||
return linphone_chat_room_get_history_range(cr, 0, nb_message);
|
||||
}
|
||||
|
||||
|
||||
void linphone_close_storage(sqlite3* db){
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
|
@ -477,6 +513,10 @@ MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
|
|||
return NULL;
|
||||
}
|
||||
|
||||
LINPHONE_PUBLIC MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
|
||||
}
|
||||
|
||||
|
|
@ -499,4 +539,8 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ static bool_t payload_type_enabled(const PayloadType *pt) {
|
|||
return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0);
|
||||
}
|
||||
|
||||
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt){
|
||||
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt){
|
||||
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){
|
||||
return payload_type_enabled(pt);
|
||||
}
|
||||
|
|
@ -77,12 +77,12 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *p
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt){
|
||||
bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt){
|
||||
if (pt->type==PAYLOAD_VIDEO) return TRUE;
|
||||
return !!(pt->flags & PAYLOAD_TYPE_IS_VBR);
|
||||
}
|
||||
|
||||
int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){
|
||||
int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enabled){
|
||||
if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
|
||||
payload_type_set_enable(pt,enabled);
|
||||
_linphone_core_codec_config_write(lc);
|
||||
|
|
@ -108,7 +108,7 @@ const char *linphone_core_get_payload_type_description(LinphoneCore *lc, Payload
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate){
|
||||
void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate){
|
||||
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){
|
||||
if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){
|
||||
pt->normal_bitrate=bitrate*1000;
|
||||
|
|
@ -181,7 +181,7 @@ static int get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt,
|
|||
}else return (int)ceil(get_audio_payload_bandwidth_from_codec_bitrate(pt)/1000.0);/*rounding codec bandwidth should be avoid, specially for AMR*/
|
||||
}
|
||||
|
||||
int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt){
|
||||
int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePayloadType *pt){
|
||||
int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
|
||||
linphone_core_get_upload_bandwidth(lc));
|
||||
if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){
|
||||
|
|
|
|||
|
|
@ -1043,7 +1043,7 @@ void linphone_presence_model_set_user_data(LinphonePresenceModel *model, void *u
|
|||
model->user_data = user_data;
|
||||
}
|
||||
|
||||
void * linphone_presence_model_get_user_data(LinphonePresenceModel *model) {
|
||||
void * linphone_presence_model_get_user_data(const LinphonePresenceModel *model) {
|
||||
return model->user_data;
|
||||
}
|
||||
|
||||
|
|
@ -1065,7 +1065,7 @@ void linphone_presence_service_set_user_data(LinphonePresenceService *service, v
|
|||
service->user_data = user_data;
|
||||
}
|
||||
|
||||
void * linphone_presence_service_get_user_data(LinphonePresenceService *service) {
|
||||
void * linphone_presence_service_get_user_data(const LinphonePresenceService *service) {
|
||||
return service->user_data;
|
||||
}
|
||||
|
||||
|
|
@ -1087,7 +1087,7 @@ void linphone_presence_person_set_user_data(LinphonePresencePerson *person, void
|
|||
person->user_data = user_data;
|
||||
}
|
||||
|
||||
void * linphone_presence_person_get_user_data(LinphonePresencePerson *person) {
|
||||
void * linphone_presence_person_get_user_data(const LinphonePresencePerson *person) {
|
||||
return person->user_data;
|
||||
}
|
||||
|
||||
|
|
@ -1109,7 +1109,7 @@ void linphone_presence_activity_set_user_data(LinphonePresenceActivity *activity
|
|||
activity->user_data = user_data;
|
||||
}
|
||||
|
||||
void * linphone_presence_activity_get_user_data(LinphonePresenceActivity *activity) {
|
||||
void * linphone_presence_activity_get_user_data(const LinphonePresenceActivity *activity) {
|
||||
return activity->user_data;
|
||||
}
|
||||
|
||||
|
|
@ -1131,7 +1131,7 @@ void linphone_presence_note_set_user_data(LinphonePresenceNote *note, void *user
|
|||
note->user_data = user_data;
|
||||
}
|
||||
|
||||
void * linphone_presence_note_get_user_data(LinphonePresenceNote *note) {
|
||||
void * linphone_presence_note_get_user_data(const LinphonePresenceNote *note) {
|
||||
return note->user_data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,8 +163,9 @@ struct _LinphoneChatMessage {
|
|||
bool_t is_read;
|
||||
unsigned int storage_id;
|
||||
SalOp *op;
|
||||
LinphoneContent *file_transfer_information;
|
||||
char *content_type;
|
||||
LinphoneContent *file_transfer_information; /**< used to store file transfer information when the message is of file transfer type */
|
||||
char *content_type; /**< is used to specified the type of message to be sent, used only for file transfer message */
|
||||
belle_http_request_t *http_request; /**< keep a reference to the http_request in case of file transfer in order to be able to cancel the transfer */
|
||||
};
|
||||
|
||||
BELLE_SIP_DECLARE_VPTR(LinphoneChatMessage);
|
||||
|
|
@ -423,6 +424,7 @@ struct _LinphoneProxyConfig
|
|||
char *reg_identity;
|
||||
char *reg_route;
|
||||
char *quality_reporting_collector;
|
||||
char *domain;
|
||||
char *realm;
|
||||
char *contact_params;
|
||||
char *contact_uri_params;
|
||||
|
|
@ -524,6 +526,7 @@ typedef struct sip_config
|
|||
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*/
|
||||
} sip_config_t;
|
||||
|
||||
typedef struct rtp_config
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob
|
|||
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 *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;
|
||||
|
|
@ -108,6 +109,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob
|
|||
obj->reg_identity = identity ? ms_strdup(identity) : NULL;
|
||||
obj->reg_proxy = proxy ? ms_strdup(proxy) : NULL;
|
||||
obj->reg_route = route ? ms_strdup(route) : NULL;
|
||||
obj->realm = realm ? ms_strdup(realm) : NULL;
|
||||
obj->quality_reporting_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0;
|
||||
obj->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL;
|
||||
obj->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 0) : 0;
|
||||
|
|
@ -150,6 +152,7 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
|
|||
if (obj->reg_route!=NULL) ms_free(obj->reg_route);
|
||||
if (obj->quality_reporting_collector!=NULL) ms_free(obj->quality_reporting_collector);
|
||||
if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx);
|
||||
if (obj->domain!=NULL) ms_free(obj->domain);
|
||||
if (obj->realm!=NULL) ms_free(obj->realm);
|
||||
if (obj->type!=NULL) ms_free(obj->type);
|
||||
if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix);
|
||||
|
|
@ -228,10 +231,10 @@ int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *ide
|
|||
obj->reg_identity=NULL;
|
||||
}
|
||||
obj->reg_identity=ms_strdup(identity);
|
||||
if (obj->realm){
|
||||
ms_free(obj->realm);
|
||||
if (obj->domain){
|
||||
ms_free(obj->domain);
|
||||
}
|
||||
obj->realm=ms_strdup(linphone_address_get_domain(addr));
|
||||
obj->domain=ms_strdup(linphone_address_get_domain(addr));
|
||||
linphone_address_destroy(addr);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -240,7 +243,7 @@ int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *ide
|
|||
}
|
||||
|
||||
const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
|
||||
return cfg->realm;
|
||||
return cfg->domain;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -275,13 +278,13 @@ int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
|
|||
|
||||
bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){
|
||||
if (obj->reg_proxy==NULL){
|
||||
if (lc->vtable.display_warning)
|
||||
if (lc && lc->vtable.display_warning)
|
||||
lc->vtable.display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\""
|
||||
" followed by a hostname."));
|
||||
return FALSE;
|
||||
}
|
||||
if (obj->reg_identity==NULL){
|
||||
if (lc->vtable.display_warning)
|
||||
if (lc && lc->vtable.display_warning)
|
||||
lc->vtable.display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like "
|
||||
"sip:username@proxydomain, such as sip:alice@example.net"));
|
||||
return FALSE;
|
||||
|
|
@ -310,7 +313,7 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
|
|||
|
||||
/**
|
||||
* Prevent a proxy config from refreshing its registration.
|
||||
* This is useful to let registrations to expire naturally (or) when the application wants to keep control on when
|
||||
* This is useful to let registrations to expire naturally (or) when the application wants to keep control on when
|
||||
* refreshes are sent.
|
||||
* However, linphone_core_set_network_reachable(lc,TRUE) will always request the proxy configs to refresh their registrations.
|
||||
* The refreshing operations can be resumed with linphone_proxy_config_refresh_register().
|
||||
|
|
@ -409,6 +412,7 @@ void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) {
|
|||
static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
|
||||
if (obj->reg_sendregister){
|
||||
LinphoneAddress* proxy=linphone_address_new(obj->reg_proxy);
|
||||
LinphoneAddress* to=linphone_address_new(obj->reg_identity);
|
||||
char* proxy_string;
|
||||
LinphoneAddress *contact;
|
||||
ms_message("LinphoneProxyConfig [%p] about to register (LinphoneCore version: %s)",obj,linphone_core_get_version());
|
||||
|
|
@ -417,11 +421,18 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
|
|||
if (obj->op)
|
||||
sal_op_release(obj->op);
|
||||
obj->op=sal_op_new(obj->lc->sal);
|
||||
|
||||
linphone_configure_op(obj->lc, obj->op, to, NULL, FALSE);
|
||||
linphone_address_destroy(to);
|
||||
|
||||
if ((contact=guess_contact_for_register(obj))) {
|
||||
sal_op_set_contact_address(obj->op,contact);
|
||||
linphone_address_destroy(contact);
|
||||
}
|
||||
|
||||
sal_op_set_user_pointer(obj->op,obj);
|
||||
|
||||
|
||||
if (sal_register(obj->op,proxy_string,obj->reg_identity,obj->expires)==0) {
|
||||
linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress");
|
||||
} else {
|
||||
|
|
@ -946,13 +957,16 @@ int linphone_proxy_config_done(LinphoneProxyConfig *obj)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char* linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg)
|
||||
{
|
||||
return cfg?cfg->realm:NULL;
|
||||
}
|
||||
void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
|
||||
{
|
||||
if (cfg->realm!=NULL) {
|
||||
ms_free(cfg->realm);
|
||||
cfg->realm=NULL;
|
||||
}
|
||||
if (realm!=NULL) cfg->realm=ms_strdup(realm);
|
||||
cfg->realm=ms_strdup(realm);
|
||||
}
|
||||
|
||||
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){
|
||||
|
|
@ -960,10 +974,15 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese
|
|||
|
||||
if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){
|
||||
if (proxy->publish_op==NULL){
|
||||
LinphoneAddress *to=linphone_address_new(linphone_proxy_config_get_identity(proxy));
|
||||
proxy->publish_op=sal_op_new(proxy->lc->sal);
|
||||
sal_op_set_route(proxy->publish_op,proxy->reg_proxy);
|
||||
sal_op_set_from(proxy->publish_op,linphone_proxy_config_get_identity(proxy));
|
||||
sal_op_set_to(proxy->publish_op,linphone_proxy_config_get_identity(proxy));
|
||||
|
||||
linphone_configure_op(proxy->lc, proxy->publish_op,
|
||||
to, NULL, FALSE);
|
||||
|
||||
if (to!=NULL){
|
||||
linphone_address_destroy(to);
|
||||
}
|
||||
if (lp_config_get_int(proxy->lc->config,"sip","publish_msg_with_contact",0)){
|
||||
SalAddress *addr=sal_address_new(linphone_proxy_config_get_identity(proxy));
|
||||
sal_op_set_contact_address(proxy->publish_op,addr);
|
||||
|
|
@ -1116,6 +1135,9 @@ void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cf
|
|||
linphone_proxy_config_enable_register(cfg,FALSE);
|
||||
linphone_proxy_config_done(cfg);
|
||||
linphone_proxy_config_update(cfg); /*so that it has an effect*/
|
||||
|
||||
/*as cfg no longer in proxies, unregister will never be issued*/
|
||||
_linphone_proxy_config_unregister(cfg);
|
||||
}
|
||||
if (lc->default_proxy==cfg){
|
||||
lc->default_proxy=NULL;
|
||||
|
|
@ -1176,6 +1198,8 @@ int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **conf
|
|||
|
||||
/**
|
||||
* Returns an unmodifiable list of entered proxy configurations.
|
||||
* @param[in] lc The LinphoneCore object
|
||||
* @return \mslist{LinphoneProxyConfig}
|
||||
**/
|
||||
const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
|
||||
return lc->sip_conf.proxies;
|
||||
|
|
@ -1202,6 +1226,9 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC
|
|||
if (obj->reg_identity!=NULL){
|
||||
lp_config_set_string(config,key,"reg_identity",obj->reg_identity);
|
||||
}
|
||||
if (obj->realm!=NULL){
|
||||
lp_config_set_string(config,key,"realm",obj->realm);
|
||||
}
|
||||
if (obj->contact_params!=NULL){
|
||||
lp_config_set_string(config,key,"contact_parameters",obj->contact_params);
|
||||
}
|
||||
|
|
@ -1256,10 +1283,10 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc
|
|||
CONFIGURE_STRING_VALUE(cfg,config,key,server_addr,"reg_proxy")
|
||||
CONFIGURE_STRING_VALUE(cfg,config,key,route,"reg_route")
|
||||
|
||||
CONFIGURE_STRING_VALUE(cfg,config,key,realm,"realm")
|
||||
|
||||
CONFIGURE_BOOL_VALUE(cfg,config,key,quality_reporting,"quality_reporting_enabled")
|
||||
|
||||
CONFIGURE_STRING_VALUE(cfg,config,key,quality_reporting_collector,"quality_reporting_collector")
|
||||
|
||||
CONFIGURE_INT_VALUE(cfg,config,key,quality_reporting_interval,"quality_reporting_interval")
|
||||
|
||||
CONFIGURE_STRING_VALUE(cfg,config,key,contact_parameters,"contact_parameters")
|
||||
|
|
|
|||
|
|
@ -36,20 +36,28 @@ static void xml2lpc_callback(void *ctx, xml2lpc_log_level level, const char *fmt
|
|||
static void linphone_remote_provisioning_apply(LinphoneCore *lc, const char *xml) {
|
||||
xml2lpc_context *context = xml2lpc_context_new(xml2lpc_callback, lc);
|
||||
int result = xml2lpc_set_xml_string(context, xml);
|
||||
char * error_msg = NULL;
|
||||
if (result == 0) {
|
||||
result = xml2lpc_convert(context, linphone_core_get_config(lc));
|
||||
LpConfig * lpc = linphone_core_get_config(lc);
|
||||
result = xml2lpc_convert(context, lpc);
|
||||
if (result == 0) {
|
||||
lp_config_sync(linphone_core_get_config(lc));
|
||||
xml2lpc_context_destroy(context);
|
||||
linphone_configuring_terminated(lc, LinphoneConfiguringSuccessful, NULL);
|
||||
// if the remote provisioning added a proxy config and none was set before, set it
|
||||
if (lp_config_has_section(lpc, "proxy_0") && lp_config_get_int(lpc, "sip", "default_proxy", -1) == -1){
|
||||
lp_config_set_int(lpc, "sip", "default_proxy", 0);
|
||||
}
|
||||
lp_config_sync(lpc);
|
||||
|
||||
} else {
|
||||
xml2lpc_context_destroy(context);
|
||||
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "xml to lpc failed");
|
||||
error_msg = "xml to lpc failed";
|
||||
}
|
||||
} else {
|
||||
xml2lpc_context_destroy(context);
|
||||
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "invalid xml");
|
||||
error_msg = "invalid xml";
|
||||
}
|
||||
|
||||
xml2lpc_context_destroy(context);
|
||||
linphone_configuring_terminated(lc
|
||||
,error_msg ? LinphoneConfiguringFailed : LinphoneConfiguringSuccessful
|
||||
, error_msg);
|
||||
}
|
||||
|
||||
static int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path){
|
||||
|
|
@ -110,33 +118,32 @@ static void belle_request_process_auth_requested(void *ctx, belle_sip_auth_event
|
|||
}
|
||||
|
||||
int linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri) {
|
||||
const char* file_path = strstr(remote_provisioning_uri, "file://");
|
||||
|
||||
if( file_path == remote_provisioning_uri ){
|
||||
// We allow for 'local remote-provisioning' in case the file is to be opened from the hard drive
|
||||
file_path += strlen("file://");
|
||||
belle_generic_uri_t *uri=belle_generic_uri_parse(remote_provisioning_uri);
|
||||
const char* scheme = uri ? belle_generic_uri_get_scheme(uri) : NULL;
|
||||
|
||||
if( scheme && (strcmp(scheme,"file") == 0) ){
|
||||
// We allow for 'local remote-provisioning' in case the file is to be opened from the hard drive.
|
||||
const char* file_path = remote_provisioning_uri + strlen("file://"); // skip scheme
|
||||
return linphone_remote_provisioning_load_file(lc, file_path);
|
||||
} else {
|
||||
belle_generic_uri_t *uri=belle_generic_uri_parse(remote_provisioning_uri);
|
||||
|
||||
} else if( scheme && strncmp(scheme, "http", 4) == 0 ) {
|
||||
belle_http_request_listener_callbacks_t belle_request_listener={0};
|
||||
belle_http_request_listener_t *listener;
|
||||
belle_http_request_t *request;
|
||||
|
||||
|
||||
belle_request_listener.process_response=belle_request_process_response_event;
|
||||
belle_request_listener.process_auth_requested=belle_request_process_auth_requested;
|
||||
belle_request_listener.process_io_error=belle_request_process_io_error;
|
||||
belle_request_listener.process_timeout=belle_request_process_timeout;
|
||||
|
||||
listener = belle_http_request_listener_create_from_callbacks(&belle_request_listener, lc);
|
||||
|
||||
|
||||
if (uri==NULL) {
|
||||
belle_sip_error("Invalid provisioning URI [%s]",remote_provisioning_uri);
|
||||
return -1;
|
||||
}
|
||||
listener = belle_http_request_listener_create_from_callbacks(&belle_request_listener, lc);
|
||||
|
||||
request=belle_http_request_create("GET",uri, NULL);
|
||||
belle_http_provider_send_request(lc->http_provider, request, listener);
|
||||
return 0;
|
||||
return belle_http_provider_send_request(lc->http_provider, request, listener);
|
||||
} else {
|
||||
ms_error("Invalid provisioning URI [%s] (missing scheme?)",remote_provisioning_uri);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -386,6 +386,13 @@ void sal_op_add_route_address(SalOp *op, const SalAddress *address){
|
|||
sal_op_set_route_address(op,address);
|
||||
}
|
||||
}
|
||||
void sal_op_set_realm(SalOp *op, const char *realm){
|
||||
SalOpBase* op_base = (SalOpBase*)op;
|
||||
if (op_base->realm != NULL){
|
||||
ms_free(op_base->realm);
|
||||
}
|
||||
op_base->realm = ms_strdup(realm);
|
||||
}
|
||||
void sal_op_set_from(SalOp *op, const char *from){
|
||||
SET_PARAM(op,from);
|
||||
}
|
||||
|
|
@ -511,6 +518,10 @@ void __sal_op_free(SalOp *op){
|
|||
ms_free(b->route);
|
||||
b->route=NULL;
|
||||
}
|
||||
if (b->realm) {
|
||||
ms_free(b->realm);
|
||||
b->realm=NULL;
|
||||
}
|
||||
if (b->contact_address) {
|
||||
sal_address_destroy(b->contact_address);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ typedef struct _SipSetup SipSetup;
|
|||
extern "C"{
|
||||
#endif
|
||||
|
||||
BuddyInfo *buddy_info_new();
|
||||
BuddyInfo *buddy_info_new(void);
|
||||
void buddy_info_free(BuddyInfo *info);
|
||||
|
||||
void buddy_lookup_request_set_key(BuddyLookupRequest *req, const char *key);
|
||||
|
|
|
|||
|
|
@ -607,7 +607,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
|
|||
mapping.remote_port = port->external_port;
|
||||
mapping.remote_host = "";
|
||||
snprintf(description, 128, "%s %s at %s:%d",
|
||||
PACKAGE_NAME,
|
||||
"Linphone",
|
||||
(port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP": "UDP",
|
||||
port->local_addr, port->local_port);
|
||||
mapping.description = description;
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ typedef struct SalOpBase{
|
|||
SalMediaDescription *remote_media;
|
||||
void *user_pointer;
|
||||
const char* call_id;
|
||||
char* realm;
|
||||
SalAddress* service_route; /*as defined by rfc3608, might be a list*/
|
||||
SalCustomHeader *sent_custom_headers;
|
||||
SalCustomHeader *recv_custom_headers;
|
||||
|
|
@ -560,6 +561,7 @@ void sal_op_set_contact_address(SalOp *op, const SalAddress* address);
|
|||
void sal_op_set_route(SalOp *op, const char *route);
|
||||
void sal_op_set_route_address(SalOp *op, const SalAddress* address);
|
||||
void sal_op_add_route_address(SalOp *op, const SalAddress* address);
|
||||
void sal_op_set_realm(SalOp *op, const char *realm);
|
||||
void sal_op_set_from(SalOp *op, const char *from);
|
||||
void sal_op_set_from_address(SalOp *op, const SalAddress *from);
|
||||
void sal_op_set_to(SalOp *op, const char *to);
|
||||
|
|
|
|||
|
|
@ -323,4 +323,14 @@ public interface LinphoneCall {
|
|||
*/
|
||||
ErrorInfo getErrorInfo();
|
||||
|
||||
/**
|
||||
* attached a user data to a call
|
||||
**/
|
||||
void setUserData(Object obj);
|
||||
|
||||
/**
|
||||
* Returns user data from a call. return null if any
|
||||
* @return an Object.
|
||||
*/
|
||||
Object getUserData();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@ public interface LinphoneCallParams {
|
|||
/**
|
||||
* Set a path to file where the call will be recorded.
|
||||
* Actual start of the recording is controlled by LinphoneCall.startRecording().
|
||||
* @param path Path to the file where the call will be recorded. If it is a WAV
|
||||
* file, only audio will be written whereas if it is a MKV file, audio and video
|
||||
* will be written.
|
||||
**/
|
||||
void setRecordFile(String path);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,12 @@ public interface LinphoneChatMessage {
|
|||
*/
|
||||
LinphoneAddress getFrom();
|
||||
|
||||
/**
|
||||
* Get destination address of the LinphoneChatMessage.
|
||||
* @return the LinphoneAddress in the To field of the message.
|
||||
*/
|
||||
LinphoneAddress getTo();
|
||||
|
||||
/**
|
||||
* Linphone message can carry external body as defined by rfc2017
|
||||
* @param message #LinphoneChatMessage
|
||||
|
|
@ -147,4 +153,5 @@ public interface LinphoneChatMessage {
|
|||
* @return an ErrorInfo.
|
||||
*/
|
||||
ErrorInfo getErrorInfo();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ package org.linphone.core;
|
|||
import org.linphone.core.LinphoneChatMessage.State;
|
||||
|
||||
/**
|
||||
*
|
||||
* A chat room is the place where text messages are exchanged.
|
||||
*
|
||||
* A chat room is the place where text messages are exchanged.
|
||||
Can be created by linphone_core_create_chat_room().
|
||||
*
|
||||
*/
|
||||
|
|
@ -43,7 +43,7 @@ public interface LinphoneChatRoom {
|
|||
* @param chat message
|
||||
*/
|
||||
void sendMessage(LinphoneChatMessage message, LinphoneChatMessage.StateListener listener);
|
||||
|
||||
|
||||
/**
|
||||
* Create a LinphoneChatMessage
|
||||
* @param chatRoom chat room associated to the message
|
||||
|
|
@ -51,31 +51,45 @@ public interface LinphoneChatRoom {
|
|||
* @return LinphoneChatMessage object
|
||||
*/
|
||||
LinphoneChatMessage createLinphoneChatMessage(String message);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the chat history associated with the peer address associated with this chat room
|
||||
* @return an array of LinphoneChatMessage
|
||||
*/
|
||||
LinphoneChatMessage[] getHistory();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the chat history associated with the peer address associated with this chat room
|
||||
* @param limit the maximum number of messages to fetch
|
||||
* @return an array of LinphoneChatMessage
|
||||
*/
|
||||
LinphoneChatMessage[] getHistory(int limit);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the chat history associated with the peer address associated with this chat room for the given range, sorted from oldest to most recent
|
||||
* @param begin the first (most recent) message to retrieve. Newest message has index 0. If negative, use value 0 instead.
|
||||
* @param end the last (oldest) message to retrieve. Oldest message has value "history size" - 1 (equivalent to -1). If negative or lower than begin value, value is given, use -1.
|
||||
* @return an array of LinphoneChatMessage, empty if nothing has been found
|
||||
*/
|
||||
LinphoneChatMessage[] getHistoryRange(int begin, int end);
|
||||
|
||||
/**
|
||||
* Destroys a LinphoneChatRoom.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the amount of unread messages associated with the peer of this chatRoom.
|
||||
* @return the amount of unread messages
|
||||
*/
|
||||
int getUnreadMessagesCount();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the amount of messages associated with the peer of this chatRoom.
|
||||
* @return the amount of messages in the conversation
|
||||
*/
|
||||
int getHistorySize();
|
||||
|
||||
/**
|
||||
* Deletes all the messages associated with the peer of this chat room
|
||||
*/
|
||||
|
|
@ -91,24 +105,24 @@ public interface LinphoneChatRoom {
|
|||
* @return true if the remote is currently composing a message, false otherwise.
|
||||
*/
|
||||
boolean isRemoteComposing();
|
||||
|
||||
|
||||
/**
|
||||
* Marks all the messages in this conversation as read
|
||||
*/
|
||||
void markAsRead();
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a message
|
||||
* @param message the message to delete
|
||||
*/
|
||||
void deleteMessage(LinphoneChatMessage message);
|
||||
|
||||
|
||||
/**
|
||||
* Update the value stored in the database for the external_body_url field
|
||||
* @param message to update
|
||||
*/
|
||||
void updateUrl(LinphoneChatMessage message);
|
||||
|
||||
|
||||
/**
|
||||
* Create a LinphoneChatMessage
|
||||
* @return LinphoneChatMessage object
|
||||
|
|
|
|||
|
|
@ -689,10 +689,17 @@ public interface LinphoneCore {
|
|||
void enablePayloadType(PayloadType pt, boolean enable) throws LinphoneCoreException;
|
||||
|
||||
/**
|
||||
* Returns whether or not the payload is enabled in linphonecore.
|
||||
* @param pt the payload type
|
||||
* @return whether or not the payload is enabled in linphonecore.
|
||||
*/
|
||||
boolean isPayloadTypeEnabled(PayloadType pt);
|
||||
|
||||
/**
|
||||
* @param pt the payload type
|
||||
* @return whether or not the payload epresents a VBR codec
|
||||
*/
|
||||
boolean payloadTypeIsVbr(PayloadType pt);
|
||||
|
||||
/**
|
||||
* Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s.
|
||||
* @param pt the payload type
|
||||
|
|
@ -707,6 +714,18 @@ public interface LinphoneCore {
|
|||
*/
|
||||
int getPayloadTypeBitrate(PayloadType pt);
|
||||
|
||||
/**
|
||||
* Enable adaptive rate control.
|
||||
* @param enable
|
||||
*/
|
||||
void enableAdaptiveRateControl(boolean enable);
|
||||
|
||||
/**
|
||||
* Enables or disable adaptive rate control.
|
||||
* @return true if adaptive rate control is enabled.
|
||||
*/
|
||||
boolean isAdaptiveRateControlEnabled();
|
||||
|
||||
/**
|
||||
* Enables or disable echo cancellation.
|
||||
* @param enable
|
||||
|
|
@ -1604,4 +1623,21 @@ public interface LinphoneCore {
|
|||
* Typical use is to stop ringing when the user requests to ignore the call.
|
||||
**/
|
||||
public void stopRinging();
|
||||
|
||||
/**
|
||||
* Set audio jitter buffer size in milliseconds.
|
||||
* A value of zero disables the jitter buffer.
|
||||
* The new value is taken into account immediately for all running or pending calls.
|
||||
* @param value the jitter buffer size in milliseconds.
|
||||
*/
|
||||
public void setAudioJittcomp(int value);
|
||||
|
||||
/**
|
||||
* Set video jitter buffer size in milliseconds.
|
||||
* A value of zero disables the jitter buffer.
|
||||
* The new value is taken into account immediately for all running or pending calls.
|
||||
* @param value the jitter buffer size in milliseconds.
|
||||
*/
|
||||
public void setVideoJittcomp(int value);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,16 +18,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
package org.linphone.core;
|
||||
/**
|
||||
* The LinphoneProxyConfig object represents a proxy configuration to be used by the LinphoneCore object. Its fields must not be used directly in favour of the accessors methods.
|
||||
* The LinphoneProxyConfig object represents a proxy configuration to be used by the LinphoneCore object. Its fields must not be used directly in favour of the accessors methods.
|
||||
* Once created and filled properly the LinphoneProxyConfig can be given to LinphoneCore with {@link LinphoneCore#addProxyConfig(LinphoneProxyConfig)}. This will automatically triggers the registration, if enabled.
|
||||
*<br>The proxy configuration are persistent to restarts because they are saved in the configuration file. As a consequence, after {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)} there might already be a default proxy that can be examined with {@link LinphoneCore#getDefaultProxyConfig()} .
|
||||
*
|
||||
*/
|
||||
public interface LinphoneProxyConfig {
|
||||
|
||||
|
||||
/**
|
||||
*Starts editing a proxy configuration.
|
||||
*Because proxy configuration must be consistent, applications MUST call {@link #edit()} before doing any attempts to modify proxy configuration (such as identity, proxy address and so on).
|
||||
*Because proxy configuration must be consistent, applications MUST call {@link #edit()} before doing any attempts to modify proxy configuration (such as identity, proxy address and so on).
|
||||
*Once the modifications are done, then the application must call {@link #done()} to commit the changes.
|
||||
*/
|
||||
public LinphoneProxyConfig edit();
|
||||
|
|
@ -58,20 +58,20 @@ public interface LinphoneProxyConfig {
|
|||
public void setProxy(String proxyUri) throws LinphoneCoreException;
|
||||
/**
|
||||
* get the proxy's SIP address.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public String getProxy();
|
||||
/**
|
||||
* Enable register for this proxy config.
|
||||
* Register message is issued after call to {@link #done()}
|
||||
* @param value
|
||||
*/
|
||||
*/
|
||||
public LinphoneProxyConfig enableRegister(boolean value);
|
||||
/**
|
||||
* @return true if registration to the proxy is enabled.
|
||||
*/
|
||||
public boolean registerEnabled();
|
||||
|
||||
|
||||
/**
|
||||
* normalize a human readable phone number into a basic string. 888-444-222 becomes 888444222
|
||||
* @param number
|
||||
|
|
@ -83,32 +83,32 @@ public interface LinphoneProxyConfig {
|
|||
* @param prefix
|
||||
*/
|
||||
public void setDialPrefix(String prefix);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the automatically added international prefix to e164 phone numbers
|
||||
*/
|
||||
public String getDialPrefix();
|
||||
|
||||
|
||||
/**
|
||||
* * Sets whether liblinphone should replace "+" by "00" in dialed numbers (passed to
|
||||
* {@link LinphoneCore#invite(String)}).
|
||||
* @param value default value is false
|
||||
*/
|
||||
public void setDialEscapePlus(boolean value);
|
||||
|
||||
|
||||
/**
|
||||
* Whether liblinphone should replace "+" by "00" in dialed numbers (passed to
|
||||
* {@link LinphoneCore#invite(String)}).
|
||||
*/
|
||||
public boolean getDialEscapePlus();
|
||||
|
||||
|
||||
/**
|
||||
* get domain host name or ip
|
||||
* @return may be null
|
||||
*/
|
||||
public String getDomain();
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return a boolean indicating that the user is successfully registered on the proxy.
|
||||
*/
|
||||
public boolean isRegistered();
|
||||
|
|
@ -119,7 +119,7 @@ public interface LinphoneProxyConfig {
|
|||
*/
|
||||
public void setRoute(String routeUri) throws LinphoneCoreException;
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return the route set for this proxy configuration.
|
||||
*/
|
||||
public String getRoute();
|
||||
|
|
@ -135,109 +135,180 @@ public interface LinphoneProxyConfig {
|
|||
* returns publish state for this proxy config (see {@link #enablePublish(boolean)} )
|
||||
*/
|
||||
public boolean publishEnabled();
|
||||
|
||||
|
||||
|
||||
|
||||
LinphoneCore.RegistrationState getState();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the registration expiration time.
|
||||
* @param delay expiration time in seconds
|
||||
*/
|
||||
void setExpires(int delay);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the registration expiration time.
|
||||
* @return delay expiration time in seconds.
|
||||
*/
|
||||
int getExpires();
|
||||
|
||||
|
||||
/**
|
||||
* Set the privacy for all calls or chat sessions using the identity exposed by this LinphoneProxyConfig
|
||||
* @param privacy_mask a or'd int of values defined in interface {@link org.linphone.core.Privacy}
|
||||
*/
|
||||
void setPrivacy(int privacy_mask);
|
||||
|
||||
|
||||
/**
|
||||
* Get the privacy mask requested for this proxy config.
|
||||
* @return the privacy mask as defined in interface {@link org.linphone.core.Privacy}
|
||||
*/
|
||||
int getPrivacy();
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether AVPF/SAVPF must be used for calls using this proxy config.
|
||||
* @param enable True to enable AVPF/SAVF, false to disable it.
|
||||
*/
|
||||
void enableAvpf(boolean enable);
|
||||
|
||||
|
||||
/**
|
||||
* Whether AVPF is used for calls through this proxy.
|
||||
* @return
|
||||
*/
|
||||
boolean avpfEnabled();
|
||||
|
||||
/**
|
||||
* Set the interval between regular RTCP reports when using AVPF/SAVPF.
|
||||
* @param interval The interval in seconds (between 0 and 5 seconds).
|
||||
*/
|
||||
void setAvpfRRInterval(int interval);
|
||||
|
||||
|
||||
/**
|
||||
* Get the interval between regular RTCP reports when using AVPF/SAVPF.
|
||||
* @return The interval in seconds.
|
||||
*/
|
||||
int getAvpfRRInterval();
|
||||
|
||||
|
||||
/**
|
||||
* Whether AVPF is used for calls through this proxy.
|
||||
* @return
|
||||
* Indicates whether quality reporting must be used for calls using this proxy config.
|
||||
* @param enable True to enable quality reporting, false to disable it.
|
||||
*/
|
||||
boolean avpfEnabled();
|
||||
|
||||
void enableQualityReporting(boolean enable);
|
||||
|
||||
|
||||
/**
|
||||
* Whether quality reporting is used for calls through this proxy.
|
||||
* @return
|
||||
*/
|
||||
boolean qualityReportingEnabled();
|
||||
|
||||
/**
|
||||
* Set the interval between quality interval reports during a call when using quality reporting.
|
||||
* @param interval The interval in seconds (should be greater than 120 seconds to avoid too much).
|
||||
*/
|
||||
void setQualityReportingInterval(int interval);
|
||||
|
||||
/**
|
||||
* Get the interval between quality interval reports during a call when using quality reporting.
|
||||
* @return The interval in seconds.
|
||||
*/
|
||||
int getQualityReportingInterval();
|
||||
|
||||
/**
|
||||
* Set the collector SIP URI to collect reports when using quality reporting.
|
||||
* @param collector The collector SIP URI which should be configured server side too.
|
||||
*/
|
||||
void setQualityReportingCollector(String collector);
|
||||
|
||||
/**
|
||||
* Get the collector SIP URI collecting reports when using quality reporting.
|
||||
* @return The SIP URI collector address.
|
||||
*/
|
||||
String getQualityReportingCollector();
|
||||
|
||||
/**
|
||||
* Set the outbound proxy realm. It is used in digest authentication to avoid
|
||||
* re-authentication if a previous token has already been provided.
|
||||
* @param The new outbound proxy realm.
|
||||
*/
|
||||
void setRealm(String realm);
|
||||
|
||||
/**
|
||||
* Get the outbound proxy realm.
|
||||
* @return The outbound proxy realm.
|
||||
*/
|
||||
String getRealm();
|
||||
|
||||
/**
|
||||
* Set optional contact parameters that will be added to the contact information sent in the registration.
|
||||
* @param contact_params a string contaning the additional parameters in text form, like "myparam=something;myparam2=something_else"
|
||||
* @param contact_params a string containing the additional parameters in text form, like "myparam=something;myparam2=something_else"
|
||||
*
|
||||
* The main use case for this function is provide the proxy additional information regarding the user agent, like for example unique identifier or android push id.
|
||||
* As an example, the contact address in the SIP register sent will look like <sip:joe@15.128.128.93:50421>;android-push-id=43143-DFE23F-2323-FA2232.
|
||||
**/
|
||||
public void setContactParameters(String contact_params);
|
||||
|
||||
|
||||
/**
|
||||
* Get the contact's parameters.
|
||||
* @return
|
||||
*/
|
||||
public String getContactParameters();
|
||||
|
||||
|
||||
/**
|
||||
* Set optional contact parameters that will be added to the contact information sent in the registration, inside the URI.
|
||||
* @param params a string contaning the additional parameters in text form, like "myparam=something;myparam2=something_else"
|
||||
* @param params a string containing the additional parameters in text form, like "myparam=something;myparam2=something_else"
|
||||
*
|
||||
* The main use case for this function is provide the proxy additional information regarding the user agent, like for example unique identifier or apple push id.
|
||||
* As an example, the contact address in the SIP register sent will look like <sip:joe@15.128.128.93:50421;apple-push-id=43143-DFE23F-2323-FA2232>.
|
||||
**/
|
||||
public void setContactUriParameters(String params);
|
||||
|
||||
|
||||
/**
|
||||
* Get the contact's uri parameters.
|
||||
* Get the contact's URI parameters.
|
||||
* @return
|
||||
*/
|
||||
public String getContactUriParameters();
|
||||
|
||||
|
||||
/**
|
||||
* Return the international prefix for the given country
|
||||
* @param country iso code
|
||||
*/
|
||||
public int lookupCCCFromIso(String iso);
|
||||
|
||||
|
||||
/**
|
||||
* Return the international prefix for the given country
|
||||
* @param e164 phone number
|
||||
*/
|
||||
public int lookupCCCFromE164(String e164);
|
||||
|
||||
|
||||
/**
|
||||
* Return reason error code.
|
||||
* @return reason code.
|
||||
*/
|
||||
public Reason getError();
|
||||
|
||||
|
||||
/**
|
||||
* Get full error information about last error occured on the proxy config.
|
||||
* @return an ErrorInfo.
|
||||
*/
|
||||
public ErrorInfo getErrorInfo();
|
||||
|
||||
/**
|
||||
* Set the publish expiration time in second.
|
||||
* @param expires in second
|
||||
*/
|
||||
public void setPublishExpires(int expires);
|
||||
/**
|
||||
* @return the publish expiration time in second. Default value is the registration expiration value.
|
||||
*/
|
||||
public int getPublishExpires();
|
||||
|
||||
/**
|
||||
* attached a user data to a proxy config
|
||||
**/
|
||||
void setUserData(Object obj);
|
||||
|
||||
/**
|
||||
* Returns user data from a proxy config. return null if any
|
||||
* @return an Object.
|
||||
*/
|
||||
Object getUserData();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
|
|||
|
||||
boolean ownPtr = false;
|
||||
protected LinphoneAuthInfoImpl(String username,String password, String realm, String domain) {
|
||||
this(username, null, password, null, null, domain);
|
||||
this(username, null, password, null, realm, domain);
|
||||
}
|
||||
protected LinphoneAuthInfoImpl(String username, String userid, String passwd, String ha1, String realm, String domain) {
|
||||
nativePtr = newLinphoneAuthInfo();
|
||||
|
|
@ -46,6 +46,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
|
|||
this.setPassword(passwd);
|
||||
this.setHa1(ha1);
|
||||
this.setDomain(domain);
|
||||
this.setRealm(realm);
|
||||
ownPtr = true;
|
||||
}
|
||||
protected LinphoneAuthInfoImpl(long aNativePtr) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class LinphoneCallImpl implements LinphoneCall {
|
|||
|
||||
protected final long nativePtr;
|
||||
boolean ownPtr = false;
|
||||
Object userData;
|
||||
private LinphoneCallStats audioStats;
|
||||
private LinphoneCallStats videoStats;
|
||||
|
||||
|
|
@ -236,4 +237,12 @@ class LinphoneCallImpl implements LinphoneCall {
|
|||
public ErrorInfo getErrorInfo() {
|
||||
return new ErrorInfoImpl(getErrorInfo(nativePtr));
|
||||
}
|
||||
@Override
|
||||
public void setUserData(Object obj) {
|
||||
userData = obj;
|
||||
}
|
||||
@Override
|
||||
public Object getUserData() {
|
||||
return userData;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage {
|
|||
return new LinphoneAddressImpl(getFrom(nativePtr),LinphoneAddressImpl.WrapMode.FromConst);
|
||||
}
|
||||
|
||||
private native long getTo(long ptr);
|
||||
@Override
|
||||
public LinphoneAddress getTo() {
|
||||
return new LinphoneAddressImpl(getTo(nativePtr),LinphoneAddressImpl.WrapMode.FromConst);
|
||||
}
|
||||
|
||||
private native void addCustomHeader(long nativePtr, String name, String value);
|
||||
@Override
|
||||
public void addCustomHeader(String name, String value) {
|
||||
|
|
@ -93,7 +99,8 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage {
|
|||
public ErrorInfo getErrorInfo() {
|
||||
return new ErrorInfoImpl(getErrorInfo(nativePtr));
|
||||
}
|
||||
protected void finalize(){
|
||||
protected void finalize() throws Throwable{
|
||||
unref(nativePtr);
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
|
|||
private native long getPeerAddress(long ptr);
|
||||
private native void sendMessage(long ptr, String message);
|
||||
private native void sendMessage2(long ptr, Object msg, long messagePtr, StateListener listener);
|
||||
private native long[] getHistoryRange(long ptr, int begin, int end);
|
||||
private native long[] getHistory(long ptr, int limit);
|
||||
private native void destroy(long ptr);
|
||||
private native int getUnreadMessagesCount(long ptr);
|
||||
private native int getHistorySize(long ptr);
|
||||
private native void deleteHistory(long ptr);
|
||||
private native void compose(long ptr);
|
||||
private native boolean isRemoteComposing(long ptr);
|
||||
|
|
@ -44,100 +46,106 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
|
|||
nativePtr = aNativePtr;
|
||||
}
|
||||
|
||||
public synchronized LinphoneAddress getPeerAddress() {
|
||||
public LinphoneAddress getPeerAddress() {
|
||||
return new LinphoneAddressImpl(getPeerAddress(nativePtr),LinphoneAddressImpl.WrapMode.FromConst);
|
||||
}
|
||||
|
||||
public synchronized void sendMessage(String message) {
|
||||
public void sendMessage(String message) {
|
||||
synchronized(getCore()){
|
||||
sendMessage(nativePtr,message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void sendMessage(LinphoneChatMessage message, StateListener listener) {
|
||||
public void sendMessage(LinphoneChatMessage message, StateListener listener) {
|
||||
synchronized(getCore()){
|
||||
sendMessage2(nativePtr, message, ((LinphoneChatMessageImpl)message).getNativePtr(), listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized LinphoneChatMessage createLinphoneChatMessage(String message) {
|
||||
public LinphoneChatMessage createLinphoneChatMessage(String message) {
|
||||
synchronized(getCore()){
|
||||
return new LinphoneChatMessageImpl(createLinphoneChatMessage(nativePtr, message));
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized LinphoneChatMessage[] getHistory() {
|
||||
|
||||
public LinphoneChatMessage[] getHistory() {
|
||||
synchronized(getCore()){
|
||||
return getHistory(0);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized LinphoneChatMessage[] getHistory(int limit) {
|
||||
|
||||
public LinphoneChatMessage[] getHistoryRange(int begin, int end) {
|
||||
synchronized(getCore()){
|
||||
long[] typesPtr = getHistory(nativePtr, limit);
|
||||
if (typesPtr == null) return null;
|
||||
|
||||
LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length];
|
||||
for (int i=0; i < messages.length; i++) {
|
||||
messages[i] = new LinphoneChatMessageImpl(typesPtr[i]);
|
||||
}
|
||||
|
||||
return messages;
|
||||
long[] typesPtr = getHistoryRange(nativePtr, begin, end);
|
||||
return getHistoryPrivate(typesPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void destroy() {
|
||||
|
||||
public LinphoneChatMessage[] getHistory(int limit) {
|
||||
synchronized(getCore()){
|
||||
long[] typesPtr = getHistory(nativePtr, limit);
|
||||
return getHistoryPrivate(typesPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
destroy(nativePtr);
|
||||
}
|
||||
|
||||
public synchronized int getUnreadMessagesCount() {
|
||||
|
||||
public int getUnreadMessagesCount() {
|
||||
synchronized(getCore()){
|
||||
return getUnreadMessagesCount(nativePtr);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void deleteHistory() {
|
||||
|
||||
public int getHistorySize() {
|
||||
synchronized(getCore()){
|
||||
return getHistorySize(nativePtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteHistory() {
|
||||
synchronized(getCore()){
|
||||
deleteHistory(nativePtr);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void compose() {
|
||||
public void compose() {
|
||||
synchronized(getCore()){
|
||||
compose(nativePtr);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean isRemoteComposing() {
|
||||
public boolean isRemoteComposing() {
|
||||
synchronized(getCore()){
|
||||
return isRemoteComposing(nativePtr);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void markAsRead() {
|
||||
|
||||
public void markAsRead() {
|
||||
synchronized(getCore()){
|
||||
markAsRead(nativePtr);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void deleteMessage(LinphoneChatMessage message) {
|
||||
|
||||
public void deleteMessage(LinphoneChatMessage message) {
|
||||
synchronized(getCore()){
|
||||
if (message != null)
|
||||
deleteMessage(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr());
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void updateUrl(LinphoneChatMessage message) {
|
||||
|
||||
public void updateUrl(LinphoneChatMessage message) {
|
||||
synchronized(getCore()){
|
||||
if (message != null)
|
||||
updateUrl(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized LinphoneChatMessage createLinphoneChatMessage(String message,
|
||||
public LinphoneChatMessage createLinphoneChatMessage(String message,
|
||||
String url, State state, long timestamp, boolean isRead,
|
||||
boolean isIncoming) {
|
||||
synchronized(getCore()){
|
||||
|
|
@ -150,4 +158,14 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
|
|||
public synchronized LinphoneCore getCore() {
|
||||
return (LinphoneCore)getCore(nativePtr);
|
||||
}
|
||||
private LinphoneChatMessage[] getHistoryPrivate(long[] typesPtr) {
|
||||
if (typesPtr == null) return null;
|
||||
|
||||
LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length];
|
||||
for (int i=0; i < messages.length; i++) {
|
||||
messages[i] = new LinphoneChatMessageImpl(typesPtr[i]);
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
private native long findPayloadType(long nativePtr, String mime, int clockRate, int channels);
|
||||
private native int enablePayloadType(long nativePtr, long payloadType, boolean enable);
|
||||
private native boolean isPayloadTypeEnabled(long nativePtr, long payloadType);
|
||||
private native boolean payloadTypeIsVbr(long nativePtr, long payloadType);
|
||||
private native void enableAdaptiveRateControl(long nativePtr,boolean enable);
|
||||
private native boolean isAdaptiveRateControlEnabled(long nativePtr);
|
||||
private native void enableEchoCancellation(long nativePtr,boolean enable);
|
||||
private native boolean isEchoCancellationEnabled(long nativePtr);
|
||||
private native Object getCurrentCall(long nativePtr) ;
|
||||
|
|
@ -105,7 +108,7 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
private native String getRing(long nativePtr);
|
||||
private native void setRootCA(long nativePtr, String path);
|
||||
private native long[] listVideoPayloadTypes(long nativePtr);
|
||||
private native long[] getProxyConfigList(long nativePtr);
|
||||
private native LinphoneProxyConfig[] getProxyConfigList(long nativePtr);
|
||||
private native long[] getAuthInfosList(long nativePtr);
|
||||
private native long findAuthInfos(long nativePtr, String username, String realm, String domain);
|
||||
private native long[] listAudioPayloadTypes(long nativePtr);
|
||||
|
|
@ -190,7 +193,7 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
|
||||
public synchronized LinphoneProxyConfig getDefaultProxyConfig() {
|
||||
isValid();
|
||||
long lNativePtr = getDefaultProxyConfig(nativePtr);
|
||||
long lNativePtr = getDefaultProxyConfig(nativePtr);
|
||||
if (lNativePtr!=0) {
|
||||
return new LinphoneProxyConfigImpl(this,lNativePtr);
|
||||
} else {
|
||||
|
|
@ -224,6 +227,7 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
isValid();
|
||||
removeProxyConfig(nativePtr, ((LinphoneProxyConfigImpl)proxyCfg).nativePtr);
|
||||
((LinphoneProxyConfigImpl)proxyCfg).mCore=null;
|
||||
((LinphoneProxyConfigImpl)proxyCfg).deleteNativePtr();
|
||||
}
|
||||
public synchronized void clearAuthInfos() {
|
||||
isValid();
|
||||
|
|
@ -338,6 +342,12 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
isValid();
|
||||
return isPayloadTypeEnabled(nativePtr, ((PayloadTypeImpl)pt).nativePtr);
|
||||
}
|
||||
|
||||
public synchronized boolean payloadTypeIsVbr(PayloadType pt) {
|
||||
isValid();
|
||||
return payloadTypeIsVbr(nativePtr, ((PayloadTypeImpl)pt).nativePtr);
|
||||
}
|
||||
|
||||
public synchronized void enableEchoCancellation(boolean enable) {
|
||||
isValid();
|
||||
enableEchoCancellation(nativePtr, enable);
|
||||
|
|
@ -512,17 +522,8 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
setRootCA(nativePtr, path);
|
||||
}
|
||||
|
||||
public synchronized LinphoneProxyConfig[] getProxyConfigList() {
|
||||
long[] typesPtr = getProxyConfigList(nativePtr);
|
||||
if (typesPtr == null) return null;
|
||||
|
||||
LinphoneProxyConfig[] proxies = new LinphoneProxyConfig[typesPtr.length];
|
||||
|
||||
for (int i=0; i < proxies.length; i++) {
|
||||
proxies[i] = new LinphoneProxyConfigImpl(this,typesPtr[i]);
|
||||
}
|
||||
|
||||
return proxies;
|
||||
public synchronized LinphoneProxyConfig[] getProxyConfigList() {
|
||||
return getProxyConfigList(nativePtr);
|
||||
}
|
||||
|
||||
public synchronized PayloadType[] getVideoCodecs() {
|
||||
|
|
@ -1198,5 +1199,25 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
public synchronized int getPayloadTypeBitrate(PayloadType pt) {
|
||||
return getPayloadTypeBitrate(nativePtr, ((PayloadTypeImpl)pt).nativePtr);
|
||||
}
|
||||
@Override
|
||||
public synchronized void enableAdaptiveRateControl(boolean enable) {
|
||||
enableAdaptiveRateControl(nativePtr,enable);
|
||||
|
||||
}
|
||||
@Override
|
||||
public synchronized boolean isAdaptiveRateControlEnabled() {
|
||||
return isAdaptiveRateControlEnabled(nativePtr);
|
||||
}
|
||||
|
||||
private native void setAudioJittcomp(long ptr, int value);
|
||||
@Override
|
||||
public synchronized void setAudioJittcomp(int value) {
|
||||
setAudioJittcomp(nativePtr,value);
|
||||
}
|
||||
private native void setVideoJittcomp(long ptr, int value);
|
||||
@Override
|
||||
public synchronized void setVideoJittcomp(int value) {
|
||||
setVideoJittcomp(nativePtr,value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class LinphoneEventImpl implements LinphoneEvent {
|
|||
|
||||
private native int notify(long nativeptr, String type, String subtype, byte data[], String encoding);
|
||||
@Override
|
||||
public synchronized void notify(LinphoneContent content) {
|
||||
public void notify(LinphoneContent content) {
|
||||
synchronized(getCore()){
|
||||
notify(mNativePtr,content.getType(),content.getSubtype(),content.getData(),content.getEncoding());
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ public class LinphoneEventImpl implements LinphoneEvent {
|
|||
|
||||
private native int updateSubscribe(long nativePtr, String type, String subtype, byte data[], String encoding);
|
||||
@Override
|
||||
public synchronized void updateSubscribe(LinphoneContent content) {
|
||||
public void updateSubscribe(LinphoneContent content) {
|
||||
synchronized(getCore()){
|
||||
updateSubscribe(mNativePtr,content.getType(), content.getSubtype(),content.getData(),content.getEncoding());
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ public class LinphoneEventImpl implements LinphoneEvent {
|
|||
|
||||
private native int updatePublish(long nativePtr, String type, String subtype, byte data[], String encoding);
|
||||
@Override
|
||||
public synchronized void updatePublish(LinphoneContent content) {
|
||||
public void updatePublish(LinphoneContent content) {
|
||||
synchronized(getCore()){
|
||||
updatePublish(mNativePtr,content.getType(), content.getSubtype(),content.getData(),content.getEncoding());
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ public class LinphoneEventImpl implements LinphoneEvent {
|
|||
|
||||
private native int terminate(long nativePtr);
|
||||
@Override
|
||||
public synchronized void terminate() {
|
||||
public void terminate() {
|
||||
synchronized(getCore()){
|
||||
terminate(mNativePtr);
|
||||
}
|
||||
|
|
@ -115,7 +115,7 @@ public class LinphoneEventImpl implements LinphoneEvent {
|
|||
|
||||
private native void sendSubscribe(long ptr, String type, String subtype, byte data [], String encoding);
|
||||
@Override
|
||||
public synchronized void sendSubscribe(LinphoneContent body) {
|
||||
public void sendSubscribe(LinphoneContent body) {
|
||||
synchronized(getCore()){
|
||||
if (body != null)
|
||||
sendSubscribe(mNativePtr, body.getType(), body.getSubtype(), body.getData(), body.getEncoding());
|
||||
|
|
@ -126,7 +126,7 @@ public class LinphoneEventImpl implements LinphoneEvent {
|
|||
|
||||
private native void sendPublish(long ptr, String type, String subtype, byte data [], String encoding);
|
||||
@Override
|
||||
public synchronized void sendPublish(LinphoneContent body) {
|
||||
public void sendPublish(LinphoneContent body) {
|
||||
synchronized(getCore()){
|
||||
if (body != null)
|
||||
sendPublish(mNativePtr, body.getType(), body.getSubtype(), body.getData(), body.getEncoding());
|
||||
|
|
|
|||
|
|
@ -15,20 +15,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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
*/
|
||||
package org.linphone.core;
|
||||
|
||||
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class LinphoneProxyConfigImpl implements LinphoneProxyConfig {
|
||||
|
||||
protected final long nativePtr;
|
||||
protected long nativePtr;
|
||||
protected LinphoneCoreImpl mCore;
|
||||
|
||||
Object userData;
|
||||
private native int getState(long nativePtr);
|
||||
private native void setExpires(long nativePtr, int delay);
|
||||
private native int getExpires(long nativePtr);
|
||||
|
|
@ -42,11 +38,28 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig {
|
|||
enableRegister(enableRegister);
|
||||
ownPtr=true;
|
||||
}
|
||||
protected LinphoneProxyConfigImpl(LinphoneCoreImpl core, long aNativePtr) {
|
||||
|
||||
protected LinphoneProxyConfigImpl(LinphoneCoreImpl core,long aNativePtr) {
|
||||
mCore=core;
|
||||
nativePtr = aNativePtr;
|
||||
ownPtr=false;
|
||||
mCore=core;
|
||||
}
|
||||
|
||||
protected LinphoneProxyConfigImpl(long aNativePtr) {
|
||||
nativePtr = aNativePtr;
|
||||
ownPtr=false;
|
||||
}
|
||||
|
||||
private void isValid() {
|
||||
if (nativePtr == 0) {
|
||||
throw new RuntimeException("proxy config removed");
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteNativePtr() {
|
||||
nativePtr=0;
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
//Log.e(LinphoneService.TAG,"fixme, should release underlying proxy config");
|
||||
if (ownPtr) delete(nativePtr);
|
||||
|
|
@ -56,42 +69,44 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig {
|
|||
|
||||
private native void edit(long ptr);
|
||||
private native void done(long ptr);
|
||||
|
||||
|
||||
private native void setIdentity(long ptr,String identity);
|
||||
private native String getIdentity(long ptr);
|
||||
private native int setProxy(long ptr,String proxy);
|
||||
private native String getProxy(long ptr);
|
||||
|
||||
|
||||
|
||||
private native void enableRegister(long ptr,boolean value);
|
||||
private native boolean isRegisterEnabled(long ptr);
|
||||
|
||||
|
||||
private native boolean isRegistered(long ptr);
|
||||
private native void setDialPrefix(long ptr, String prefix);
|
||||
private native String getDialPrefix(long ptr);
|
||||
|
||||
|
||||
private native String normalizePhoneNumber(long ptr,String number);
|
||||
|
||||
|
||||
private native String getDomain(long ptr);
|
||||
|
||||
|
||||
private native void setDialEscapePlus(long ptr, boolean value);
|
||||
private native boolean getDialEscapePlus(long ptr);
|
||||
|
||||
|
||||
private native String getRoute(long ptr);
|
||||
private native int setRoute(long ptr,String uri);
|
||||
private native void enablePublish(long ptr,boolean enable);
|
||||
private native boolean publishEnabled(long ptr);
|
||||
private native void setContactParameters(long ptr, String params);
|
||||
|
||||
|
||||
private native int lookupCCCFromIso(long nativePtr, String iso);
|
||||
private native int lookupCCCFromE164(long nativePtr, String e164);
|
||||
|
||||
|
||||
public LinphoneProxyConfig enableRegister(boolean value) {
|
||||
isValid();
|
||||
enableRegister(nativePtr,value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void done() {
|
||||
isValid();
|
||||
Object mutex=mCore!=null ? mCore : this;
|
||||
synchronized(mutex){
|
||||
done(nativePtr);
|
||||
|
|
@ -99,6 +114,7 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig {
|
|||
}
|
||||
|
||||
public LinphoneProxyConfig edit() {
|
||||
isValid();
|
||||
Object mutex=mCore!=null ? mCore : this;
|
||||
synchronized(mutex){
|
||||
edit(nativePtr);
|
||||
|
|
@ -107,141 +123,253 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig {
|
|||
}
|
||||
|
||||
public void setIdentity(String identity) throws LinphoneCoreException {
|
||||
isValid();
|
||||
setIdentity(nativePtr,identity);
|
||||
}
|
||||
|
||||
public void setProxy(String proxyUri) throws LinphoneCoreException {
|
||||
isValid();
|
||||
if (setProxy(nativePtr,proxyUri)!=0) {
|
||||
throw new LinphoneCoreException("Bad proxy address ["+proxyUri+"]");
|
||||
}
|
||||
}
|
||||
public String normalizePhoneNumber(String number) {
|
||||
isValid();
|
||||
return normalizePhoneNumber(nativePtr,number);
|
||||
}
|
||||
public void setDialPrefix(String prefix) {
|
||||
isValid();
|
||||
setDialPrefix(nativePtr, prefix);
|
||||
}
|
||||
public String getDialPrefix() {
|
||||
isValid();
|
||||
return getDialPrefix(nativePtr);
|
||||
}
|
||||
public String getDomain() {
|
||||
isValid();
|
||||
return getDomain(nativePtr);
|
||||
}
|
||||
public void setDialEscapePlus(boolean value) {
|
||||
setDialEscapePlus(nativePtr,value);
|
||||
isValid();
|
||||
setDialEscapePlus(nativePtr,value);
|
||||
}
|
||||
public boolean getDialEscapePlus() {
|
||||
isValid();
|
||||
return getDialEscapePlus(nativePtr);
|
||||
}
|
||||
public String getIdentity() {
|
||||
isValid();
|
||||
return getIdentity(nativePtr);
|
||||
}
|
||||
public String getProxy() {
|
||||
isValid();
|
||||
return getProxy(nativePtr);
|
||||
}
|
||||
public boolean isRegistered() {
|
||||
isValid();
|
||||
return isRegistered(nativePtr);
|
||||
}
|
||||
public boolean registerEnabled() {
|
||||
isValid();
|
||||
return isRegisterEnabled(nativePtr);
|
||||
}
|
||||
public String getRoute() {
|
||||
isValid();
|
||||
return getRoute(nativePtr);
|
||||
}
|
||||
public void setRoute(String routeUri) throws LinphoneCoreException {
|
||||
isValid();
|
||||
if (setRoute(nativePtr, routeUri) != 0) {
|
||||
throw new LinphoneCoreException("cannot set route ["+routeUri+"]");
|
||||
}
|
||||
}
|
||||
public void enablePublish(boolean enable) {
|
||||
isValid();
|
||||
enablePublish(nativePtr,enable);
|
||||
}
|
||||
public RegistrationState getState() {
|
||||
isValid();
|
||||
return RegistrationState.fromInt(getState(nativePtr));
|
||||
}
|
||||
|
||||
public void setExpires(int delay) {
|
||||
isValid();
|
||||
setExpires(nativePtr, delay);
|
||||
}
|
||||
public int getExpires() {
|
||||
isValid();
|
||||
return getExpires(nativePtr);
|
||||
}
|
||||
public boolean publishEnabled() {
|
||||
return publishEnabled(nativePtr);
|
||||
isValid();
|
||||
return publishEnabled(nativePtr);
|
||||
}
|
||||
@Override
|
||||
public void setContactParameters(String params) {
|
||||
isValid();
|
||||
setContactParameters(nativePtr, params);
|
||||
}
|
||||
@Override
|
||||
public int lookupCCCFromIso(String iso) {
|
||||
isValid();
|
||||
return lookupCCCFromIso(nativePtr, iso);
|
||||
}
|
||||
@Override
|
||||
public int lookupCCCFromE164(String e164) {
|
||||
isValid();
|
||||
return lookupCCCFromE164(nativePtr, e164);
|
||||
}
|
||||
private native int getError(long nativeptr);
|
||||
@Override
|
||||
public Reason getError() {
|
||||
isValid();
|
||||
return Reason.fromInt(getError(nativePtr));
|
||||
}
|
||||
private native void setPrivacy(long nativePtr, int mask);
|
||||
@Override
|
||||
public void setPrivacy(int privacy_mask) {
|
||||
isValid();
|
||||
setPrivacy(nativePtr,privacy_mask);
|
||||
}
|
||||
|
||||
private native int getPrivacy(long nativePtr);
|
||||
@Override
|
||||
public int getPrivacy() {
|
||||
isValid();
|
||||
return getPrivacy(nativePtr);
|
||||
}
|
||||
|
||||
|
||||
private native void enableAvpf(long nativePtr, boolean enable);
|
||||
@Override
|
||||
public void enableAvpf(boolean enable) {
|
||||
isValid();
|
||||
enableAvpf(nativePtr, enable);
|
||||
}
|
||||
|
||||
private native boolean avpfEnabled(long nativePtr);
|
||||
@Override
|
||||
public boolean avpfEnabled() {
|
||||
isValid();
|
||||
return avpfEnabled(nativePtr);
|
||||
}
|
||||
|
||||
|
||||
private native void setAvpfRRInterval(long nativePtr, int interval);
|
||||
@Override
|
||||
public void setAvpfRRInterval(int interval) {
|
||||
isValid();
|
||||
setAvpfRRInterval(nativePtr, interval);
|
||||
}
|
||||
|
||||
|
||||
private native int getAvpfRRInterval(long nativePtr);
|
||||
@Override
|
||||
public int getAvpfRRInterval() {
|
||||
isValid();
|
||||
return getAvpfRRInterval(nativePtr);
|
||||
}
|
||||
|
||||
|
||||
private native String getContactParameters(long ptr);
|
||||
@Override
|
||||
public String getContactParameters() {
|
||||
isValid();
|
||||
return getContactParameters(nativePtr);
|
||||
}
|
||||
|
||||
|
||||
private native void setContactUriParameters(long ptr, String params);
|
||||
@Override
|
||||
public void setContactUriParameters(String params) {
|
||||
isValid();
|
||||
setContactUriParameters(nativePtr,params);
|
||||
}
|
||||
|
||||
|
||||
private native String getContactUriParameters(long ptr);
|
||||
@Override
|
||||
public String getContactUriParameters() {
|
||||
isValid();
|
||||
return getContactUriParameters(nativePtr);
|
||||
}
|
||||
|
||||
private native long getErrorInfo(long nativePtr);
|
||||
|
||||
@Override
|
||||
public ErrorInfo getErrorInfo() {
|
||||
return new ErrorInfoImpl(getErrorInfo(nativePtr));
|
||||
}
|
||||
|
||||
private native void enableQualityReporting(long nativePtr, boolean enable);
|
||||
@Override
|
||||
public void enableQualityReporting(boolean enable) {
|
||||
isValid();
|
||||
enableQualityReporting(nativePtr, enable);
|
||||
}
|
||||
|
||||
private native boolean qualityReportingEnabled(long nativePtr);
|
||||
@Override
|
||||
public boolean qualityReportingEnabled() {
|
||||
isValid();
|
||||
return avpfEnabled(nativePtr);
|
||||
}
|
||||
|
||||
private native void setQualityReportingInterval(long nativePtr, int interval);
|
||||
@Override
|
||||
public void setQualityReportingInterval(int interval) {
|
||||
isValid();
|
||||
setQualityReportingInterval(nativePtr, interval);
|
||||
}
|
||||
private native int getQualityReportingInterval(long nativePtr);
|
||||
@Override
|
||||
public int getQualityReportingInterval() {
|
||||
isValid();
|
||||
return getQualityReportingInterval(nativePtr);
|
||||
}
|
||||
|
||||
private native void setQualityReportingCollector(long nativePtr, String collector);
|
||||
@Override
|
||||
public void setQualityReportingCollector(String collector) {
|
||||
isValid();
|
||||
setQualityReportingCollector(nativePtr, collector);
|
||||
}
|
||||
private native String getQualityReportingCollector(long nativePtr);
|
||||
@Override
|
||||
public String getQualityReportingCollector() {
|
||||
|
||||
isValid();
|
||||
return getQualityReportingCollector(nativePtr);
|
||||
}
|
||||
|
||||
private native void setRealm(long nativePtr, String realm);
|
||||
@Override
|
||||
public void setRealm(String realm) {
|
||||
isValid();
|
||||
setRealm(nativePtr, realm);
|
||||
}
|
||||
private native String getRealm(long nativePtr);
|
||||
@Override
|
||||
public String getRealm() {
|
||||
|
||||
isValid();
|
||||
return getRealm(nativePtr);
|
||||
}
|
||||
|
||||
private native void setPublishExpires(long nativePtr, int expires);
|
||||
@Override
|
||||
public void setPublishExpires(int expires) {
|
||||
isValid();
|
||||
setPublishExpires(nativePtr, expires);
|
||||
}
|
||||
private native int getPublishExpires(long nativePtr);
|
||||
@Override
|
||||
public int getPublishExpires() {
|
||||
|
||||
isValid();
|
||||
return getPublishExpires(nativePtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserData(Object obj) {
|
||||
userData = obj;
|
||||
}
|
||||
@Override
|
||||
public Object getUserData() {
|
||||
return userData;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 6d75b63ac302fbcabe9aab003d6c1174441982a1
|
||||
Subproject commit 974f7ae2c810a4662d4c1b6a644ee9d0be31e894
|
||||
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
|||
Subproject commit 9aae6334aa4268954e32c7a3382e2dbc40b215d0
|
||||
Subproject commit b9534b1b2beb4bc549741e1f55a9c0bfe15d6c90
|
||||
|
|
@ -1,17 +1,32 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
install(FILES archived-rootca.pem
|
||||
RENAME rootca.pem
|
||||
COMPONENT COMP_liblinphone
|
||||
DESTINATION share/linphone
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||
|
||||
install(FILES ringback.wav
|
||||
COMPONENT COMP_liblinphone
|
||||
DESTINATION share/sounds/linphone
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||
|
||||
add_subdirectory(rings)
|
||||
|
||||
install(FILES ../mediastreamer2/src/voip/nowebcamCIF.jpg
|
||||
COMPONENT COMP_liblinphone
|
||||
DESTINATION share/images
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,25 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
install(FILES oldphone.wav toy-mono.wav
|
||||
COMPONENT COMP_liblinphone
|
||||
DESTINATION share/sounds/linphone/rings
|
||||
|
|
|
|||
|
|
@ -18,14 +18,24 @@
|
|||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "CUnit/Basic.h"
|
||||
#include "linphonecore.h"
|
||||
#include "lpconfig.h"
|
||||
#include "private.h"
|
||||
#include "liblinphone_tester.h"
|
||||
|
||||
static void srtp_call(void);
|
||||
static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy);
|
||||
static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime);
|
||||
static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mime);
|
||||
|
||||
// prototype definition for call_recording()
|
||||
#ifdef ANDROID
|
||||
#ifdef HAVE_OPENH264
|
||||
extern void libmsopenh264_init(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){
|
||||
char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to);
|
||||
|
|
@ -306,6 +316,8 @@ static void call_outbound_with_multiple_proxy() {
|
|||
// calling marie should go through the second proxy config
|
||||
CU_ASSERT_TRUE(call(marie, pauline));
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
#if 0 /* TODO: activate test when the implementation is ready */
|
||||
|
|
@ -423,8 +435,8 @@ static void call_with_specified_codec_bitrate(void) {
|
|||
goto end;
|
||||
}
|
||||
|
||||
disable_all_codecs_except_one(marie->lc,"opus");
|
||||
disable_all_codecs_except_one(pauline->lc,"opus");
|
||||
disable_all_audio_codecs_except_one(marie->lc,"opus");
|
||||
disable_all_audio_codecs_except_one(pauline->lc,"opus");
|
||||
|
||||
linphone_core_set_payload_type_bitrate(marie->lc,
|
||||
linphone_core_find_payload_type(marie->lc,"opus",48000,-1),
|
||||
|
|
@ -533,7 +545,7 @@ static void cancelled_call(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime){
|
||||
static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mime){
|
||||
const MSList *elem=linphone_core_get_audio_codecs(lc);
|
||||
PayloadType *pt;
|
||||
|
||||
|
|
@ -546,13 +558,27 @@ static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime){
|
|||
linphone_core_enable_payload_type(lc,pt,TRUE);
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void disable_all_video_codecs_except_one(LinphoneCore *lc, const char *mime) {
|
||||
const MSList *codecs = linphone_core_get_video_codecs(lc);
|
||||
const MSList *it = NULL;
|
||||
PayloadType *pt = NULL;
|
||||
|
||||
for(it = codecs; it != NULL; it = it->next) {
|
||||
linphone_core_enable_payload_type(lc, (PayloadType *)it->data, FALSE);
|
||||
}
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(pt = linphone_core_find_payload_type(lc, mime, -1, -1));
|
||||
linphone_core_enable_payload_type(lc, pt, TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void call_failed_because_of_codecs(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCall* out_call;
|
||||
|
||||
disable_all_codecs_except_one(marie->lc,"pcmu");
|
||||
disable_all_codecs_except_one(pauline->lc,"pcma");
|
||||
disable_all_audio_codecs_except_one(marie->lc,"pcmu");
|
||||
disable_all_audio_codecs_except_one(pauline->lc,"pcma");
|
||||
out_call = linphone_core_invite(pauline->lc,"marie");
|
||||
linphone_call_ref(out_call);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
|
||||
|
|
@ -934,15 +960,11 @@ static void call_paused_resumed(void) {
|
|||
|
||||
wait_for_until(pauline->lc, marie->lc, NULL, 5, 3000);
|
||||
|
||||
int exp_cum = - rtp_session_get_rcv_ext_seq_number(call_pauline->audiostream->ms.sessions.rtp_session);
|
||||
|
||||
linphone_core_pause_call(pauline->lc,call_pauline);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausing,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPausedByRemote,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPaused,1));
|
||||
|
||||
exp_cum += rtp_session_get_seq_number(linphone_core_get_current_call(marie->lc)->audiostream->ms.sessions.rtp_session);
|
||||
|
||||
/*stay in pause a little while in order to generate traffic*/
|
||||
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
|
||||
|
||||
|
|
@ -953,11 +975,58 @@ static void call_paused_resumed(void) {
|
|||
/*same here: wait a while for a bit of a traffic, we need to receive a RTCP packet*/
|
||||
wait_for_until(pauline->lc, marie->lc, NULL, 5, 5000);
|
||||
|
||||
/*there should be a bit of packets loss for the ones sent by PAUSED (pauline) between the latest RTCP SR report received
|
||||
by PAUSER (marie) because PAUSER will drop any packets received after the pause. Keep a tolerance of 1 more packet lost
|
||||
in case of ...*/
|
||||
/*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);
|
||||
CU_ASSERT_TRUE(abs(stats->cum_packet_loss - exp_cum)<=1);
|
||||
CU_ASSERT_EQUAL(stats->cum_packet_loss, 0);
|
||||
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_paused_resumed_with_loss(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCall* call_pauline;
|
||||
const rtp_stats_t * stats;
|
||||
|
||||
|
||||
OrtpNetworkSimulatorParams params={0};
|
||||
params.enabled=TRUE;
|
||||
params.loss_rate=25;
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
call_pauline = linphone_core_get_current_call(pauline->lc);
|
||||
rtp_session_enable_network_simulation(call_pauline->audiostream->ms.sessions.rtp_session,¶ms);
|
||||
rtp_session_enable_network_simulation(call_pauline->videostream->ms.sessions.rtp_session,¶ms);
|
||||
|
||||
wait_for_until(pauline->lc, marie->lc, NULL, 5, 4000);
|
||||
|
||||
linphone_core_pause_call(pauline->lc,call_pauline);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausing,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPausedByRemote,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPaused,1));
|
||||
|
||||
/*stay in pause a little while in order to generate traffic*/
|
||||
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
|
||||
|
||||
linphone_core_resume_call(pauline->lc,call_pauline);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
/*same here: wait a while for a bit of a traffic, we need to receive a RTCP packet*/
|
||||
wait_for_until(pauline->lc, marie->lc, NULL, 5, 5000);
|
||||
|
||||
/*since stats are NOT totally reset during pause, the stats->packet_recv is computed from
|
||||
the start of call. This test ensures that the loss rate is consistent during the entire call.*/
|
||||
stats = rtp_session_get_stats(call_pauline->sessions->rtp_session);
|
||||
CU_ASSERT_TRUE(((stats->cum_packet_loss * 100.f / stats->packet_recv) / params.loss_rate) > .5f);
|
||||
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
|
|
@ -984,19 +1053,29 @@ static bool_t pause_call_1(LinphoneCoreManager* mgr_1,LinphoneCall* call_1,Linph
|
|||
static void call_paused_resumed_from_callee(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCall* call_obj;
|
||||
LinphoneCall* call_marie;
|
||||
const rtp_stats_t * stats;
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
call_obj = linphone_core_get_current_call(marie->lc);
|
||||
call_marie = linphone_core_get_current_call(marie->lc);
|
||||
|
||||
linphone_core_pause_call(marie->lc,call_obj);
|
||||
linphone_core_pause_call(marie->lc,call_marie);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPausing,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPaused,1));
|
||||
|
||||
linphone_core_resume_call(marie->lc,call_obj);
|
||||
/*stay in pause a little while in order to generate traffic*/
|
||||
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
|
||||
|
||||
linphone_core_resume_call(marie->lc,call_marie);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
/*same here: wait a while for a bit of a traffic, we need to receive a RTCP packet*/
|
||||
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);
|
||||
CU_ASSERT_EQUAL(stats->cum_packet_loss, 0);
|
||||
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
|
|
@ -1007,7 +1086,6 @@ static void call_paused_resumed_from_callee(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) {
|
||||
LinphoneVideoPolicy caller_policy;
|
||||
|
|
@ -1065,7 +1143,42 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee)
|
|||
/*send vfu*/
|
||||
linphone_call_send_vfu_request(call_obj);
|
||||
return wait_for(caller->lc,callee->lc,&callee->stat.number_of_IframeDecoded,initial_callee_stat.number_of_IframeDecoded+1);
|
||||
} else return 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool_t remove_video(LinphoneCoreManager *caller, LinphoneCoreManager *callee) {
|
||||
LinphoneCallParams *callee_params;
|
||||
LinphoneCall *call_obj;
|
||||
stats initial_caller_stat = caller->stat;
|
||||
stats initial_callee_stat = callee->stat;
|
||||
|
||||
if (!linphone_core_get_current_call(callee->lc)
|
||||
|| (linphone_call_get_state(linphone_core_get_current_call(callee->lc)) != LinphoneCallStreamsRunning)
|
||||
|| !linphone_core_get_current_call(caller->lc)
|
||||
|| (linphone_call_get_state(linphone_core_get_current_call(caller->lc)) != LinphoneCallStreamsRunning)) {
|
||||
ms_warning("bad state for removing video");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((call_obj = linphone_core_get_current_call(callee->lc))) {
|
||||
callee_params = linphone_call_params_copy(linphone_call_get_current_params(call_obj));
|
||||
|
||||
/* Remove video. */
|
||||
linphone_call_params_enable_video(callee_params, FALSE);
|
||||
linphone_core_update_call(callee->lc, call_obj, callee_params);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(caller->lc, callee->lc, &caller->stat.number_of_LinphoneCallUpdatedByRemote, initial_caller_stat.number_of_LinphoneCallUpdatedByRemote + 1));
|
||||
CU_ASSERT_TRUE(wait_for(caller->lc, callee->lc, &callee->stat.number_of_LinphoneCallUpdating, initial_callee_stat.number_of_LinphoneCallUpdating + 1));
|
||||
CU_ASSERT_TRUE(wait_for(caller->lc, callee->lc, &callee->stat.number_of_LinphoneCallStreamsRunning, initial_callee_stat.number_of_LinphoneCallStreamsRunning + 1));
|
||||
CU_ASSERT_TRUE(wait_for(caller->lc, callee->lc, &caller->stat.number_of_LinphoneCallStreamsRunning, initial_caller_stat.number_of_LinphoneCallStreamsRunning + 1));
|
||||
|
||||
CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc))));
|
||||
CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc))));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void call_with_video_added(void) {
|
||||
|
|
@ -1104,6 +1217,56 @@ static void call_with_video_added_random_ports(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_with_several_video_switches(void) {
|
||||
int dummy = 0;
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
|
||||
CU_ASSERT_TRUE(add_video(pauline,marie));
|
||||
wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */
|
||||
CU_ASSERT_TRUE(remove_video(pauline,marie));
|
||||
CU_ASSERT_TRUE(add_video(pauline,marie));
|
||||
wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */
|
||||
CU_ASSERT_TRUE(remove_video(pauline,marie));
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void srtp_call_with_several_video_switches(void) {
|
||||
int dummy = 0;
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
||||
if (linphone_core_media_encryption_supported(marie->lc, LinphoneMediaEncryptionSRTP)) {
|
||||
linphone_core_set_media_encryption(marie->lc, LinphoneMediaEncryptionSRTP);
|
||||
linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionSRTP);
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
|
||||
CU_ASSERT_TRUE(add_video(pauline,marie));
|
||||
wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */
|
||||
CU_ASSERT_TRUE(remove_video(pauline,marie));
|
||||
CU_ASSERT_TRUE(add_video(pauline,marie));
|
||||
wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */
|
||||
CU_ASSERT_TRUE(remove_video(pauline,marie));
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
} else {
|
||||
ms_warning("Not tested because SRTP is not available.");
|
||||
}
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_with_declined_video_base(bool_t using_policy) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
|
@ -1857,8 +2020,8 @@ static void early_media_call_with_update_base(bool_t media_change){
|
|||
lcs = ms_list_append(lcs,marie->lc);
|
||||
lcs = ms_list_append(lcs,pauline->lc);
|
||||
if (media_change) {
|
||||
disable_all_codecs_except_one(marie->lc,"pcmu");
|
||||
disable_all_codecs_except_one(pauline->lc,"pcmu");
|
||||
disable_all_audio_codecs_except_one(marie->lc,"pcmu");
|
||||
disable_all_audio_codecs_except_one(pauline->lc,"pcmu");
|
||||
|
||||
}
|
||||
/*
|
||||
|
|
@ -1883,8 +2046,8 @@ static void early_media_call_with_update_base(bool_t media_change){
|
|||
pauline_params = linphone_call_params_copy(linphone_call_get_current_params(pauline_call));
|
||||
|
||||
if (media_change) {
|
||||
disable_all_codecs_except_one(marie->lc,"pcma");
|
||||
disable_all_codecs_except_one(pauline->lc,"pcma");
|
||||
disable_all_audio_codecs_except_one(marie->lc,"pcma");
|
||||
disable_all_audio_codecs_except_one(pauline->lc,"pcma");
|
||||
}
|
||||
#define UPDATED_SESSION_NAME "nouveau nom de session"
|
||||
|
||||
|
|
@ -2593,6 +2756,83 @@ static void savpf_to_savpf_call(void) {
|
|||
profile_call(TRUE, TRUE, TRUE, TRUE, "RTP/SAVPF");
|
||||
}
|
||||
|
||||
static void call_recording() {
|
||||
LinphoneCoreManager *marie = NULL;
|
||||
LinphoneCoreManager *pauline = NULL;
|
||||
LinphoneCallParams *marieParams = NULL;
|
||||
LinphoneCallParams *paulineParams = NULL;
|
||||
LinphoneCall *callInst = NULL;
|
||||
int dummy=0;
|
||||
char *filepath = NULL;
|
||||
|
||||
#ifdef ANDROID
|
||||
#ifdef HAVE_OPENH264
|
||||
libmsopenh264_init();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
marie = linphone_core_manager_new("marie_h264_rc");
|
||||
pauline = linphone_core_manager_new("pauline_h264_rc");
|
||||
marieParams = linphone_core_create_default_call_parameters(marie->lc);
|
||||
paulineParams = linphone_core_create_default_call_parameters(pauline->lc);
|
||||
|
||||
#ifdef ANDROID
|
||||
const char dirname[] = "/sdcard/Movies/liblinphone_tester";
|
||||
#else
|
||||
const char dirname[] = ".test";
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
const char filename[] = "recording.mkv";
|
||||
#else
|
||||
const char filename[] = "recording.wav";
|
||||
#endif
|
||||
|
||||
filepath = ms_new0(char, strlen(dirname) + strlen(filename) + 2);
|
||||
strcpy(filepath, dirname);
|
||||
strcat(filepath, "/");
|
||||
strcat(filepath, filename);
|
||||
if(access(dirname, F_OK) != 0) {
|
||||
#ifdef WIN32
|
||||
CU_ASSERT_EQUAL(mkdir(dirname),0);
|
||||
#else
|
||||
CU_ASSERT_EQUAL(mkdir(dirname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH), 0);
|
||||
#endif
|
||||
}
|
||||
CU_ASSERT_EQUAL(access(dirname, W_OK), 0);
|
||||
if(access(filepath, F_OK) == 0) {
|
||||
CU_ASSERT_EQUAL(remove(filepath), 0);
|
||||
}
|
||||
|
||||
linphone_call_params_set_record_file(marieParams, filepath);
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
if((linphone_core_find_payload_type(marie->lc, "H264", -1, -1) != NULL) && (linphone_core_find_payload_type(pauline->lc, "H264", -1, -1) != NULL)) {
|
||||
linphone_call_params_enable_video(marieParams, TRUE);
|
||||
linphone_call_params_enable_video(paulineParams, TRUE);
|
||||
disable_all_video_codecs_except_one(marie->lc, "H264");
|
||||
disable_all_video_codecs_except_one(pauline->lc, "H264");
|
||||
} else {
|
||||
ms_warning("call_recording(): the H264 payload has not been found. Only sound will be recorded");
|
||||
}
|
||||
#endif
|
||||
|
||||
CU_ASSERT_TRUE(call_with_params(marie, pauline, marieParams, paulineParams));
|
||||
CU_ASSERT_PTR_NOT_NULL(callInst = linphone_core_get_current_call(marie->lc));
|
||||
|
||||
ms_message("call_recording(): the call will be recorded into %s", filepath);
|
||||
linphone_call_start_recording(callInst);
|
||||
wait_for_until(marie->lc,pauline->lc,&dummy,1,10000);
|
||||
linphone_call_stop_recording(callInst);
|
||||
|
||||
CU_ASSERT_EQUAL(access(filepath, F_OK), 0);
|
||||
end_call(marie, pauline);
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
ms_free(filepath);
|
||||
}
|
||||
|
||||
test_t call_tests[] = {
|
||||
{ "Early declined call", early_declined_call },
|
||||
{ "Call declined", call_declined },
|
||||
|
|
@ -2617,6 +2857,7 @@ test_t call_tests[] = {
|
|||
{ "Call terminated by caller", call_terminated_by_caller },
|
||||
{ "Call without SDP", call_with_no_sdp},
|
||||
{ "Call paused resumed", call_paused_resumed },
|
||||
{ "Call paused resumed with loss", call_paused_resumed_with_loss },
|
||||
{ "Call paused resumed from callee", call_paused_resumed_from_callee },
|
||||
{ "SRTP call", srtp_call },
|
||||
{ "ZRTP call",zrtp_call},
|
||||
|
|
@ -2630,6 +2871,8 @@ test_t call_tests[] = {
|
|||
{ "ZRTP ice video call", zrtp_video_ice_call },
|
||||
{ "Call with video added", call_with_video_added },
|
||||
{ "Call with video added (random ports)", call_with_video_added_random_ports },
|
||||
{ "Call with several video switches", call_with_several_video_switches },
|
||||
{ "SRTP call with several video switches", srtp_call_with_several_video_switches },
|
||||
{ "Call with video declined", call_with_declined_video},
|
||||
{ "Call with video declined using policy", call_with_declined_video_using_policy},
|
||||
{ "Call with multiple early media", multiple_early_media },
|
||||
|
|
@ -2680,7 +2923,8 @@ test_t call_tests[] = {
|
|||
{ "SAVPF to AVP call", savpf_to_avp_call },
|
||||
{ "SAVPF to AVPF call", savpf_to_avpf_call },
|
||||
{ "SAVPF to SAVP call", savpf_to_savp_call },
|
||||
{ "SAVPF to SAVPF call", savpf_to_savpf_call }
|
||||
{ "SAVPF to SAVPF call", savpf_to_savpf_call },
|
||||
{ "Call recording", call_recording }
|
||||
};
|
||||
|
||||
test_suite_t call_test_suite = {
|
||||
|
|
|
|||
|
|
@ -513,3 +513,25 @@ enabled=true
|
|||
filter = (user-agent contains 'redirect') && !(request.uri.params contains 'redirected')
|
||||
contact= <sip:sipopen.example.org;redirected>
|
||||
|
||||
##
|
||||
## The purpose of the StatisticsCollector module is to collect call
|
||||
## statistics (RFC 6035) and store them on the server.
|
||||
##
|
||||
[module::StatisticsCollector]
|
||||
# Indicate whether the module is activated.
|
||||
# Default value: false
|
||||
enabled=true
|
||||
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# SIP URI of the statistics collector. Note that the messages destinated
|
||||
# to this address will be deleted by this module and thus not be
|
||||
# delivered.
|
||||
# Default value:
|
||||
collector-address=sip:collector@sip.example.org
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@
|
|||
|
||||
#ifdef ANDROID
|
||||
|
||||
extern void AndroidPrintf(FILE *stream, const char *fmt, ...);
|
||||
#define fprintf(file, fmt, ...) AndroidPrintf(file, fmt, ##__VA_ARGS__)
|
||||
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
#include <CUnit/Util.h>
|
||||
|
|
@ -118,8 +115,9 @@ static void liblinphone_tester_qnx_log_handler(OrtpLogLevel lev, const char *fmt
|
|||
#endif /* __QNX__ */
|
||||
|
||||
|
||||
|
||||
void helper(const char *name) {
|
||||
fprintf(stderr,"%s --help\n"
|
||||
liblinphone_tester_fprintf(stderr,"%s --help\n"
|
||||
"\t\t\t--verbose\n"
|
||||
"\t\t\t--silent\n"
|
||||
"\t\t\t--list-suites\n"
|
||||
|
|
@ -197,7 +195,7 @@ int main (int argc, char *argv[])
|
|||
liblinphone_tester_list_suite_tests(suite_name);
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); \
|
||||
liblinphone_tester_fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); \
|
||||
helper(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,6 +247,10 @@ void liblinphone_tester_chat_message_state_change(LinphoneChatMessage* msg,Linph
|
|||
void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreManager* callee);
|
||||
void liblinphone_tester_clock_start(MSTimeSpec *start);
|
||||
bool_t liblinphone_tester_clock_elapsed(const MSTimeSpec *start, int value_ms);
|
||||
#ifdef ANDROID
|
||||
void cunit_android_trace_handler(int level, const char *fmt, va_list args) ;
|
||||
#endif
|
||||
int liblinphone_tester_fprintf(FILE * stream, const char * format, ...);
|
||||
|
||||
#endif /* LIBLINPHONE_TESTER_H_ */
|
||||
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess
|
|||
ms_free(from);
|
||||
counters = get_stats(lc);
|
||||
counters->number_of_LinphoneMessageReceived++;
|
||||
if (linphone_chat_message_get_file_transfer_information(message))
|
||||
counters->number_of_LinphoneMessageReceivedWithFile++;
|
||||
if (counters->last_received_chat_message) linphone_chat_message_unref(counters->last_received_chat_message);
|
||||
linphone_chat_message_ref(counters->last_received_chat_message=message);
|
||||
if (linphone_chat_message_get_external_body_url(message)) {
|
||||
if (linphone_chat_message_get_file_transfer_information(message)) {
|
||||
counters->number_of_LinphoneMessageReceivedWithFile++;
|
||||
} else if (linphone_chat_message_get_external_body_url(message)) {
|
||||
counters->number_of_LinphoneMessageExtBodyReceived++;
|
||||
if (message_external_body_url) {
|
||||
CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_external_body_url(message),message_external_body_url);
|
||||
|
|
@ -75,7 +75,7 @@ void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *message, cons
|
|||
/*next chunk*/
|
||||
file = (FILE*)linphone_chat_message_get_user_data(message);
|
||||
|
||||
if (size==0) { /* tranfer complerte */
|
||||
if (size==0) { /* tranfer complete */
|
||||
stats* counters = get_stats(lc);
|
||||
linphone_chat_room_destroy(linphone_chat_message_get_chat_room(message));
|
||||
linphone_chat_message_destroy(message);
|
||||
|
|
@ -124,7 +124,7 @@ void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *me
|
|||
const LinphoneAddress* to_address = linphone_chat_message_get_to(message);
|
||||
char *address = linphone_chat_message_is_outgoing(message)?linphone_address_as_string(to_address):linphone_address_as_string(from_address);
|
||||
stats* counters = get_stats(lc);
|
||||
printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress
|
||||
ms_message(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress
|
||||
,(linphone_chat_message_is_outgoing(message)?"sent":"received")
|
||||
, content->type
|
||||
, content->subtype
|
||||
|
|
@ -157,6 +157,9 @@ void liblinphone_tester_chat_message_state_change(LinphoneChatMessage* msg,Linph
|
|||
case LinphoneChatMessageStateInProgress:
|
||||
counters->number_of_LinphoneMessageInProgress++;
|
||||
break;
|
||||
case LinphoneChatMessageStateFileTransferError:
|
||||
counters->number_of_LinphoneMessageNotDelivered++;
|
||||
break;
|
||||
default:
|
||||
ms_error("Unexpected state [%s] for message [%p]",linphone_chat_message_state_to_string(state),msg);
|
||||
}
|
||||
|
|
@ -377,19 +380,20 @@ static void file_transfer_message(void) {
|
|||
|
||||
linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1));
|
||||
if (marie->stat.last_received_info_message ) {
|
||||
linphone_chat_message_start_file_download((const LinphoneChatMessage*)marie->stat.last_received_info_message);
|
||||
if (marie->stat.last_received_chat_message ) {
|
||||
linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change);
|
||||
}
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageExtBodyReceived,1));
|
||||
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1);
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1);
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void file_transfer_message_io_error(void) {
|
||||
static void file_transfer_message_io_error_upload(void) {
|
||||
int i;
|
||||
char* to;
|
||||
LinphoneChatRoom* chat_room;
|
||||
|
|
@ -439,6 +443,173 @@ static void file_transfer_message_io_error(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_IS_BUGGED_NO_CALL_TO_IO_ERROR_CALLBACK
|
||||
static void file_transfer_message_io_error_download(void) {
|
||||
int i;
|
||||
char* to;
|
||||
LinphoneChatRoom* chat_room;
|
||||
LinphoneChatMessage* message;
|
||||
LinphoneContent content;
|
||||
const char* big_file_content="big file"; /* setting dummy file content to something */
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
reset_counters(&marie->stat);
|
||||
reset_counters(&pauline->stat);
|
||||
|
||||
/* setting dummy file content to something */
|
||||
for (i=0;i<sizeof(big_file);i+=strlen(big_file_content))
|
||||
memcpy(big_file+i, big_file_content, strlen(big_file_content));
|
||||
|
||||
big_file[0]=*"S";
|
||||
big_file[sizeof(big_file)-1]=*"E";
|
||||
|
||||
/* Globally configure an http file transfer server. */
|
||||
linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
|
||||
|
||||
/* create a chatroom on pauline's side */
|
||||
to = linphone_address_as_string(marie->identity);
|
||||
chat_room = linphone_core_create_chat_room(pauline->lc,to);
|
||||
|
||||
/* create a file transfer message */
|
||||
memset(&content,0,sizeof(content));
|
||||
content.type="text";
|
||||
content.subtype="plain";
|
||||
content.size=sizeof(big_file); /*total size to be transfered*/
|
||||
content.name = "bigfile.txt";
|
||||
message = linphone_chat_room_create_file_transfer_message(chat_room, &content);
|
||||
|
||||
linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc);
|
||||
|
||||
/* wait for marie to receive pauline's message */
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1));
|
||||
|
||||
|
||||
if (marie->stat.last_received_chat_message ) { /* get last message and use it to download file */
|
||||
linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change);
|
||||
/* wait for file to be 50% downloaded */
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
|
||||
/* and simulate network error */
|
||||
sal_set_recv_error(marie->lc->sal, -1);
|
||||
}
|
||||
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1);
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered,1);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,0);
|
||||
|
||||
sal_set_recv_error(marie->lc->sal, 0);
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void file_transfer_message_upload_cancelled(void) {
|
||||
int i;
|
||||
char* to;
|
||||
LinphoneChatRoom* chat_room;
|
||||
LinphoneChatMessage* message;
|
||||
LinphoneContent content;
|
||||
const char* big_file_content="big file"; /* setting dummy file content to something */
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
reset_counters(&marie->stat);
|
||||
reset_counters(&pauline->stat);
|
||||
|
||||
/* setting dummy file content to something */
|
||||
for (i=0;i<sizeof(big_file);i+=strlen(big_file_content))
|
||||
memcpy(big_file+i, big_file_content, strlen(big_file_content));
|
||||
|
||||
big_file[0]=*"S";
|
||||
big_file[sizeof(big_file)-1]=*"E";
|
||||
|
||||
/* Globally configure an http file transfer server. */
|
||||
linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
|
||||
|
||||
/* create a chatroom on pauline's side */
|
||||
to = linphone_address_as_string(marie->identity);
|
||||
chat_room = linphone_core_create_chat_room(pauline->lc,to);
|
||||
|
||||
/* create a file transfer message */
|
||||
memset(&content,0,sizeof(content));
|
||||
content.type="text";
|
||||
content.subtype="plain";
|
||||
content.size=sizeof(big_file); /*total size to be transfered*/
|
||||
content.name = "bigfile.txt";
|
||||
message = linphone_chat_room_create_file_transfer_message(chat_room, &content);
|
||||
|
||||
linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc);
|
||||
|
||||
/*wait for file to be 50% uploaded and cancel the transfer */
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer, 50));
|
||||
linphone_chat_room_cancel_file_transfer(message);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1));
|
||||
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,0);
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void file_transfer_message_download_cancelled(void) {
|
||||
int i;
|
||||
char* to;
|
||||
LinphoneChatRoom* chat_room;
|
||||
LinphoneChatMessage* message;
|
||||
LinphoneContent content;
|
||||
const char* big_file_content="big file"; /* setting dummy file content to something */
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
reset_counters(&marie->stat);
|
||||
reset_counters(&pauline->stat);
|
||||
|
||||
/* setting dummy file content to something */
|
||||
for (i=0;i<sizeof(big_file);i+=strlen(big_file_content))
|
||||
memcpy(big_file+i, big_file_content, strlen(big_file_content));
|
||||
|
||||
big_file[0]=*"S";
|
||||
big_file[sizeof(big_file)-1]=*"E";
|
||||
|
||||
/* Globally configure an http file transfer server. */
|
||||
linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
|
||||
|
||||
/* create a chatroom on pauline's side */
|
||||
to = linphone_address_as_string(marie->identity);
|
||||
chat_room = linphone_core_create_chat_room(pauline->lc,to);
|
||||
|
||||
/* create a file transfer message */
|
||||
memset(&content,0,sizeof(content));
|
||||
content.type="text";
|
||||
content.subtype="plain";
|
||||
content.size=sizeof(big_file); /*total size to be transfered*/
|
||||
content.name = "bigfile.txt";
|
||||
message = linphone_chat_room_create_file_transfer_message(chat_room, &content);
|
||||
|
||||
linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc);
|
||||
|
||||
/* wait for marie to receive pauline's message */
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1));
|
||||
|
||||
|
||||
if (marie->stat.last_received_chat_message ) { /* get last message and use it to download file */
|
||||
linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change);
|
||||
/* wait for file to be 50% downloaded */
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
|
||||
/* and cancel the transfer */
|
||||
linphone_chat_room_cancel_file_transfer(marie->stat.last_received_chat_message);
|
||||
}
|
||||
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1);
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,0);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered,1);
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void text_message_with_send_error(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
|
@ -583,12 +754,11 @@ static void is_composing_notification(void) {
|
|||
/*
|
||||
* Copy file "from" to file "to".
|
||||
* Destination file is truncated if existing.
|
||||
* Return 1 on success, 0 on error (printing an error).
|
||||
* Return 0 on success, positive value on error.
|
||||
*/
|
||||
static int
|
||||
message_tester_copy_file(const char *from, const char *to)
|
||||
{
|
||||
char message[256];
|
||||
FILE *in, *out;
|
||||
char buf[256];
|
||||
size_t n;
|
||||
|
|
@ -597,21 +767,17 @@ message_tester_copy_file(const char *from, const char *to)
|
|||
in=fopen(from, "r");
|
||||
if ( in == NULL )
|
||||
{
|
||||
snprintf(message, 255, "Can't open %s for reading: %s\n",
|
||||
from, strerror(errno));
|
||||
fprintf(stderr, "%s", message);
|
||||
return 0;
|
||||
ms_error("Can't open %s for reading: %s\n",from,strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Open "to" file for writing (will truncate existing files) */
|
||||
out=fopen(to, "w");
|
||||
if ( out == NULL )
|
||||
{
|
||||
snprintf(message, 255, "Can't open %s for writing: %s\n",
|
||||
to, strerror(errno));
|
||||
fprintf(stderr, "%s", message);
|
||||
ms_error("Can't open %s for writing: %s\n",to,strerror(errno));
|
||||
fclose(in);
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Copy data from "in" to "out" */
|
||||
|
|
@ -619,16 +785,17 @@ message_tester_copy_file(const char *from, const char *to)
|
|||
{
|
||||
if ( ! fwrite(buf, 1, n, out) )
|
||||
{
|
||||
ms_error("Could not write in %s: %s\n",to,strerror(errno));
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
return 0;
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_no_strange_time(void* data,int argc, char** argv,char** cNames) {
|
||||
|
|
@ -643,7 +810,7 @@ static void message_storage_migration() {
|
|||
snprintf(src_db,sizeof(src_db), "%s/messages.db", liblinphone_tester_file_prefix);
|
||||
snprintf(tmp_db,sizeof(tmp_db), "%s/tmp.db", liblinphone_tester_writable_dir_prefix);
|
||||
|
||||
CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 1);
|
||||
CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 0);
|
||||
|
||||
// enable to test the performances of the migration step
|
||||
//linphone_core_message_storage_set_debug(marie->lc, TRUE);
|
||||
|
|
@ -657,8 +824,54 @@ static void message_storage_migration() {
|
|||
|
||||
// check that all messages have been migrated to the UTC time storage
|
||||
CU_ASSERT(sqlite3_exec(marie->lc->db, "SELECT * FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK );
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
remove(tmp_db);
|
||||
}
|
||||
|
||||
static void history_messages_count() {
|
||||
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
|
||||
LinphoneAddress *jehan_addr = linphone_address_new("<sip:Jehan@sip.linphone.org>");
|
||||
LinphoneChatRoom *chatroom;
|
||||
MSList *messages;
|
||||
char src_db[256];
|
||||
char tmp_db[256];
|
||||
snprintf(src_db,sizeof(src_db), "%s/messages.db", liblinphone_tester_file_prefix);
|
||||
snprintf(tmp_db,sizeof(tmp_db), "%s/tmp.db", liblinphone_tester_writable_dir_prefix);
|
||||
|
||||
CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 0);
|
||||
|
||||
linphone_core_set_chat_database_path(marie->lc, tmp_db);
|
||||
|
||||
chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr);
|
||||
CU_ASSERT_PTR_NOT_NULL(chatroom);
|
||||
if (chatroom){
|
||||
MSList *history=linphone_chat_room_get_history(chatroom,0);
|
||||
CU_ASSERT_EQUAL(linphone_chat_room_get_history_size(chatroom), 1270);
|
||||
CU_ASSERT_EQUAL(ms_list_size(history), linphone_chat_room_get_history_size(chatroom));
|
||||
/*check the second most recent message*/
|
||||
CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)history->next->data), "Fore and aft follow each other.");
|
||||
|
||||
/*test offset+limit: retrieve the 42th latest message only and check its content*/
|
||||
messages=linphone_chat_room_get_history_range(chatroom, 42, 42);
|
||||
CU_ASSERT_EQUAL(ms_list_size(messages), 1);
|
||||
CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->data), "If you open yourself to the Tao is intangible and evasive, yet prefers to keep us at the mercy of the kingdom, then all of the streams of hundreds of valleys because of its limitless possibilities.");
|
||||
|
||||
/*test offset without limit*/
|
||||
CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, -1)), 1270-1265);
|
||||
|
||||
/*test limit without offset*/
|
||||
CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 0, 5)), 6);
|
||||
|
||||
/*test invalid start*/
|
||||
CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, 1260)), 1270-1265);
|
||||
}
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_address_destroy(jehan_addr);
|
||||
remove(tmp_db);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
test_t message_tests[] = {
|
||||
|
|
@ -671,13 +884,17 @@ test_t message_tests[] = {
|
|||
{ "Text message with send error", text_message_with_send_error },
|
||||
{ "Text message with external body", text_message_with_external_body },
|
||||
{ "File transfer message", file_transfer_message },
|
||||
{ "File transfer message with io error", file_transfer_message_io_error },
|
||||
{ "File transfer message with io error at upload", file_transfer_message_io_error_upload },
|
||||
/* { "File transfer message with io error at download", file_transfer_message_io_error_download },*/
|
||||
{ "File transfer message upload cancelled", file_transfer_message_upload_cancelled },
|
||||
{ "File transfer message download cancelled", file_transfer_message_download_cancelled },
|
||||
{ "Text message denied", text_message_denied },
|
||||
{ "Info message", info_message },
|
||||
{ "Info message with body", info_message_with_body },
|
||||
{ "IsComposing notification", is_composing_notification }
|
||||
#ifdef MSG_STORAGE_ENABLED
|
||||
,{ "Database migration", message_storage_migration }
|
||||
,{ "History count", history_messages_count }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
Binary file not shown.
55
tester/rcfiles/marie_h264_rc
Normal file
55
tester/rcfiles/marie_h264_rc
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
[sip]
|
||||
sip_port=-1
|
||||
sip_tcp_port=-1
|
||||
sip_tls_port=-1
|
||||
default_proxy=0
|
||||
ping_with_options=0
|
||||
register_only_when_network_is_up=0
|
||||
composing_idle_timeout=1
|
||||
|
||||
[auth_info_0]
|
||||
username=marie
|
||||
userid=marie
|
||||
passwd=secret
|
||||
realm=sip.example.org
|
||||
|
||||
|
||||
[proxy_0]
|
||||
reg_proxy=sip.example.org;transport=tcp
|
||||
reg_route=sip.example.org;transport=tcp;lr
|
||||
reg_identity=sip:marie@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
quality_reporting_collector=sip:collector@sip.example.org
|
||||
quality_reporting_enabled=1
|
||||
|
||||
[friend_0]
|
||||
url="Paupoche" <sip:pauline@sip.example.org>
|
||||
pol=accept
|
||||
subscribe=0
|
||||
|
||||
|
||||
[rtp]
|
||||
audio_rtp_port=8070
|
||||
video_rtp_port=9072
|
||||
|
||||
[video]
|
||||
display=1
|
||||
capture=1
|
||||
show_local=0
|
||||
size=vga
|
||||
enabled=0
|
||||
self_view=0
|
||||
automatically_initiate=0
|
||||
automatically_accept=0
|
||||
device=StaticImage: Static picture
|
||||
|
||||
[sound]
|
||||
echocancellation=0 #to not overload cpu in case of VG
|
||||
|
||||
[video_codec_0]
|
||||
mime=H264
|
||||
rate=90000
|
||||
enabled=1
|
||||
3
tester/rcfiles/marie_remote_invalid_uri_rc
Normal file
3
tester/rcfiles/marie_remote_invalid_uri_rc
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[misc]
|
||||
config-uri=/tmp/lol
|
||||
|
||||
52
tester/rcfiles/pauline_h264_rc
Normal file
52
tester/rcfiles/pauline_h264_rc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
[sip]
|
||||
sip_port=-1
|
||||
sip_tcp_port=-1
|
||||
sip_tls_port=-1
|
||||
default_proxy=0
|
||||
ping_with_options=0
|
||||
register_only_when_network_is_up=0
|
||||
composing_idle_timeout=1
|
||||
|
||||
[auth_info_0]
|
||||
username=pauline
|
||||
userid=pauline
|
||||
passwd=secret
|
||||
realm=sip.example.org
|
||||
|
||||
|
||||
[proxy_0]
|
||||
reg_proxy=sip2.linphone.org;transport=tls
|
||||
reg_route=sip2.linphone.org;transport=tls
|
||||
reg_identity=sip:pauline@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
#[friend_0]
|
||||
#url="Mariette" <sip:marie@sip.example.org>
|
||||
#pol=accept
|
||||
#subscribe=0
|
||||
|
||||
[rtp]
|
||||
audio_rtp_port=8090
|
||||
video_rtp_port=9092
|
||||
|
||||
[video]
|
||||
display=0
|
||||
capture=1
|
||||
show_local=0
|
||||
size=vga
|
||||
enabled=0
|
||||
self_view=0
|
||||
automatically_initiate=0
|
||||
automatically_accept=0
|
||||
device=StaticImage: Static picture
|
||||
|
||||
[sound]
|
||||
echocancellation=0 #to not overload cpu in case of VG
|
||||
|
||||
[video_codec_0]
|
||||
mime=H264
|
||||
rate=90000
|
||||
enabled=1
|
||||
|
|
@ -77,6 +77,12 @@ static void remote_provisioning_invalid(void) {
|
|||
linphone_core_manager_destroy(marie);
|
||||
}
|
||||
|
||||
static void remote_provisioning_invalid_uri(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new2("marie_remote_invalid_uri_rc", FALSE);
|
||||
CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringFailed,1));
|
||||
linphone_core_manager_destroy(marie);
|
||||
}
|
||||
|
||||
static void remote_provisioning_default_values(void) {
|
||||
LinphoneProxyConfig *lpc;
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new2("marie_remote_default_values_rc", FALSE);
|
||||
|
|
@ -120,7 +126,8 @@ test_t remote_provisioning_tests[] = {
|
|||
{ "Remote provisioning invalid", remote_provisioning_invalid },
|
||||
{ "Remote provisioning transient successful", remote_provisioning_transient },
|
||||
{ "Remote provisioning default values", remote_provisioning_default_values },
|
||||
{ "Remote provisioning from file", remote_provisioning_file }
|
||||
{ "Remote provisioning from file", remote_provisioning_file },
|
||||
{ "Remote provisioning invalid URI", remote_provisioning_invalid_uri }
|
||||
};
|
||||
|
||||
test_suite_t remote_provisioning_test_suite = {
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ void linphone_proxy_config_address_equal_test() {
|
|||
void linphone_proxy_config_is_server_config_changed_test() {
|
||||
LinphoneProxyConfig* proxy_config = linphone_proxy_config_new();
|
||||
|
||||
linphone_proxy_config_done(proxy_config); /*test done without edit*/
|
||||
|
||||
linphone_proxy_config_set_identity(proxy_config,"sip:toto@titi");
|
||||
linphone_proxy_config_edit(proxy_config);
|
||||
linphone_proxy_config_set_identity(proxy_config,"sips:toto@titi");
|
||||
|
|
@ -164,6 +166,16 @@ void linphone_proxy_config_is_server_config_changed_test() {
|
|||
linphone_proxy_config_destroy(proxy_config);
|
||||
}
|
||||
|
||||
static void chat_root_test(void) {
|
||||
LinphoneCoreVTable v_table;
|
||||
LinphoneCore* lc;
|
||||
memset (&v_table,0,sizeof(v_table));
|
||||
lc = linphone_core_new(&v_table,NULL,NULL,NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(lc);
|
||||
linphone_core_create_chat_room(lc,"sip:toto@titi.com");
|
||||
linphone_core_destroy(lc);
|
||||
}
|
||||
|
||||
test_t setup_tests[] = {
|
||||
{ "Linphone Address", linphone_address_test },
|
||||
{ "Linphone proxy config address equal (internal api)", linphone_proxy_config_address_equal_test},
|
||||
|
|
@ -171,7 +183,8 @@ test_t setup_tests[] = {
|
|||
{ "Linphone core init/uninit", core_init_test },
|
||||
{ "Linphone random transport port",core_sip_transport_test},
|
||||
{ "Linphone interpret url", linphone_interpret_url_test },
|
||||
{ "LPConfig from buffer", linphone_lpconfig_from_buffer }
|
||||
{ "LPConfig from buffer", linphone_lpconfig_from_buffer },
|
||||
{ "Chat room", chat_root_test }
|
||||
};
|
||||
|
||||
test_suite_t setup_test_suite = {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,11 @@ const char *liblinphone_tester_file_prefix=".";
|
|||
#endif
|
||||
|
||||
/* TODO: have the same "static" for QNX and windows as above? */
|
||||
#ifdef ANDROID
|
||||
const char *liblinphone_tester_writable_dir_prefix = "/data/data/org.linphone.tester/cache";
|
||||
#else
|
||||
const char *liblinphone_tester_writable_dir_prefix = ".";
|
||||
#endif
|
||||
|
||||
const char *userhostsfile = "tester_hosts";
|
||||
|
||||
|
|
@ -199,7 +203,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f
|
|||
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.file_transfer_received=file_transfer_received;
|
||||
mgr->v_table.file_transfer_recv=file_transfer_received;
|
||||
mgr->v_table.file_transfer_send=file_transfer_send;
|
||||
mgr->v_table.file_transfer_progress_indication=file_transfer_progress_indication;
|
||||
mgr->v_table.is_composing_received=is_composing_received;
|
||||
|
|
@ -294,7 +298,7 @@ int liblinphone_tester_test_suite_index(const char *suite_name) {
|
|||
void liblinphone_tester_list_suites() {
|
||||
int j;
|
||||
for(j=0;j<liblinphone_tester_nb_test_suites();j++) {
|
||||
fprintf(stdout, "%s\n", liblinphone_tester_test_suite_name(j));
|
||||
liblinphone_tester_fprintf(stdout, "%s\n", liblinphone_tester_test_suite_name(j));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +306,7 @@ void liblinphone_tester_list_suite_tests(const char *suite_name) {
|
|||
int j;
|
||||
for( j = 0; j < liblinphone_tester_nb_tests(suite_name); j++) {
|
||||
const char *test_name = liblinphone_tester_test_name(suite_name, j);
|
||||
fprintf(stdout, "%s\n", test_name);
|
||||
liblinphone_tester_fprintf(stdout, "%s\n", test_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -443,4 +447,17 @@ int liblinphone_tester_run_tests(const char *suite_name, const char *test_name)
|
|||
CU_cleanup_registry();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int liblinphone_tester_fprintf(FILE * stream, const char * format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int result;
|
||||
#ifndef ANDROID
|
||||
result = vfprintf(stream,format,args);
|
||||
#else
|
||||
/*used by liblinphone tester to retrieve suite list*/
|
||||
result = 0;
|
||||
cunit_android_trace_handler(stream, format, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
743
tools/genapixml.py
Executable file
743
tools/genapixml.py
Executable file
|
|
@ -0,0 +1,743 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2014 Belledonne Communications SARL
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import string
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
import xml.dom.minidom as minidom
|
||||
|
||||
|
||||
class CObject:
|
||||
def __init__(self, name):
|
||||
self.name = name.strip()
|
||||
self.briefDescription = ''
|
||||
self.detailedDescription = None
|
||||
self.deprecated = False
|
||||
|
||||
|
||||
class CEnumValue(CObject):
|
||||
pass
|
||||
|
||||
|
||||
class CEnum(CObject):
|
||||
def __init__(self, name):
|
||||
CObject.__init__(self, name)
|
||||
self.values = []
|
||||
self.associatedTypedef = None
|
||||
|
||||
def addValue(self, value):
|
||||
self.values.append(value)
|
||||
|
||||
|
||||
class CStructMember(CObject):
|
||||
def __init__(self, name, t):
|
||||
CObject.__init__(self, name)
|
||||
self.ctype = t.strip()
|
||||
|
||||
|
||||
class CStruct(CObject):
|
||||
def __init__(self, name):
|
||||
CObject.__init__(self, name)
|
||||
self.members = []
|
||||
self.associatedTypedef = None
|
||||
|
||||
def addMember(self, member):
|
||||
self.members.append(member)
|
||||
|
||||
|
||||
class CTypedef(CObject):
|
||||
def __init__(self, name, definition):
|
||||
CObject.__init__(self, name)
|
||||
self.definition = definition.strip()
|
||||
|
||||
|
||||
class CArgument(CObject):
|
||||
def __init__(self, t, name = '', enums = [], structs = []):
|
||||
CObject.__init__(self, name)
|
||||
self.description = None
|
||||
self.containedType = None
|
||||
keywords = [ 'const', 'struct', 'enum', 'signed', 'unsigned', 'short', 'long', '*' ]
|
||||
fullySplittedType = []
|
||||
splittedType = t.strip().split(' ')
|
||||
for s in splittedType:
|
||||
if s.startswith('*'):
|
||||
fullySplittedType.append('*')
|
||||
if len(s) > 1:
|
||||
fullySplittedType.append(s[1:])
|
||||
elif s.endswith('*'):
|
||||
fullySplittedType.append(s[:-1])
|
||||
fullySplittedType.append('*')
|
||||
else:
|
||||
fullySplittedType.append(s)
|
||||
isStruct = False
|
||||
isEnum = False
|
||||
self.ctype = 'int' # Default to int so that the result is correct eg. for 'unsigned short'
|
||||
for s in fullySplittedType:
|
||||
if not s in keywords:
|
||||
self.ctype = s
|
||||
if s == 'struct':
|
||||
isStruct = True
|
||||
if s == 'enum':
|
||||
isEnum = True
|
||||
if isStruct:
|
||||
for st in structs:
|
||||
if st.associatedTypedef is not None:
|
||||
self.ctype = st.associatedTypedef.name
|
||||
elif isEnum:
|
||||
for e in enums:
|
||||
if e.associatedTypedef is not None:
|
||||
self.ctype = e.associatedTypedef.name
|
||||
if self.ctype == 'int' and 'int' not in fullySplittedType:
|
||||
if fullySplittedType[-1] == '*':
|
||||
fullySplittedType.insert(-1, 'int')
|
||||
else:
|
||||
fullySplittedType.append('int')
|
||||
self.completeType = ' '.join(fullySplittedType)
|
||||
|
||||
def __str__(self):
|
||||
return self.completeType + " " + self.name
|
||||
|
||||
|
||||
class CArgumentsList:
|
||||
def __init__(self):
|
||||
self.arguments = []
|
||||
|
||||
def addArgument(self, arg):
|
||||
self.arguments.append(arg)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.arguments)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.arguments[key]
|
||||
|
||||
def __str__(self):
|
||||
argstr = []
|
||||
for arg in self.arguments:
|
||||
argstr.append(str(arg))
|
||||
return ', '.join(argstr)
|
||||
|
||||
|
||||
class CFunction(CObject):
|
||||
def __init__(self, name, returnarg, argslist):
|
||||
CObject.__init__(self, name)
|
||||
self.returnArgument = returnarg
|
||||
self.arguments = argslist
|
||||
self.location = None
|
||||
|
||||
|
||||
class CEvent(CFunction):
|
||||
pass
|
||||
|
||||
|
||||
class CProperty:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.getter = None
|
||||
self.setter = None
|
||||
|
||||
|
||||
class CClass(CObject):
|
||||
def __init__(self, st):
|
||||
CObject.__init__(self, st.associatedTypedef.name)
|
||||
if st.deprecated or st.associatedTypedef.deprecated:
|
||||
self.deprecated = True
|
||||
if len(st.associatedTypedef.briefDescription) > 0:
|
||||
self.briefDescription = st.associatedTypedef.briefDescription
|
||||
elif len(st.briefDescription) > 0:
|
||||
self.briefDescription = st.briefDescription
|
||||
if st.associatedTypedef.detailedDescription is not None:
|
||||
self.detailedDescription = st.associatedTypedef.detailedDescription
|
||||
elif st.detailedDescription is not None:
|
||||
self.detailedDescription = st.detailedDescription
|
||||
self.__struct = st
|
||||
self.events = {}
|
||||
self.classMethods = {}
|
||||
self.instanceMethods = {}
|
||||
self.properties = {}
|
||||
self.__computeCFunctionPrefix()
|
||||
|
||||
def __computeCFunctionPrefix(self):
|
||||
self.cFunctionPrefix = ''
|
||||
first = True
|
||||
for l in self.name:
|
||||
if l.isupper() and not first:
|
||||
self.cFunctionPrefix += '_'
|
||||
self.cFunctionPrefix += l.lower()
|
||||
first = False
|
||||
self.cFunctionPrefix += '_'
|
||||
|
||||
def __addPropertyGetter(self, name, f):
|
||||
if not name in self.properties:
|
||||
prop = CProperty(name)
|
||||
self.properties[name] = prop
|
||||
self.properties[name].getter = f
|
||||
|
||||
def __addPropertySetter(self, name, f):
|
||||
if not name in self.properties:
|
||||
prop = CProperty(name)
|
||||
self.properties[name] = prop
|
||||
self.properties[name].setter = f
|
||||
|
||||
def __addClassMethod(self, f):
|
||||
name = f.name[len(self.cFunctionPrefix):]
|
||||
if string.find(name, 'get_') == 0 and len(f.arguments) == 0:
|
||||
self.__addPropertyGetter(name[4:], f)
|
||||
elif string.find(name, 'is_') == 0 and len(f.arguments) == 0 and f.returnArgument.ctype == 'bool_t':
|
||||
self.__addPropertyGetter(name[3:], f)
|
||||
elif string.rfind(name, '_enabled') == (len(name) - 8) and len(f.arguments) == 0 and f.returnArgument.ctype == 'bool_t':
|
||||
self.__addPropertyGetter(name, f)
|
||||
elif string.find(name, 'set_') == 0 and len(f.arguments) == 1:
|
||||
self.__addPropertySetter(name[4:], f)
|
||||
elif string.find(name, 'enable_') == 0 and len(f.arguments) == 1 and f.arguments[0].ctype == 'bool_t':
|
||||
self.__addPropertySetter(name[7:] + '_enabled', f)
|
||||
else:
|
||||
if not f.name in self.classMethods:
|
||||
self.classMethods[f.name] = f
|
||||
|
||||
def __addInstanceMethod(self, f):
|
||||
name = f.name[len(self.cFunctionPrefix):]
|
||||
if string.find(name, 'get_') == 0 and len(f.arguments) == 1:
|
||||
self.__addPropertyGetter(name[4:], f)
|
||||
elif string.find(name, 'is_') == 0 and len(f.arguments) == 1 and f.returnArgument.ctype == 'bool_t':
|
||||
self.__addPropertyGetter(name[3:], f)
|
||||
elif string.rfind(name, '_enabled') == (len(name) - 8) and len(f.arguments) == 1 and f.returnArgument.ctype == 'bool_t':
|
||||
self.__addPropertyGetter(name, f)
|
||||
elif string.find(name, 'set_') == 0 and len(f.arguments) == 2:
|
||||
self.__addPropertySetter(name[4:], f)
|
||||
elif string.find(name, 'enable_') == 0 and len(f.arguments) == 2 and f.arguments[1].ctype == 'bool_t':
|
||||
self.__addPropertySetter(name[7:] + '_enabled', f)
|
||||
else:
|
||||
if not f.name in self.instanceMethods:
|
||||
self.instanceMethods[f.name] = f
|
||||
|
||||
def addEvent(self, ev):
|
||||
if not ev.name in self.events:
|
||||
self.events[ev.name] = ev
|
||||
|
||||
def addMethod(self, f):
|
||||
if len(f.arguments) > 0 and f.arguments[0].ctype == self.name:
|
||||
self.__addInstanceMethod(f)
|
||||
else:
|
||||
self.__addClassMethod(f)
|
||||
|
||||
|
||||
class Project:
|
||||
def __init__(self):
|
||||
self.verbose = False
|
||||
self.prettyPrint = False
|
||||
self.enums = []
|
||||
self.__structs = []
|
||||
self.__typedefs = []
|
||||
self.__events = []
|
||||
self.__functions = []
|
||||
self.classes = []
|
||||
|
||||
def add(self, elem):
|
||||
if isinstance(elem, CClass):
|
||||
if self.verbose:
|
||||
print("Adding class " + elem.name)
|
||||
self.classes.append(elem)
|
||||
elif isinstance(elem, CEnum):
|
||||
if self.verbose:
|
||||
print("Adding enum " + elem.name)
|
||||
for ev in elem.values:
|
||||
print("\t" + ev.name)
|
||||
self.enums.append(elem)
|
||||
elif isinstance(elem, CStruct):
|
||||
if self.verbose:
|
||||
print("Adding struct " + elem.name)
|
||||
for sm in elem.members:
|
||||
print("\t" + sm.ctype + " " + sm.name)
|
||||
self.__structs.append(elem)
|
||||
elif isinstance(elem, CTypedef):
|
||||
if self.verbose:
|
||||
print("Adding typedef " + elem.name)
|
||||
print("\t" + elem.definition)
|
||||
self.__typedefs.append(elem)
|
||||
elif isinstance(elem, CEvent):
|
||||
if self.verbose:
|
||||
print("Adding event " + elem.name)
|
||||
print("\tReturns: " + elem.returnArgument.ctype)
|
||||
print("\tArguments: " + str(elem.arguments))
|
||||
self.__events.append(elem)
|
||||
elif isinstance(elem, CFunction):
|
||||
if self.verbose:
|
||||
print("Adding function " + elem.name)
|
||||
print("\tReturns: " + elem.returnArgument.ctype)
|
||||
print("\tArguments: " + str(elem.arguments))
|
||||
self.__functions.append(elem)
|
||||
|
||||
def __cleanDescription(self, descriptionNode):
|
||||
for para in descriptionNode.findall('./para'):
|
||||
for n in para.findall('./parameterlist'):
|
||||
para.remove(n)
|
||||
for n in para.findall("./simplesect[@kind='return']"):
|
||||
para.remove(n)
|
||||
for n in para.findall("./simplesect[@kind='see']"):
|
||||
t = ''.join(n.itertext())
|
||||
n.clear()
|
||||
n.tag = 'see'
|
||||
n.text = t
|
||||
for n in para.findall("./simplesect[@kind='note']"):
|
||||
n.tag = 'note'
|
||||
n.attrib = {}
|
||||
for n in para.findall(".//xrefsect"):
|
||||
para.remove(n)
|
||||
for n in para.findall('.//ref'):
|
||||
n.attrib = {}
|
||||
for n in para.findall(".//mslist"):
|
||||
para.remove(n)
|
||||
if descriptionNode.tag == 'parameterdescription':
|
||||
descriptionNode.tag = 'description'
|
||||
if descriptionNode.tag == 'simplesect':
|
||||
descriptionNode.tag = 'description'
|
||||
descriptionNode.attrib = {}
|
||||
return descriptionNode
|
||||
|
||||
def __discoverClasses(self):
|
||||
for td in self.__typedefs:
|
||||
if string.find(td.definition, 'enum ') == 0:
|
||||
for e in self.enums:
|
||||
if (e.associatedTypedef is None) and td.definition[5:] == e.name:
|
||||
e.associatedTypedef = td
|
||||
break
|
||||
elif string.find(td.definition, 'struct ') == 0:
|
||||
structFound = False
|
||||
for st in self.__structs:
|
||||
if (st.associatedTypedef is None) and td.definition[7:] == st.name:
|
||||
st.associatedTypedef = td
|
||||
structFound = True
|
||||
break
|
||||
if not structFound:
|
||||
name = td.definition[7:]
|
||||
print("Structure with no associated typedef: " + name)
|
||||
st = CStruct(name)
|
||||
st.associatedTypedef = td
|
||||
self.add(st)
|
||||
for td in self.__typedefs:
|
||||
if string.find(td.definition, 'struct ') == 0:
|
||||
for st in self.__structs:
|
||||
if st.associatedTypedef == td:
|
||||
self.add(CClass(st))
|
||||
break
|
||||
elif ('Linphone' + td.definition) == td.name:
|
||||
st = CStruct(td.name)
|
||||
st.associatedTypedef = td
|
||||
self.add(st)
|
||||
self.add(CClass(st))
|
||||
# Sort classes by length of name (longest first), so that methods are put in the right class
|
||||
self.classes.sort(key = lambda c: len(c.name), reverse = True)
|
||||
for e in self.__events:
|
||||
for c in self.classes:
|
||||
if string.find(e.name, c.name) == 0:
|
||||
c.addEvent(e)
|
||||
for f in self.__functions:
|
||||
for c in self.classes:
|
||||
if c.cFunctionPrefix == f.name[0 : len(c.cFunctionPrefix)]:
|
||||
c.addMethod(f)
|
||||
break
|
||||
|
||||
def __parseCEnumValue(self, node):
|
||||
ev = CEnumValue(node.find('./name').text)
|
||||
deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']")
|
||||
if deprecatedNode is not None:
|
||||
ev.deprecated = True
|
||||
ev.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip()
|
||||
ev.detailedDescription = self.__cleanDescription(node.find('./detaileddescription'))
|
||||
return ev
|
||||
|
||||
def __parseCEnumMemberdef(self, node):
|
||||
e = CEnum(node.find('./name').text)
|
||||
deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']")
|
||||
if deprecatedNode is not None:
|
||||
e.deprecated = True
|
||||
e.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip()
|
||||
e.detailedDescription = self.__cleanDescription(node.find('./detaileddescription'))
|
||||
enumvalues = node.findall("enumvalue[@prot='public']")
|
||||
for enumvalue in enumvalues:
|
||||
ev = self.__parseCEnumValue(enumvalue)
|
||||
e.addValue(ev)
|
||||
return e
|
||||
|
||||
def __findCEnum(self, tree):
|
||||
memberdefs = tree.findall("./compounddef[@kind='group']/sectiondef[@kind='enum']/memberdef[@kind='enum'][@prot='public']")
|
||||
for m in memberdefs:
|
||||
e = self.__parseCEnumMemberdef(m)
|
||||
self.add(e)
|
||||
|
||||
def __parseCStructMember(self, node, structname):
|
||||
name = node.find('./name').text
|
||||
definition = node.find('./definition').text
|
||||
t = definition[0:string.find(definition, structname + "::" + name)]
|
||||
sm = CStructMember(name, t)
|
||||
deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']")
|
||||
if deprecatedNode is not None:
|
||||
sm.deprecated = True
|
||||
sm.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip()
|
||||
sm.detailedDescription = self.__cleanDescription(node.find('./detaileddescription'))
|
||||
return sm
|
||||
|
||||
def __parseCStructCompounddef(self, node):
|
||||
s = CStruct(node.find('./compoundname').text)
|
||||
deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']")
|
||||
if deprecatedNode is not None:
|
||||
s.deprecated = True
|
||||
s.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip()
|
||||
s.detailedDescription = self.__cleanDescription(node.find('./detaileddescription'))
|
||||
structmembers = node.findall("sectiondef/memberdef[@kind='variable'][@prot='public']")
|
||||
for structmember in structmembers:
|
||||
sm = self.__parseCStructMember(structmember, s.name)
|
||||
s.addMember(sm)
|
||||
return s
|
||||
|
||||
def __findCStruct(self, tree):
|
||||
compounddefs = tree.findall("./compounddef[@kind='struct'][@prot='public']")
|
||||
for c in compounddefs:
|
||||
s = self.__parseCStructCompounddef(c)
|
||||
self.add(s)
|
||||
|
||||
def __parseCTypedefMemberdef(self, node):
|
||||
name = node.find('./name').text
|
||||
definition = node.find('./definition').text
|
||||
if string.find(definition, 'typedef ') == 0:
|
||||
definition = definition[8 :]
|
||||
if string.rfind(name, 'Cb') == len(name) - 2:
|
||||
pos = string.find(definition, "(*")
|
||||
if pos == -1:
|
||||
return None
|
||||
returntype = definition[0:pos].strip()
|
||||
if returntype != "void":
|
||||
return None
|
||||
returnarg = CArgument(returntype, enums = self.enums, structs = self.__structs)
|
||||
definition = definition[pos + 2 :]
|
||||
pos = string.find(definition, "(")
|
||||
definition = definition[pos + 1 : -1]
|
||||
argslist = CArgumentsList()
|
||||
for argdef in definition.split(', '):
|
||||
argType = ''
|
||||
starPos = string.rfind(argdef, '*')
|
||||
spacePos = string.rfind(argdef, ' ')
|
||||
if starPos != -1:
|
||||
argType = argdef[0 : starPos + 1]
|
||||
argName = argdef[starPos + 1 :]
|
||||
elif spacePos != -1:
|
||||
argType = argdef[0 : spacePos]
|
||||
argName = argdef[spacePos + 1 :]
|
||||
argslist.addArgument(CArgument(argType, argName, self.enums, self.__structs))
|
||||
if len(argslist) > 0:
|
||||
paramdescs = node.findall("detaileddescription/para/parameterlist[@kind='param']/parameteritem")
|
||||
if paramdescs:
|
||||
for arg in argslist.arguments:
|
||||
for paramdesc in paramdescs:
|
||||
if arg.name == paramdesc.find('./parameternamelist').find('./parametername').text:
|
||||
arg.description = self.__cleanDescription(paramdesc.find('./parameterdescription'))
|
||||
missingDocWarning = ''
|
||||
for arg in argslist.arguments:
|
||||
if arg.description == None:
|
||||
missingDocWarning += "\t'" + arg.name + "' parameter not documented\n";
|
||||
if missingDocWarning != '':
|
||||
print(name + ":\n" + missingDocWarning)
|
||||
f = CEvent(name, returnarg, argslist)
|
||||
deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']")
|
||||
if deprecatedNode is not None:
|
||||
f.deprecated = True
|
||||
f.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip()
|
||||
f.detailedDescription = self.__cleanDescription(node.find('./detaileddescription'))
|
||||
return f
|
||||
else:
|
||||
pos = string.rfind(definition, " " + name)
|
||||
if pos != -1:
|
||||
definition = definition[0 : pos]
|
||||
td = CTypedef(name, definition)
|
||||
deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']")
|
||||
if deprecatedNode is not None:
|
||||
td.deprecated = True
|
||||
td.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip()
|
||||
td.detailedDescription = self.__cleanDescription(node.find('./detaileddescription'))
|
||||
return td
|
||||
return None
|
||||
|
||||
def __findCTypedef(self, tree):
|
||||
memberdefs = tree.findall("./compounddef[@kind='group']/sectiondef[@kind='typedef']/memberdef[@kind='typedef'][@prot='public']")
|
||||
for m in memberdefs:
|
||||
td = self.__parseCTypedefMemberdef(m)
|
||||
self.add(td)
|
||||
|
||||
def __parseCFunctionMemberdef(self, node):
|
||||
missingDocWarning = ''
|
||||
name = node.find('./name').text
|
||||
t = ''.join(node.find('./type').itertext())
|
||||
returnarg = CArgument(t, enums = self.enums, structs = self.__structs)
|
||||
returndesc = node.find("./detaileddescription/para/simplesect[@kind='return']")
|
||||
if returndesc is not None:
|
||||
if returnarg.ctype == 'MSList':
|
||||
n = returndesc.find('.//mslist')
|
||||
if n is not None:
|
||||
returnarg.containedType = n.text
|
||||
returnarg.description = self.__cleanDescription(returndesc)
|
||||
elif returnarg.completeType != 'void':
|
||||
missingDocWarning += "\tReturn value is not documented\n"
|
||||
argslist = CArgumentsList()
|
||||
argslistNode = node.findall('./param')
|
||||
for argNode in argslistNode:
|
||||
argType = ''.join(argNode.find('./type').itertext())
|
||||
argName = ''
|
||||
argNameNode = argNode.find('./declname')
|
||||
if argNameNode is not None:
|
||||
argName = ''.join(argNameNode.itertext())
|
||||
if argType != 'void':
|
||||
argslist.addArgument(CArgument(argType, argName, self.enums, self.__structs))
|
||||
if len(argslist) > 0:
|
||||
paramdescs = node.findall("./detaileddescription/para/parameterlist[@kind='param']/parameteritem")
|
||||
if paramdescs:
|
||||
for arg in argslist.arguments:
|
||||
for paramdesc in paramdescs:
|
||||
if arg.name == paramdesc.find('./parameternamelist').find('./parametername').text:
|
||||
if arg.ctype == 'MSList':
|
||||
n = paramdesc.find('.//mslist')
|
||||
if n is not None:
|
||||
arg.containedType = n.text
|
||||
arg.description = self.__cleanDescription(paramdesc.find('./parameterdescription'))
|
||||
missingDocWarning = ''
|
||||
for arg in argslist.arguments:
|
||||
if arg.description == None:
|
||||
missingDocWarning += "\t'" + arg.name + "' parameter not documented\n";
|
||||
f = CFunction(name, returnarg, argslist)
|
||||
deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']")
|
||||
if deprecatedNode is not None:
|
||||
f.deprecated = True
|
||||
f.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip()
|
||||
f.detailedDescription = self.__cleanDescription(node.find('./detaileddescription'))
|
||||
if f.briefDescription == '' and ''.join(f.detailedDescription.itertext()).strip() == '':
|
||||
return None
|
||||
locationNode = node.find('./location')
|
||||
if locationNode is not None:
|
||||
f.location = locationNode.get('file')
|
||||
if not f.location.endswith('.h'):
|
||||
missingDocWarning += "\tNot documented in a header file ('" + f.location + "')\n";
|
||||
if missingDocWarning != '':
|
||||
print(name + ":\n" + missingDocWarning)
|
||||
return f
|
||||
|
||||
def __findCFunction(self, tree):
|
||||
memberdefs = tree.findall("./compounddef[@kind='group']/sectiondef[@kind='func']/memberdef[@kind='function'][@prot='public'][@static='no']")
|
||||
for m in memberdefs:
|
||||
f = self.__parseCFunctionMemberdef(m)
|
||||
self.add(f)
|
||||
|
||||
def initFromFiles(self, xmlfiles):
|
||||
trees = []
|
||||
for f in xmlfiles:
|
||||
tree = None
|
||||
try:
|
||||
if self.verbose:
|
||||
print("Parsing XML file: " + f.name)
|
||||
tree = ET.parse(f)
|
||||
except ET.ParseError as e:
|
||||
print(e)
|
||||
if tree is not None:
|
||||
trees.append(tree)
|
||||
for tree in trees:
|
||||
self.__findCEnum(tree)
|
||||
for tree in trees:
|
||||
self.__findCStruct(tree)
|
||||
for tree in trees:
|
||||
self.__findCTypedef(tree)
|
||||
for tree in trees:
|
||||
self.__findCFunction(tree)
|
||||
self.__discoverClasses()
|
||||
|
||||
def initFromDir(self, xmldir):
|
||||
files = [ os.path.join(xmldir, f) for f in os.listdir(xmldir) if (os.path.isfile(os.path.join(xmldir, f)) and f.endswith('.xml')) ]
|
||||
self.initFromFiles(files)
|
||||
|
||||
def check(self):
|
||||
for c in self.classes:
|
||||
for name, p in c.properties.iteritems():
|
||||
if p.getter is None and p.setter is not None:
|
||||
print("Property '" + name + "' of class '" + c.name + "' has a setter but no getter")
|
||||
|
||||
|
||||
class Generator:
|
||||
def __init__(self, outputfile):
|
||||
self.__outputfile = outputfile
|
||||
|
||||
def __generateEnum(self, cenum, enumsNode):
|
||||
enumNodeAttributes = { 'name' : cenum.name, 'deprecated' : str(cenum.deprecated).lower() }
|
||||
if cenum.associatedTypedef is not None:
|
||||
enumNodeAttributes['name'] = cenum.associatedTypedef.name
|
||||
enumNode = ET.SubElement(enumsNode, 'enum', enumNodeAttributes)
|
||||
if cenum.briefDescription != '':
|
||||
enumBriefDescriptionNode = ET.SubElement(enumNode, 'briefdescription')
|
||||
enumBriefDescriptionNode.text = cenum.briefDescription
|
||||
enumNode.append(cenum.detailedDescription)
|
||||
if len(cenum.values) > 0:
|
||||
enumValuesNode = ET.SubElement(enumNode, 'values')
|
||||
for value in cenum.values:
|
||||
enumValuesNodeAttributes = { 'name' : value.name, 'deprecated' : str(value.deprecated).lower() }
|
||||
valueNode = ET.SubElement(enumValuesNode, 'value', enumValuesNodeAttributes)
|
||||
if value.briefDescription != '':
|
||||
valueBriefDescriptionNode = ET.SubElement(valueNode, 'briefdescription')
|
||||
valueBriefDescriptionNode.text = value.briefDescription
|
||||
valueNode.append(value.detailedDescription)
|
||||
|
||||
def __generateFunction(self, parentNode, nodeName, f):
|
||||
functionAttributes = { 'name' : f.name, 'deprecated' : str(f.deprecated).lower() }
|
||||
if f.location is not None:
|
||||
functionAttributes['location'] = f.location
|
||||
functionNode = ET.SubElement(parentNode, nodeName, functionAttributes)
|
||||
returnValueAttributes = { 'type' : f.returnArgument.ctype, 'completetype' : f.returnArgument.completeType }
|
||||
if f.returnArgument.containedType is not None:
|
||||
returnValueAttributes['containedtype'] = f.returnArgument.containedType
|
||||
returnValueNode = ET.SubElement(functionNode, 'return', returnValueAttributes)
|
||||
if f.returnArgument.description is not None:
|
||||
returnValueNode.append(f.returnArgument.description)
|
||||
argumentsNode = ET.SubElement(functionNode, 'arguments')
|
||||
for arg in f.arguments:
|
||||
argumentNodeAttributes = { 'name' : arg.name, 'type' : arg.ctype, 'completetype' : arg.completeType }
|
||||
if arg.containedType is not None:
|
||||
argumentNodeAttributes['containedtype'] = arg.containedType
|
||||
argumentNode = ET.SubElement(argumentsNode, 'argument', argumentNodeAttributes)
|
||||
if arg.description is not None:
|
||||
argumentNode.append(arg.description)
|
||||
if f.briefDescription != '':
|
||||
functionBriefDescriptionNode = ET.SubElement(functionNode, 'briefdescription')
|
||||
functionBriefDescriptionNode.text = f.briefDescription
|
||||
functionNode.append(f.detailedDescription)
|
||||
|
||||
def __generateClass(self, cclass, classesNode):
|
||||
# Do not include classes that contain nothing
|
||||
if len(cclass.events) == 0 and len(cclass.classMethods) == 0 and \
|
||||
len(cclass.instanceMethods) == 0 and len(cclass.properties) == 0:
|
||||
return
|
||||
# Check the capabilities of the class
|
||||
has_ref_method = False
|
||||
has_unref_method = False
|
||||
has_destroy_method = False
|
||||
for methodname in cclass.instanceMethods:
|
||||
methodname_without_prefix = methodname.replace(cclass.cFunctionPrefix, '')
|
||||
if methodname_without_prefix == 'ref':
|
||||
has_ref_method = True
|
||||
elif methodname_without_prefix == 'unref':
|
||||
has_unref_method = True
|
||||
elif methodname_without_prefix == 'destroy':
|
||||
has_destroy_method = True
|
||||
refcountable = False
|
||||
destroyable = False
|
||||
if has_ref_method and has_unref_method:
|
||||
refcountable = True
|
||||
if has_destroy_method:
|
||||
destroyable = True
|
||||
classNodeAttributes = {
|
||||
'name' : cclass.name,
|
||||
'cfunctionprefix' : cclass.cFunctionPrefix,
|
||||
'deprecated' : str(cclass.deprecated).lower(),
|
||||
'refcountable' : str(refcountable).lower(),
|
||||
'destroyable' : str(destroyable).lower()
|
||||
}
|
||||
# Generate the XML node for the class
|
||||
classNode = ET.SubElement(classesNode, 'class', classNodeAttributes)
|
||||
if len(cclass.events) > 0:
|
||||
eventsNode = ET.SubElement(classNode, 'events')
|
||||
eventnames = []
|
||||
for eventname in cclass.events:
|
||||
eventnames.append(eventname)
|
||||
eventnames.sort()
|
||||
for eventname in eventnames:
|
||||
self.__generateFunction(eventsNode, 'event', cclass.events[eventname])
|
||||
if len(cclass.classMethods) > 0:
|
||||
classMethodsNode = ET.SubElement(classNode, 'classmethods')
|
||||
methodnames = []
|
||||
for methodname in cclass.classMethods:
|
||||
methodnames.append(methodname)
|
||||
methodnames.sort()
|
||||
for methodname in methodnames:
|
||||
self.__generateFunction(classMethodsNode, 'classmethod', cclass.classMethods[methodname])
|
||||
if len(cclass.instanceMethods) > 0:
|
||||
instanceMethodsNode = ET.SubElement(classNode, 'instancemethods')
|
||||
methodnames = []
|
||||
for methodname in cclass.instanceMethods:
|
||||
methodnames.append(methodname)
|
||||
methodnames.sort()
|
||||
for methodname in methodnames:
|
||||
self.__generateFunction(instanceMethodsNode, 'instancemethod', cclass.instanceMethods[methodname])
|
||||
if len(cclass.properties) > 0:
|
||||
propertiesNode = ET.SubElement(classNode, 'properties')
|
||||
propnames = []
|
||||
for propname in cclass.properties:
|
||||
propnames.append(propname)
|
||||
propnames.sort()
|
||||
for propname in propnames:
|
||||
propertyNodeAttributes = { 'name' : propname }
|
||||
propertyNode = ET.SubElement(propertiesNode, 'property', propertyNodeAttributes)
|
||||
if cclass.properties[propname].getter is not None:
|
||||
self.__generateFunction(propertyNode, 'getter', cclass.properties[propname].getter)
|
||||
if cclass.properties[propname].setter is not None:
|
||||
self.__generateFunction(propertyNode, 'setter', cclass.properties[propname].setter)
|
||||
if cclass.briefDescription != '':
|
||||
classBriefDescriptionNode = ET.SubElement(classNode, 'briefdescription')
|
||||
classBriefDescriptionNode.text = cclass.briefDescription
|
||||
classNode.append(cclass.detailedDescription)
|
||||
|
||||
def generate(self, project):
|
||||
print("Generating XML document of Linphone API to '" + self.__outputfile.name + "'")
|
||||
apiNode = ET.Element('api')
|
||||
project.enums.sort(key = lambda e: e.name)
|
||||
if len(project.enums) > 0:
|
||||
enumsNode = ET.SubElement(apiNode, 'enums')
|
||||
for cenum in project.enums:
|
||||
self.__generateEnum(cenum, enumsNode)
|
||||
if len(project.classes) > 0:
|
||||
classesNode = ET.SubElement(apiNode, 'classes')
|
||||
project.classes.sort(key = lambda c: c.name)
|
||||
for cclass in project.classes:
|
||||
self.__generateClass(cclass, classesNode)
|
||||
s = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
s += ET.tostring(apiNode, 'utf-8')
|
||||
if project.prettyPrint:
|
||||
s = minidom.parseString(s).toprettyxml(indent='\t')
|
||||
self.__outputfile.write(s)
|
||||
|
||||
|
||||
|
||||
def main(argv = None):
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
argparser = argparse.ArgumentParser(description="Generate XML version of the Linphone API.")
|
||||
argparser.add_argument('-o', '--outputfile', metavar='outputfile', type=argparse.FileType('w'), help="Output XML file describing the Linphone API.")
|
||||
argparser.add_argument('--verbose', help="Increase output verbosity", action='store_true')
|
||||
argparser.add_argument('--pretty', help="XML pretty print", action='store_true')
|
||||
argparser.add_argument('xmldir', help="XML directory generated by doxygen.")
|
||||
args = argparser.parse_args()
|
||||
if args.outputfile == None:
|
||||
args.outputfile = open('api.xml', 'w')
|
||||
project = Project()
|
||||
if args.verbose:
|
||||
project.verbose = True
|
||||
if args.pretty:
|
||||
project.prettyPrint = True
|
||||
project.initFromDir(args.xmldir)
|
||||
project.check()
|
||||
gen = Generator(args.outputfile)
|
||||
gen.generate(project)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
4
tools/python/.gitignore
vendored
Normal file
4
tools/python/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
*.pyc
|
||||
build
|
||||
linphone.c
|
||||
.kdev*
|
||||
116
tools/python/apixml2python.py
Executable file
116
tools/python/apixml2python.py
Executable file
|
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2014 Belledonne Communications SARL
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pystache
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
sys.path.append(os.path.realpath(__file__))
|
||||
from apixml2python.linphone import LinphoneModule
|
||||
|
||||
|
||||
blacklisted_classes = [
|
||||
'LinphoneTunnel',
|
||||
'LinphoneTunnelConfig'
|
||||
]
|
||||
blacklisted_events = [
|
||||
'LinphoneCoreInfoReceivedCb', # missing LinphoneInfoMessage
|
||||
'LinphoneCoreNotifyReceivedCb', # missing LinphoneContent
|
||||
'LinphoneCoreFileTransferProgressIndicationCb', # missing LinphoneContent
|
||||
'LinphoneCoreFileTransferRecvCb', # missing LinphoneContent
|
||||
'LinphoneCoreFileTransferSendCb' # missing LinphoneContent
|
||||
]
|
||||
blacklisted_functions = [
|
||||
'linphone_call_log_get_local_stats', # missing rtp_stats_t
|
||||
'linphone_call_log_get_remote_stats', # missing rtp_stats_t
|
||||
'linphone_call_params_get_privacy', # missing LinphonePrivacyMask
|
||||
'linphone_call_params_set_privacy', # missing LinphonePrivacyMask
|
||||
'linphone_chat_message_get_file_transfer_information', # missing LinphoneContent
|
||||
'linphone_chat_message_start_file_download', # to be handwritten because of callback
|
||||
'linphone_chat_message_state_to_string', # There is no use to wrap this function
|
||||
'linphone_chat_room_create_file_transfer_message', # missing LinphoneContent
|
||||
'linphone_core_can_we_add_call', # private function
|
||||
'linphone_core_get_audio_port_range', # to be handwritten because of result via arguments
|
||||
'linphone_core_get_default_proxy', # to be handwritten because of double pointer indirection
|
||||
'linphone_core_get_sip_transports', # missing LCSipTransports
|
||||
'linphone_core_get_sip_transports_used', # missing LCSipTransports
|
||||
'linphone_core_get_supported_video_sizes', # missing MSVideoSizeDef
|
||||
'linphone_core_get_video_policy', # missing LinphoneVideoPolicy
|
||||
'linphone_core_get_video_port_range', # to be handwritten because of result via arguments
|
||||
'linphone_core_publish', # missing LinphoneContent
|
||||
'linphone_core_serialize_logs', # There is no use to wrap this function
|
||||
'linphone_core_set_log_file', # There is no use to wrap this function
|
||||
'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module
|
||||
'linphone_core_set_log_level', # There is no use to wrap this function
|
||||
'linphone_core_set_video_policy', # missing LinphoneVideoPolicy
|
||||
'linphone_core_set_sip_transports', # missing LCSipTransports
|
||||
'linphone_core_subscribe', # missing LinphoneContent
|
||||
'linphone_event_notify', # missing LinphoneContent
|
||||
'linphone_event_send_publish', # missing LinphoneContent
|
||||
'linphone_event_send_subscribe', # missing LinphoneContent
|
||||
'linphone_event_update_publish', # missing LinphoneContent
|
||||
'linphone_event_update_subscribe', # missing LinphoneContent
|
||||
'linphone_proxy_config_get_privacy', # missing LinphonePrivacyMask
|
||||
'linphone_proxy_config_normalize_number', # to be handwritten because of result via arguments
|
||||
'linphone_proxy_config_set_file_transfer_server', # defined but not implemented in linphone core
|
||||
'linphone_proxy_config_set_privacy', # missing LinphonePrivacyMask
|
||||
'linphone_tunnel_get_http_proxy', # to be handwritten because of double pointer indirection
|
||||
'lp_config_for_each_entry', # to be handwritten because of callback
|
||||
'lp_config_for_each_section', # to be handwritten because of callback
|
||||
'lp_config_get_range', # to be handwritten because of result via arguments
|
||||
'lp_config_load_dict_to_section', # missing LinphoneDictionary
|
||||
'lp_config_section_to_dict' # missing LinphoneDictionary
|
||||
]
|
||||
hand_written_functions = [
|
||||
'linphone_chat_room_send_message2',
|
||||
'linphone_core_get_video_devices',
|
||||
'linphone_core_new',
|
||||
'linphone_core_new_with_config'
|
||||
]
|
||||
|
||||
def generate(apixmlfile, outputfile):
|
||||
tree = ET.parse(apixmlfile)
|
||||
renderer = pystache.Renderer()
|
||||
m = LinphoneModule(tree, blacklisted_classes, blacklisted_events, blacklisted_functions, hand_written_functions)
|
||||
os.chdir('apixml2python')
|
||||
tmpfilename = outputfile.name + '.tmp'
|
||||
f = open(tmpfilename, 'w')
|
||||
f.write(renderer.render(m))
|
||||
f.close()
|
||||
f = open(tmpfilename, 'rU')
|
||||
for line in f:
|
||||
outputfile.write(line)
|
||||
f.close()
|
||||
os.unlink(tmpfilename)
|
||||
|
||||
|
||||
def main(argv = None):
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
argparser = argparse.ArgumentParser(description="Generate a Python wrapper of the Linphone API.")
|
||||
argparser.add_argument('-o', '--outputfile', metavar='outputfile', type=argparse.FileType('w'), help="Output C file containing the code of the Python wrapper.")
|
||||
argparser.add_argument('apixmlfile', help="XML file of the Linphone API generated by genapixml.py.")
|
||||
args = argparser.parse_args()
|
||||
if args.outputfile == None:
|
||||
args.outputfile = open('linphone.c', 'w')
|
||||
generate(args.apixmlfile, args.outputfile)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
0
tools/python/apixml2python/__init__.py
Normal file
0
tools/python/apixml2python/__init__.py
Normal file
14
tools/python/apixml2python/handwritten_declarations.mustache
Normal file
14
tools/python/apixml2python/handwritten_declarations.mustache
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
static PyObject * pylinphone_Core_get_video_devices(PyObject *self, void *closure);
|
||||
|
||||
static PyTypeObject pylinphone_VideoSizeType;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
MSVideoSize vs;
|
||||
} pylinphone_VideoSizeObject;
|
||||
|
||||
int PyLinphoneVideoSize_Check(PyObject *p);
|
||||
MSVideoSize PyLinphoneVideoSize_AsMSVideoSize(PyObject *obj);
|
||||
PyObject * PyLinphoneVideoSize_FromMSVideoSize(MSVideoSize vs);
|
||||
time_t PyDateTime_As_time_t(PyObject *obj);
|
||||
PyObject * PyDateTime_From_time_t(time_t t);
|
||||
481
tools/python/apixml2python/handwritten_definitions.mustache
Normal file
481
tools/python/apixml2python/handwritten_definitions.mustache
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
static void pylinphone_dispatch_messages(void) {
|
||||
#ifdef WIN32
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, 1)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void pylinphone_log(const char *level, int indent, const char *fmt, va_list args) {
|
||||
static int current_indent = 1;
|
||||
PyObject *linphone_module;
|
||||
PyGILState_STATE gstate;
|
||||
|
||||
gstate = PyGILState_Ensure();
|
||||
linphone_module = PyImport_ImportModule("linphone.linphone");
|
||||
if ((linphone_module != NULL) && PyObject_HasAttrString(linphone_module, "__log_handler")) {
|
||||
PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler");
|
||||
if ((log_handler != NULL) && PyCallable_Check(log_handler)) {
|
||||
char logstr[4096];
|
||||
int i = 0;
|
||||
if (indent == -1) current_indent--;
|
||||
if (current_indent < 1) current_indent = 1;
|
||||
if ((indent >= -1) && (indent <= 1)) {
|
||||
for (i = 0; i < current_indent; i++) {
|
||||
logstr[i] = '\t';
|
||||
}
|
||||
}
|
||||
if (indent == 1) current_indent++;
|
||||
if (vsnprintf(logstr + i, sizeof(logstr) - i, fmt, args) > 0) {
|
||||
if (PyEval_CallObject(log_handler, Py_BuildValue("ss", level, logstr)) == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
Py_DECREF(log_handler);
|
||||
}
|
||||
Py_DECREF(linphone_module);
|
||||
}
|
||||
PyGILState_Release(gstate);
|
||||
}
|
||||
|
||||
static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
pylinphone_log("debug", indent, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static const char * pylinphone_ortp_log_level_to_string(OrtpLogLevel lev) {
|
||||
switch (lev) {
|
||||
default:
|
||||
case ORTP_DEBUG:
|
||||
return "debug";
|
||||
case ORTP_MESSAGE:
|
||||
return "info";
|
||||
case ORTP_WARNING:
|
||||
return "warning";
|
||||
case ORTP_ERROR:
|
||||
return "error";
|
||||
case ORTP_FATAL:
|
||||
return "critical";
|
||||
case ORTP_TRACE:
|
||||
return "debug";
|
||||
}
|
||||
}
|
||||
|
||||
static void pylinphone_module_log_handler(OrtpLogLevel lev, const char *fmt, va_list args) {
|
||||
PyGILState_STATE gstate;
|
||||
PyObject *linphone_module;
|
||||
const char *level;
|
||||
|
||||
gstate = PyGILState_Ensure();
|
||||
linphone_module = PyImport_ImportModule("linphone.linphone");
|
||||
level = pylinphone_ortp_log_level_to_string(lev);
|
||||
if ((linphone_module != NULL) && PyObject_HasAttrString(linphone_module, "__log_handler")) {
|
||||
PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler");
|
||||
if ((log_handler != NULL) && PyCallable_Check(log_handler)) {
|
||||
char logstr[4096];
|
||||
if (vsnprintf(logstr, sizeof(logstr), fmt, args) > 0) {
|
||||
if (PyEval_CallObject(log_handler, Py_BuildValue("ss", level, logstr)) == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
Py_DECREF(log_handler);
|
||||
}
|
||||
Py_DECREF(linphone_module);
|
||||
}
|
||||
PyGILState_Release(gstate);
|
||||
}
|
||||
|
||||
static void pylinphone_init_logging(void) {
|
||||
linphone_core_serialize_logs();
|
||||
linphone_core_set_log_handler(pylinphone_module_log_handler);
|
||||
linphone_core_set_log_level(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
|
||||
}
|
||||
|
||||
|
||||
static PyObject * pylinphone_module_method_set_log_handler(PyObject *self, PyObject *args) {
|
||||
PyObject *linphone_module = PyImport_ImportModule("linphone.linphone");
|
||||
PyObject *callback;
|
||||
if (!PyArg_ParseTuple(args, "O", &callback)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyCallable_Check(callback)) {
|
||||
PyErr_SetString(PyExc_TypeError, "The argument must be a callable");
|
||||
return NULL;
|
||||
}
|
||||
if (linphone_module != NULL) {
|
||||
Py_INCREF(callback);
|
||||
PyObject_SetAttrString(linphone_module, "__log_handler", callback);
|
||||
Py_DECREF(linphone_module);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject * pylinphone_Core_get_video_devices(PyObject *self, void *closure) {
|
||||
PyObject *_list;
|
||||
const char **_devices;
|
||||
LinphoneCore *native_ptr = pylinphone_Core_get_native_ptr(self);
|
||||
|
||||
if (native_ptr == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid linphone.Core instance");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, self, native_ptr);
|
||||
_devices = linphone_core_get_video_devices(native_ptr);
|
||||
pylinphone_dispatch_messages();
|
||||
|
||||
_list = PyList_New(0);
|
||||
while (*_devices != NULL) {
|
||||
PyObject *_item = PyString_FromString(*_devices);
|
||||
PyList_Append(_list, _item);
|
||||
_devices++;
|
||||
}
|
||||
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, _list);
|
||||
return _list;
|
||||
}
|
||||
|
||||
static PyObject * pylinphone_Core_class_method_new(PyObject *cls, PyObject *args) {
|
||||
LinphoneCore * cresult;
|
||||
pylinphone_CoreObject *self;
|
||||
PyObject * pyret;
|
||||
LinphoneCoreVTable _vtable = { 0 };
|
||||
PyObject * _vtable_dict;
|
||||
const char * _config_path;
|
||||
const char * _factory_config_path;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Ozz", &_vtable_dict, &_config_path, &_factory_config_path)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyDict_Check(_vtable_dict)) {
|
||||
PyErr_SetString(PyExc_TypeError, "The first argument must be a dictionary");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = (pylinphone_CoreObject *)PyObject_New(pylinphone_CoreObject, &pylinphone_CoreType);
|
||||
if (self == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(_vtable_dict);
|
||||
self->vtable_dict = _vtable_dict;
|
||||
{{#events}}
|
||||
{{{event_vtable_reference}}}
|
||||
{{/events}}
|
||||
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p, \"%s\", \"%s\")", __FUNCTION__, _vtable_dict, _config_path, _factory_config_path);
|
||||
cresult = linphone_core_new(&_vtable, _config_path, _factory_config_path, self);
|
||||
self->native_ptr = cresult;
|
||||
|
||||
pyret = Py_BuildValue("O", self);
|
||||
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret);
|
||||
Py_DECREF(self);
|
||||
return pyret;
|
||||
}
|
||||
|
||||
static PyObject * pylinphone_Core_class_method_new_with_config(PyObject *cls, PyObject *args) {
|
||||
LinphoneCore * cresult;
|
||||
pylinphone_CoreObject *self;
|
||||
PyObject * pyret;
|
||||
LinphoneCoreVTable _vtable = { 0 };
|
||||
PyObject * _vtable_dict;
|
||||
PyObject * _config;
|
||||
LpConfig * _config_native_ptr;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OO", &_vtable_dict, &_config)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyDict_Check(_vtable_dict)) {
|
||||
PyErr_SetString(PyExc_TypeError, "The first argument must be a dictionary");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((_config_native_ptr = pylinphone_LpConfig_get_native_ptr(_config)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = (pylinphone_CoreObject *)PyObject_New(pylinphone_CoreObject, &pylinphone_CoreType);
|
||||
if (self == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(_vtable_dict);
|
||||
self->vtable_dict = _vtable_dict;
|
||||
{{#events}}
|
||||
{{{event_vtable_reference}}}
|
||||
{{/events}}
|
||||
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, _config, _config_native_ptr);
|
||||
cresult = linphone_core_new_with_config(&_vtable, _config_native_ptr, self);
|
||||
self->native_ptr = cresult;
|
||||
|
||||
pyret = Py_BuildValue("O", self);
|
||||
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret);
|
||||
Py_DECREF(self);
|
||||
return pyret;
|
||||
}
|
||||
|
||||
|
||||
static void pylinphone_ChatRoom_callback_chat_message_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state, void *ud) {
|
||||
PyGILState_STATE pygil_state;
|
||||
PyObject *pycm = NULL;
|
||||
PyObject *func = NULL;
|
||||
PyObject *_dict = (PyObject *)ud;
|
||||
PyObject *_cb = PyDict_GetItemString(_dict, "callback");
|
||||
PyObject *_ud = PyDict_GetItemString(_dict, "user_data");
|
||||
|
||||
pygil_state = PyGILState_Ensure();
|
||||
pycm = linphone_chat_message_get_user_data(msg);
|
||||
if (pycm == NULL) {
|
||||
pycm = pylinphone_ChatMessage_new_from_native_ptr(&pylinphone_ChatMessageType, msg);
|
||||
}
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p, %p [%p], %d, %p)", __FUNCTION__, pycm, msg, state, ud);
|
||||
if ((_cb != NULL) && PyCallable_Check(_cb)) {
|
||||
if (PyEval_CallObject(_cb, Py_BuildValue("OiO", pycm, state, _ud)) == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s", __FUNCTION__);
|
||||
PyGILState_Release(pygil_state);
|
||||
}
|
||||
|
||||
static PyObject * pylinphone_ChatRoom_instance_method_send_message2(PyObject *self, PyObject *args) {
|
||||
PyObject *_chat_message;
|
||||
PyObject *_dict;
|
||||
PyObject *_cb;
|
||||
PyObject *_ud;
|
||||
LinphoneChatMessage * _chat_message_native_ptr;
|
||||
LinphoneChatRoom *native_ptr = pylinphone_ChatRoom_get_native_ptr(self);
|
||||
|
||||
if (native_ptr == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid linphone.ChatRoom instance");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, "OOO", &_chat_message, &_cb, &_ud)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyObject_IsInstance(_chat_message, (PyObject *)&pylinphone_ChatMessageType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "The msg argument must be a linphone.ChatMessage");
|
||||
return NULL;
|
||||
}
|
||||
if ((_cb != Py_None) && !PyCallable_Check(_cb)) {
|
||||
PyErr_SetString(PyExc_TypeError, "The status_cb argument must be a callable");
|
||||
return NULL;
|
||||
}
|
||||
if ((_chat_message_native_ptr = pylinphone_ChatMessage_get_native_ptr(_chat_message)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
_dict = PyDict_New();
|
||||
PyDict_SetItemString(_dict, "callback", _cb);
|
||||
PyDict_SetItemString(_dict, "user_data", _ud);
|
||||
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p], %p [%p], %p, %p)", __FUNCTION__, self, native_ptr, _chat_message, _chat_message_native_ptr, _cb, _ud);
|
||||
linphone_chat_room_send_message2(native_ptr, _chat_message_native_ptr, pylinphone_ChatRoom_callback_chat_message_state_changed, _dict);
|
||||
pylinphone_dispatch_messages();
|
||||
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> None", __FUNCTION__);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void pylinphone_VideoSize_dealloc(PyObject *self) {
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p)", __FUNCTION__, self);
|
||||
self->ob_type->tp_free(self);
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s", __FUNCTION__);
|
||||
}
|
||||
|
||||
static PyObject * pylinphone_VideoSize_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
|
||||
pylinphone_VideoSizeObject *self = (pylinphone_VideoSizeObject *)type->tp_alloc(type, 0);
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s()", __FUNCTION__);
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
static int pylinphone_VideoSize_init(PyObject *self, PyObject *args, PyObject *kwds) {
|
||||
pylinphone_VideoSizeObject *vso = (pylinphone_VideoSizeObject *)self;
|
||||
int width;
|
||||
int height;
|
||||
if (!PyArg_ParseTuple(args, "ii", &width, &height)) {
|
||||
return -1;
|
||||
}
|
||||
vso->vs.width = width;
|
||||
vso->vs.height = height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyMemberDef pylinphone_VideoSize_members[] = {
|
||||
{ "width", T_INT, offsetof(pylinphone_VideoSizeObject, vs) + offsetof(MSVideoSize, width), 0, "[int] The width of the video" },
|
||||
{ "height", T_INT, offsetof(pylinphone_VideoSizeObject, vs) + offsetof(MSVideoSize, height), 0, "[int] The height of the video" },
|
||||
{ NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject pylinphone_VideoSizeType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"linphone.VideoSize", /* tp_name */
|
||||
sizeof(pylinphone_VideoSizeObject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
pylinphone_VideoSize_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
"Object representing the size of a video: its width and its height in pixels.", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
pylinphone_VideoSize_members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
pylinphone_VideoSize_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
pylinphone_VideoSize_new, /* tp_new */
|
||||
0, /* tp_free */
|
||||
};
|
||||
|
||||
int PyLinphoneVideoSize_Check(PyObject *p) {
|
||||
return PyObject_IsInstance(p, (PyObject *)&pylinphone_VideoSizeType);
|
||||
}
|
||||
|
||||
MSVideoSize PyLinphoneVideoSize_AsMSVideoSize(PyObject *obj) {
|
||||
return ((pylinphone_VideoSizeObject *)obj)->vs;
|
||||
}
|
||||
|
||||
PyObject * PyLinphoneVideoSize_FromMSVideoSize(MSVideoSize vs) {
|
||||
PyObject *linphone_module;
|
||||
PyObject *pyret = NULL;
|
||||
PyGILState_STATE gstate;
|
||||
|
||||
gstate = PyGILState_Ensure();
|
||||
linphone_module = PyImport_ImportModule("linphone.linphone");
|
||||
if (linphone_module != NULL) {
|
||||
PyObject *cls = PyObject_GetAttrString(linphone_module, "VideoSize");
|
||||
if (cls != NULL) {
|
||||
pyret = PyEval_CallObject(cls, Py_BuildValue("ii", vs.width, vs.height));
|
||||
if (pyret == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_DECREF(cls);
|
||||
}
|
||||
Py_DECREF(linphone_module);
|
||||
}
|
||||
PyGILState_Release(gstate);
|
||||
|
||||
if (pyret == NULL) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return pyret;
|
||||
}
|
||||
|
||||
|
||||
time_t PyDateTime_As_time_t(PyObject *obj) {
|
||||
time_t ret = -1;
|
||||
PyObject *utctimetuple = PyObject_GetAttrString(obj, "utctimetuple");
|
||||
if (utctimetuple != NULL) {
|
||||
PyObject *calendar_module = PyImport_ImportModule("calendar");
|
||||
if (calendar_module != NULL) {
|
||||
PyObject *timegm = PyObject_GetAttrString(calendar_module, "timegm");
|
||||
if (timegm != NULL) {
|
||||
PyObject *tuple = PyEval_CallObject(utctimetuple, Py_BuildValue("()"));
|
||||
PyObject *pyres = PyEval_CallObject(timegm, Py_BuildValue("(O)", tuple));
|
||||
ret = (time_t)PyLong_AsLong(pyres);
|
||||
Py_DECREF(timegm);
|
||||
}
|
||||
Py_DECREF(calendar_module);
|
||||
}
|
||||
Py_DECREF(utctimetuple);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject * PyDateTime_From_time_t(time_t t) {
|
||||
PyObject *pyret = NULL;
|
||||
PyObject *datetime_module;
|
||||
if (t == -1) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
datetime_module = PyImport_ImportModule("datetime");
|
||||
if (datetime_module != NULL) {
|
||||
PyObject *datetime_class = PyObject_GetAttrString(datetime_module, "datetime");
|
||||
if (datetime_class != NULL) {
|
||||
PyObject *utcfromtimestamp = PyObject_GetAttrString(datetime_class, "utcfromtimestamp");
|
||||
if (utcfromtimestamp != NULL) {
|
||||
pyret = PyEval_CallObject(utcfromtimestamp, Py_BuildValue("(f)", (float)t));
|
||||
if (pyret == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_DECREF(utcfromtimestamp);
|
||||
}
|
||||
Py_DECREF(datetime_class);
|
||||
}
|
||||
Py_DECREF(datetime_module);
|
||||
}
|
||||
if (pyret == NULL) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return pyret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject * pylinphone_PayloadTypeType_module_method_string(PyObject *self, PyObject *args) {
|
||||
const char *value_str = "[invalid]";
|
||||
int value;
|
||||
PyObject *pyret;
|
||||
if (!PyArg_ParseTuple(args, "i", &value)) {
|
||||
return NULL;
|
||||
}
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%d)", __FUNCTION__, value);
|
||||
switch (value) {
|
||||
case PAYLOAD_AUDIO_CONTINUOUS:
|
||||
value_str = "PAYLOAD_AUDIO_CONTINUOUS";
|
||||
break;
|
||||
case PAYLOAD_AUDIO_PACKETIZED:
|
||||
value_str = "PAYLOAD_AUDIO_PACKETIZED";
|
||||
break;
|
||||
case PAYLOAD_VIDEO:
|
||||
value_str = "PAYLOAD_VIDEO";
|
||||
break;
|
||||
case PAYLOAD_TEXT:
|
||||
value_str = "PAYLOAD_TEXT";
|
||||
break;
|
||||
case PAYLOAD_OTHER:
|
||||
value_str = "PAYLOAD_OTHER";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pyret = Py_BuildValue("z", value_str);
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret);
|
||||
return pyret;
|
||||
}
|
||||
|
||||
static PyMethodDef pylinphone_PayloadTypeType_ModuleMethods[] = {
|
||||
{ "string", pylinphone_PayloadTypeType_module_method_string, METH_VARARGS, "Get a string representation of a linphone.PayloadTypeType value." },
|
||||
/* Sentinel */
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
1087
tools/python/apixml2python/linphone.py
Normal file
1087
tools/python/apixml2python/linphone.py
Normal file
File diff suppressed because it is too large
Load diff
309
tools/python/apixml2python/linphone_module.mustache
Normal file
309
tools/python/apixml2python/linphone_module.mustache
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
Copyright (C) 2014 Belledonne Communications SARL
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include <structmember.h>
|
||||
#include <datetime.h>
|
||||
#include <linphone/linphonecore.h>
|
||||
#include <linphone/linphone_tunnel.h>
|
||||
#include <linphone/linphonecore_utils.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "gitversion.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define PYLINPHONE_INLINE __inline
|
||||
#else
|
||||
#define PYLINPHONE_INLINE inline
|
||||
#endif
|
||||
|
||||
|
||||
static void pylinphone_dispatch_messages(void);
|
||||
static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...);
|
||||
|
||||
|
||||
{{> handwritten_declarations}}
|
||||
|
||||
|
||||
|
||||
{{#classes}}
|
||||
static PyTypeObject pylinphone_{{class_name}}Type;
|
||||
{{/classes}}
|
||||
|
||||
{{#classes}}
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
{{class_cname}} *native_ptr;
|
||||
{{{class_object_members}}}
|
||||
} pylinphone_{{class_name}}Object;
|
||||
|
||||
{{/classes}}
|
||||
|
||||
{{#classes}}
|
||||
static {{class_cname}} * pylinphone_{{class_name}}_get_native_ptr(PyObject *self);
|
||||
static PyObject * pylinphone_{{class_name}}_new_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr);
|
||||
{{#class_type_hand_written_methods}}
|
||||
static PyObject * pylinphone_{{class_name}}_class_method_{{method_name}}(PyObject *cls, PyObject *args);
|
||||
{{/class_type_hand_written_methods}}
|
||||
{{#class_instance_hand_written_methods}}
|
||||
static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyObject *self, PyObject *args);
|
||||
{{/class_instance_hand_written_methods}}
|
||||
{{/classes}}
|
||||
|
||||
{{#mslist_types}}
|
||||
PyObject * PyList_FromMSListOf{{c_contained_type}}(const MSList *msl) {
|
||||
PyObject *pyl = PyList_New(0);
|
||||
while (msl != NULL) {
|
||||
{{c_contained_type}} *native_ptr = ({{c_contained_type}} *)msl->data;
|
||||
PyObject *item = pylinphone_{{python_contained_type}}_new_from_native_ptr(&pylinphone_{{python_contained_type}}Type, native_ptr);
|
||||
PyList_Append(pyl, item);
|
||||
msl = ms_list_next(msl);
|
||||
}
|
||||
return pyl;
|
||||
}
|
||||
|
||||
MSList * PyList_AsMSListOf{{c_contained_type}}(PyObject *pyl) {
|
||||
MSList *msl = NULL;
|
||||
Py_ssize_t idx;
|
||||
Py_ssize_t size = PyList_Size(pyl);
|
||||
for (idx = 0; idx < size; idx++) {
|
||||
PyObject *item = PyList_GetItem(pyl, idx);
|
||||
{{c_contained_type}} *native_ptr = pylinphone_{{python_contained_type}}_get_native_ptr(item);
|
||||
msl = ms_list_append(msl, native_ptr);
|
||||
}
|
||||
return msl;
|
||||
}
|
||||
|
||||
{{/mslist_types}}
|
||||
|
||||
{{#events}}
|
||||
{{{event_callback_definition}}}
|
||||
{{/events}}
|
||||
|
||||
{{#classes}}
|
||||
|
||||
static {{class_cname}} * pylinphone_{{class_name}}_get_native_ptr(PyObject *self) {
|
||||
return ((pylinphone_{{class_name}}Object *)self)->native_ptr;
|
||||
}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_new_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr) {
|
||||
{{{new_from_native_pointer_body}}}
|
||||
}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
|
||||
{{{new_body}}}
|
||||
}
|
||||
|
||||
static void pylinphone_{{class_name}}_dealloc(PyObject *self) {
|
||||
{{{dealloc_body}}}
|
||||
}
|
||||
|
||||
{{#class_type_methods}}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_class_method_{{method_name}}(PyObject *cls, PyObject *args) {
|
||||
{{{method_body}}}
|
||||
}
|
||||
|
||||
{{/class_type_methods}}
|
||||
|
||||
{{#class_instance_methods}}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyObject *self, PyObject *args) {
|
||||
{{{method_body}}}
|
||||
}
|
||||
|
||||
{{/class_instance_methods}}
|
||||
|
||||
static PyMethodDef pylinphone_{{class_name}}_methods[] = {
|
||||
/* Class methods */
|
||||
{{#class_type_hand_written_methods}}
|
||||
{ "{{method_name}}", pylinphone_{{class_name}}_class_method_{{method_name}}, METH_VARARGS | METH_CLASS, "" },
|
||||
{{/class_type_hand_written_methods}}
|
||||
{{#class_type_methods}}
|
||||
{ "{{method_name}}", pylinphone_{{class_name}}_class_method_{{method_name}}, METH_VARARGS | METH_CLASS, "{{{method_doc}}}" },
|
||||
{{/class_type_methods}}
|
||||
/* Instance methods */
|
||||
{{#class_instance_hand_written_methods}}
|
||||
{ "{{method_name}}", pylinphone_{{class_name}}_instance_method_{{method_name}}, METH_VARARGS, "" },
|
||||
{{/class_instance_hand_written_methods}}
|
||||
{{#class_instance_methods}}
|
||||
{ "{{method_name}}", pylinphone_{{class_name}}_instance_method_{{method_name}}, METH_VARARGS, "{{{method_doc}}}" },
|
||||
{{/class_instance_methods}}
|
||||
/* Sentinel */
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
{{#class_properties}}
|
||||
|
||||
{{{getter_definition_begin}}}
|
||||
{{{getter_body}}}
|
||||
{{{getter_definition_end}}}
|
||||
|
||||
{{{setter_definition_begin}}}
|
||||
{{{setter_body}}}
|
||||
{{{setter_definition_end}}}
|
||||
|
||||
{{/class_properties}}
|
||||
|
||||
static PyGetSetDef pylinphone_{{class_name}}_getseters[] = {
|
||||
{{#class_hand_written_properties}}
|
||||
{ "{{property_name}}", {{getter_reference}}, {{setter_reference}}, "" },
|
||||
{{/class_hand_written_properties}}
|
||||
{{#class_properties}}
|
||||
{ "{{property_name}}", {{getter_reference}}, {{setter_reference}}, "{{{property_doc}}}" },
|
||||
{{/class_properties}}
|
||||
/* Sentinel */
|
||||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static PyTypeObject pylinphone_{{class_name}}Type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"linphone.{{class_name}}", /* tp_name */
|
||||
sizeof(pylinphone_{{class_name}}Object), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
pylinphone_{{class_name}}_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
"{{{class_doc}}}", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
pylinphone_{{class_name}}_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
pylinphone_{{class_name}}_getseters, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
pylinphone_{{class_name}}_new, /* tp_new */
|
||||
0, /* tp_free */
|
||||
};
|
||||
|
||||
{{/classes}}
|
||||
|
||||
|
||||
{{> handwritten_definitions}}
|
||||
|
||||
|
||||
static PyMethodDef pylinphone_ModuleMethods[] = {
|
||||
{ "set_log_handler", pylinphone_module_method_set_log_handler, METH_VARARGS, "" },
|
||||
/* Sentinel */
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
{{#enums}}
|
||||
static PyObject * pylinphone_{{enum_name}}_module_method_string(PyObject *self, PyObject *args) {
|
||||
const char *value_str = "[invalid]";
|
||||
int value;
|
||||
PyObject *pyret;
|
||||
if (!PyArg_ParseTuple(args, "i", &value)) {
|
||||
return NULL;
|
||||
}
|
||||
pylinphone_trace(1, "[PYLINPHONE] >>> %s(%d)", __FUNCTION__, value);
|
||||
switch (value) {
|
||||
{{#enum_values}}
|
||||
case {{enum_value_cname}}:
|
||||
value_str = "{{enum_value_name}}";
|
||||
break;
|
||||
{{/enum_values}}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pyret = Py_BuildValue("z", value_str);
|
||||
pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret);
|
||||
return pyret;
|
||||
}
|
||||
|
||||
static PyMethodDef pylinphone_{{enum_name}}_ModuleMethods[] = {
|
||||
{ "string", pylinphone_{{enum_name}}_module_method_string, METH_VARARGS, "Get a string representation of a linphone.{{enum_name}} value." },
|
||||
/* Sentinel */
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
{{/enums}}
|
||||
|
||||
PyMODINIT_FUNC initlinphone(void) {
|
||||
PyObject *m;
|
||||
PyObject *menum;
|
||||
|
||||
PyDateTime_IMPORT;
|
||||
pylinphone_init_logging();
|
||||
|
||||
{{#classes}}
|
||||
if (PyType_Ready(&pylinphone_{{class_name}}Type) < 0) return;
|
||||
{{/classes}}
|
||||
|
||||
/* Hand-written classes. */
|
||||
if (PyType_Ready(&pylinphone_VideoSizeType) < 0) return;
|
||||
|
||||
m = Py_InitModule3("linphone", pylinphone_ModuleMethods, "Python module giving access to the Linphone library.");
|
||||
if (m == NULL) return;
|
||||
if (PyModule_AddStringConstant(m, "__version__", LINPHONE_GIT_REVISION) < 0) return;
|
||||
|
||||
{{#enums}}
|
||||
menum = Py_InitModule3("{{enum_name}}", pylinphone_{{enum_name}}_ModuleMethods, "{{{enum_doc}}}");
|
||||
if (menum == NULL) return;
|
||||
if (PyModule_AddObject(m, "{{enum_name}}", menum) < 0) return;
|
||||
{{#enum_values}}
|
||||
if (PyModule_AddIntConstant(menum, "{{enum_value_name}}", {{enum_value_cname}}) < 0) return;
|
||||
{{/enum_values}}
|
||||
{{/enums}}
|
||||
|
||||
menum = Py_InitModule3("PayloadTypeType", pylinphone_PayloadTypeType_ModuleMethods, "Type of linphone.PayloadType.");
|
||||
if (menum == NULL) return;
|
||||
if (PyModule_AddObject(m, "PayloadTypeType", menum) < 0) return;
|
||||
if (PyModule_AddIntConstant(menum, "PAYLOAD_AUDIO_CONTINUOUS", PAYLOAD_AUDIO_CONTINUOUS) < 0) return;
|
||||
if (PyModule_AddIntConstant(menum, "PAYLOAD_AUDIO_PACKETIZED", PAYLOAD_AUDIO_PACKETIZED) < 0) return;
|
||||
if (PyModule_AddIntConstant(menum, "PAYLOAD_VIDEO", PAYLOAD_VIDEO) < 0) return;
|
||||
if (PyModule_AddIntConstant(menum, "PAYLOAD_TEXT", PAYLOAD_TEXT) < 0) return;
|
||||
if (PyModule_AddIntConstant(menum, "PAYLOAD_OTHER", PAYLOAD_OTHER) < 0) return;
|
||||
|
||||
{{#classes}}
|
||||
Py_INCREF(&pylinphone_{{class_name}}Type);
|
||||
PyModule_AddObject(m, "{{class_name}}", (PyObject *)&pylinphone_{{class_name}}Type);
|
||||
{{/classes}}
|
||||
|
||||
/* Hand-written classes. */
|
||||
Py_INCREF(&pylinphone_VideoSizeType);
|
||||
PyModule_AddObject(m, "VideoSize", (PyObject *)&pylinphone_VideoSizeType);
|
||||
}
|
||||
514
tools/python/linphone-daemon.py
Normal file
514
tools/python/linphone-daemon.py
Normal file
|
|
@ -0,0 +1,514 @@
|
|||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import linphone
|
||||
|
||||
|
||||
class Response:
|
||||
Ok = 0
|
||||
Error = 1
|
||||
|
||||
def __init__(self, status, msg = ''):
|
||||
self.status = status
|
||||
if status == Response.Ok:
|
||||
self.body = msg
|
||||
self.reason = None
|
||||
else:
|
||||
self.body = None
|
||||
self.reason = msg
|
||||
|
||||
def __str__(self):
|
||||
status_str = ["Ok", "Error"][self.status]
|
||||
body = ''
|
||||
if self.reason:
|
||||
body += "Reason: {reason}\n".format(reason=self.reason)
|
||||
if self.body:
|
||||
body += '\n' + self.body + '\n'
|
||||
return \
|
||||
"""Status: {status}
|
||||
{body}""".format(status=status_str, body=body)
|
||||
|
||||
class RegisterStatusResponse(Response):
|
||||
def __init__(self):
|
||||
Response.__init__(self, Response.Ok)
|
||||
|
||||
def append(self, id, proxy_cfg):
|
||||
self.body += \
|
||||
"""Id: {id}
|
||||
State: {state}
|
||||
""".format(id=id, state=str(linphone.RegistrationState.string(proxy_cfg.state)))
|
||||
|
||||
class CommandExample:
|
||||
def __init__(self, command, output):
|
||||
self.command = command
|
||||
self.output = output
|
||||
|
||||
def __str__(self):
|
||||
return \
|
||||
"""> {command}
|
||||
{output}""".format(command=self.command, output=self.output)
|
||||
|
||||
class Command:
|
||||
def __init__(self, name, proto):
|
||||
self.name = name
|
||||
self.proto = proto
|
||||
self.examples = []
|
||||
|
||||
def exec_command(self, app, args):
|
||||
pass
|
||||
|
||||
def add_example(self, example):
|
||||
self.examples.append(example)
|
||||
|
||||
def help(self):
|
||||
body = \
|
||||
"""{proto}
|
||||
|
||||
Description:
|
||||
{description}
|
||||
""".format(proto=self.proto, description=self.__doc__)
|
||||
idx = 0
|
||||
for example in self.examples:
|
||||
idx += 1
|
||||
body += \
|
||||
"""
|
||||
Example {idx}:
|
||||
{example}
|
||||
""".format(idx=idx, example=str(example))
|
||||
return body
|
||||
|
||||
class CallCommand(Command):
|
||||
"""Place a call."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "call", "call <sip-address>")
|
||||
self.add_example(CommandExample(
|
||||
"call daemon-test@sip.linphone.org",
|
||||
"Status: Ok\n\nId: 1"
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"call daemon-test@sip.linphone.org",
|
||||
"Status: Error\nReason: Call creation failed."
|
||||
))
|
||||
|
||||
def exec_command(self, app, args):
|
||||
if len(args) >= 1:
|
||||
call = app.core.invite(args[0])
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "Call creation failed."))
|
||||
else:
|
||||
id = app.update_call_id(call)
|
||||
app.send_response(Response(Response.Ok, "Id: " + str(id)))
|
||||
else:
|
||||
app.send_response(Response(Response.Error, "Missing parameter."))
|
||||
|
||||
class CallPauseCommand(Command):
|
||||
"""Pause a call (pause current if no id is specified)."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "call-pause", "call-pause [call-id]")
|
||||
self.add_example(CommandExample(
|
||||
"call-pause 1",
|
||||
"Status: Ok\n\nCall was paused"
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"call-pause 2",
|
||||
"Status: Error\nReason: No call with such id."
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"call-pause",
|
||||
"Status: Error\nReason: No current call available."
|
||||
))
|
||||
|
||||
def exec_command(self, app, args):
|
||||
current = False
|
||||
if len(args) >= 1:
|
||||
call = app.find_call(args[0])
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "No call with such id."))
|
||||
return
|
||||
else:
|
||||
current = True
|
||||
call = app.core.current_call
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "No current call available."))
|
||||
return
|
||||
if app.core.pause_call(call) == 0:
|
||||
msg = "Call was paused."
|
||||
if current:
|
||||
msg = "Current call was paused."
|
||||
app.send_response(Response(Response.Ok, msg))
|
||||
else:
|
||||
app.send_response(Response(Response.Error, "Error pausing call."))
|
||||
|
||||
class CallResumeCommand(Command):
|
||||
"""Resume a call (resume current if no id is specified)."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "call-resume", "call-resume [call-id]")
|
||||
self.add_example(CommandExample(
|
||||
"call-resume 1",
|
||||
"Status: Ok\n\nCall was resumed"
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"call-resume 2",
|
||||
"Status: Error\nReason: No call with such id."
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"call-resume",
|
||||
"Status: Error\nReason: No current call available."
|
||||
))
|
||||
|
||||
def exec_command(self, app, args):
|
||||
current = False
|
||||
if len(args) >= 1:
|
||||
call = app.find_call(args[0])
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "No call with such id."))
|
||||
return
|
||||
else:
|
||||
current = True
|
||||
call = app.core.current_call
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "No current call available."))
|
||||
return
|
||||
if app.core.resume_call(call) == 0:
|
||||
msg = "Call was resumed."
|
||||
if current:
|
||||
msg = "Current call was resumed."
|
||||
app.send_response(Response(Response.Ok, msg))
|
||||
else:
|
||||
app.send_response(Response(Response.Error, "Error resuming call."))
|
||||
|
||||
class CallStatusCommand(Command):
|
||||
"""Return status of the specified call or of the current call if no id is given."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "call-status", "call-status [call-id]")
|
||||
self.add_example(CommandExample(
|
||||
"call-status 1",
|
||||
"Status: Ok\n\nState: LinphoneCallStreamsRunning\nFrom: <sip:daemon-test@sip.linphone.org>\nDirection: out\nDuration: 6"
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"call-status 2",
|
||||
"Status: Error\nReason: No call with such id."
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"call-status",
|
||||
"Status: Error\nReason: No current call available."
|
||||
))
|
||||
|
||||
def exec_command(self, app, args):
|
||||
if len(args) >= 1:
|
||||
call = app.find_call(args[0])
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "No call with such id."))
|
||||
return
|
||||
else:
|
||||
call = app.core.current_call
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "No current call available."))
|
||||
return
|
||||
state = call.state
|
||||
body = "State: {state}".format(state=linphone.CallState.string(state))
|
||||
if state == linphone.CallState.CallOutgoingInit \
|
||||
or state == linphone.CallState.CallOutgoingProgress \
|
||||
or state == linphone.CallState.CallOutgoingRinging \
|
||||
or state == linphone.CallState.CallPaused \
|
||||
or state == linphone.CallState.CallStreamsRunning \
|
||||
or state == linphone.CallState.CallConnected \
|
||||
or state == linphone.CallState.CallIncomingReceived:
|
||||
body += "\nFrom: {address}".format(address=call.remote_address.as_string())
|
||||
if state == linphone.CallState.CallStreamsRunning \
|
||||
or state == linphone.CallState.CallConnected:
|
||||
direction_str = 'in'
|
||||
if call.dir == linphone.CallDir.CallOutgoing:
|
||||
direction_str = 'out'
|
||||
body += "\nDirection: {direction}\nDuration: {duration}".format(direction=direction_str, duration=call.duration)
|
||||
app.send_response(Response(Response.Ok, body))
|
||||
|
||||
class HelpCommand(Command):
|
||||
"""Show <command> help notice, if command is unspecified or inexistent show all commands."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "help", "help <command>")
|
||||
|
||||
def exec_command(self, app, args):
|
||||
body = ''
|
||||
if args:
|
||||
command = [item for item in app.commands if item.name == args[0]]
|
||||
if command:
|
||||
body = command[0].help()
|
||||
else:
|
||||
app.send_response(Response(Response.Error, "Unknown command '{command}'.".format(command=args[0])))
|
||||
return
|
||||
else:
|
||||
for command in app.commands:
|
||||
body += command.proto + '\n'
|
||||
app.send_response(Response(Response.Ok, body))
|
||||
|
||||
class QuitCommand(Command):
|
||||
"""Quit the application."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "quit", "quit")
|
||||
|
||||
def exec_command(self, app, args):
|
||||
app.quit()
|
||||
app.send_response(Response(Response.Ok))
|
||||
|
||||
class RegisterCommand(Command):
|
||||
"""Register the daemon to a SIP proxy. If one of the parameters <password>, <userid> and <realm> is not needed, send the string "NULL"."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "register", "register <identity> <proxy-address> [password] [userid] [realm] [contact-parameters]")
|
||||
self.add_example(CommandExample(
|
||||
"register sip:daemon-test@sip.linphone.org sip.linphone.org password bob linphone.org",
|
||||
"Status: Ok\n\nId: 1"
|
||||
))
|
||||
|
||||
def exec_command(self, app, args):
|
||||
if len(args) >= 2:
|
||||
password = None
|
||||
userid = None
|
||||
realm = None
|
||||
contact_parameters = None
|
||||
identity = args[0]
|
||||
proxy = args[1]
|
||||
if len(args) > 2 and args[2] != "NULL":
|
||||
password = args[2]
|
||||
if len(args) > 3 and args[3] != "NULL":
|
||||
userid = args[3]
|
||||
if len(args) > 4 and args[4] != "NULL":
|
||||
realm = args[4]
|
||||
if len(args) > 5 and args[5] != "NULL":
|
||||
contact_parameters = args[5]
|
||||
proxy_cfg = app.core.create_proxy_config()
|
||||
if password is not None:
|
||||
addr = linphone.Address.new(identity)
|
||||
if addr is not None:
|
||||
info = linphone.AuthInfo.new(addr.username, userid, password, None, realm, None)
|
||||
app.core.add_auth_info(info)
|
||||
print(info)
|
||||
proxy_cfg.identity = identity
|
||||
proxy_cfg.server_addr = proxy
|
||||
proxy_cfg.register_enabled = True
|
||||
proxy_cfg.contact_parameters = contact_parameters
|
||||
app.core.add_proxy_config(proxy_cfg)
|
||||
id = app.update_proxy_id(proxy_cfg)
|
||||
app.send_response(Response(Response.Ok, "Id: " + str(id)))
|
||||
else:
|
||||
app.send_response(Response(Response.Error, "Missing/Incorrect parameter(s)."))
|
||||
|
||||
class RegisterStatusCommand(Command):
|
||||
"""Return status of a registration or of all registrations."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "register-status", "register-status <register_id|ALL>")
|
||||
self.add_example(CommandExample(
|
||||
"register-status 1",
|
||||
"Status: Ok\n\nId: 1\nState: LinphoneRegistrationOk"
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"register-status ALL",
|
||||
"Status: Ok\n\nId: 1\nState: LinphoneRegistrationOk\n\nId: 2\nState: LinphoneRegistrationFailed"
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"register-status 3",
|
||||
"Status: Error\nReason: No register with such id."
|
||||
))
|
||||
|
||||
def exec_command(self, app, args):
|
||||
if len(args) == 0:
|
||||
app.send_response(Response(Response.Error, "Missing parameter."))
|
||||
else:
|
||||
id = args[0]
|
||||
if id == "ALL":
|
||||
response = RegisterStatusResponse()
|
||||
for id in app.proxy_ids_map:
|
||||
response.append(id, app.proxy_ids_map[id])
|
||||
app.send_response(response)
|
||||
else:
|
||||
proxy_cfg = app.find_proxy(id)
|
||||
if proxy_cfg is None:
|
||||
app.send_response(Response(Response.Error, "No register with such id."))
|
||||
else:
|
||||
app.send_response(RegisterStatusResponse().append(id, proxy_cfg))
|
||||
|
||||
class TerminateCommand(Command):
|
||||
"""Terminate the specified call or the current call if no id is given."""
|
||||
def __init__(self):
|
||||
Command.__init__(self, "terminate", "terminate [call id]")
|
||||
self.add_example(CommandExample(
|
||||
"terminate 2",
|
||||
"Status: Error\nReason: No call with such id."
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"terminate 1",
|
||||
"Status: Ok\n"
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"terminate",
|
||||
"Status: Ok\n"
|
||||
))
|
||||
self.add_example(CommandExample(
|
||||
"terminate",
|
||||
"Status: Error\nReason: No active call."
|
||||
))
|
||||
|
||||
def exec_command(self, app, args):
|
||||
if len(args) >= 1:
|
||||
call = app.find_call(args[0])
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "No call with such id."))
|
||||
return
|
||||
else:
|
||||
call = app.core.current_call
|
||||
if call is None:
|
||||
app.send_response(Response(Response.Error, "No active call."))
|
||||
return
|
||||
app.core.terminate_call(call)
|
||||
app.send_response(Response(Response.Ok))
|
||||
|
||||
|
||||
class Daemon:
|
||||
def __init__(self):
|
||||
self.quitting = False
|
||||
self._next_proxy_id = 1
|
||||
self.proxy_ids_map = {}
|
||||
self._next_call_id = 1
|
||||
self.call_ids_map = {}
|
||||
self.command_mutex = threading.Lock()
|
||||
self.command_executed_event = threading.Event()
|
||||
self.command_to_execute = None
|
||||
self.commands = [
|
||||
CallCommand(),
|
||||
CallPauseCommand(),
|
||||
CallResumeCommand(),
|
||||
CallStatusCommand(),
|
||||
HelpCommand(),
|
||||
QuitCommand(),
|
||||
RegisterCommand(),
|
||||
RegisterStatusCommand(),
|
||||
TerminateCommand()
|
||||
]
|
||||
|
||||
def global_state_changed(self, core, state, message):
|
||||
logging.warning("[PYTHON] global_state_changed: " + str(state) + ", " + message)
|
||||
if state == linphone.GlobalState.GlobalOn:
|
||||
logging.warning("[PYTHON] core version: " + str(core.version))
|
||||
|
||||
def registration_state_changed(self, core, proxy_cfg, state, message):
|
||||
logging.warning("[PYTHON] registration_state_changed: " + str(state) + ", " + message)
|
||||
|
||||
def call_state_changed(self, core, call, state, message):
|
||||
logging.warning("[PYTHON] call_state_changed: " + str(state) + ", " + message)
|
||||
|
||||
def send_response(self, response):
|
||||
print(response)
|
||||
|
||||
def exec_command(self, command_line):
|
||||
splitted_command_line = command_line.split()
|
||||
name = splitted_command_line[0]
|
||||
args = splitted_command_line[1:]
|
||||
command = [item for item in self.commands if item.name == name]
|
||||
if command:
|
||||
command[0].exec_command(self, args)
|
||||
else:
|
||||
self.send_response(Response(Response.Error, "Unknown command."))
|
||||
|
||||
def interact(self):
|
||||
command_line = raw_input('> ').strip()
|
||||
if command_line != '':
|
||||
self.command_mutex.acquire()
|
||||
self.command_to_execute = command_line
|
||||
self.command_mutex.release()
|
||||
self.command_executed_event.wait()
|
||||
self.command_executed_event.clear()
|
||||
|
||||
def run(self, args):
|
||||
def command_read(daemon):
|
||||
while not daemon.quitting:
|
||||
daemon.interact()
|
||||
|
||||
callbacks = {
|
||||
'global_state_changed':self.global_state_changed,
|
||||
'registration_state_changed':self.registration_state_changed,
|
||||
'call_state_changed':self.call_state_changed
|
||||
}
|
||||
|
||||
# Create a linphone core and iterate every 20 ms
|
||||
self.core = linphone.Core.new(callbacks, args.config, args.factory_config)
|
||||
t = threading.Thread(target=command_read, kwargs={'daemon':self})
|
||||
t.start()
|
||||
while not self.quitting:
|
||||
self.command_mutex.acquire()
|
||||
command_line = self.command_to_execute
|
||||
if command_line is not None:
|
||||
self.exec_command(command_line)
|
||||
self.command_to_execute = None
|
||||
self.command_executed_event.set()
|
||||
self.command_mutex.release()
|
||||
self.core.iterate()
|
||||
time.sleep(0.02)
|
||||
t.join()
|
||||
|
||||
def quit(self):
|
||||
self.quitting = True
|
||||
|
||||
def update_proxy_id(self, proxy):
|
||||
id = self._next_proxy_id
|
||||
self.proxy_ids_map[str(id)] = proxy
|
||||
self._next_proxy_id += 1
|
||||
return id
|
||||
|
||||
def find_proxy(self, id):
|
||||
if self.proxy_ids_map.has_key(id):
|
||||
return self.proxy_ids_map[id]
|
||||
return None
|
||||
|
||||
def update_call_id(self, call):
|
||||
id = self._next_call_id
|
||||
self.call_ids_map[str(id)] = call
|
||||
self._next_call_id += 1
|
||||
return id
|
||||
|
||||
def find_call(self, id):
|
||||
if self.call_ids_map.has_key(id):
|
||||
return self.call_ids_map[id]
|
||||
return None
|
||||
|
||||
def setup_log_colors():
|
||||
logging.addLevelName(logging.DEBUG, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.DEBUG))
|
||||
logging.addLevelName(logging.INFO, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.INFO))
|
||||
logging.addLevelName(logging.WARNING, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.WARNING))
|
||||
logging.addLevelName(logging.ERROR, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.ERROR))
|
||||
|
||||
def setup_log(log, trace):
|
||||
if log is None:
|
||||
setup_log_colors()
|
||||
format = "%(asctime)s.%(msecs)03d %(levelname)s: %(message)s"
|
||||
datefmt = "%H:%M:%S"
|
||||
if trace:
|
||||
level = logging.DEBUG
|
||||
else:
|
||||
level = logging.INFO
|
||||
logging.basicConfig(filename=log, level=level, format=format, datefmt=datefmt)
|
||||
|
||||
# Define the linphone module log handler
|
||||
def log_handler(level, msg):
|
||||
method = getattr(logging, level)
|
||||
if not msg.strip().startswith('[PYLINPHONE]'):
|
||||
msg = '[CORE] ' + msg
|
||||
method(msg)
|
||||
|
||||
def main(argv = None):
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
argparser = argparse.ArgumentParser(description="Linphone console interface in Python.")
|
||||
argparser.add_argument('--config', default=None, help="Path to the linphonerc configuration file to use.")
|
||||
argparser.add_argument('--factory_config', default=None, help="Path to the linphonerc factory configuration file to use.")
|
||||
argparser.add_argument('--log', default=None, help="Path to the file used for logging (default is the standard output).")
|
||||
argparser.add_argument('--trace', action='store_true', help="Output linphone Python module tracing logs (for debug purposes).")
|
||||
args = argparser.parse_args()
|
||||
setup_log(args.log, args.trace)
|
||||
linphone.set_log_handler(log_handler)
|
||||
d = Daemon()
|
||||
d.run(args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
27
tools/python/setup.py
Normal file
27
tools/python/setup.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2014 Belledonne Communications SARL
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
m = Extension('linphone',
|
||||
include_dirs = ['/home/ghislain/linphone-install/include'],
|
||||
libraries = ['linphone'],
|
||||
library_dirs = ['/home/ghislain/linphone-install/lib'],
|
||||
sources = ['linphone.c']
|
||||
)
|
||||
setup(name = 'Linphone', version = '1.0', description = 'Linphone package', ext_modules = [m])
|
||||
Loading…
Add table
Reference in a new issue