diff --git a/.gitignore b/.gitignore index 6a94843fa..85a6aed1d 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,8 @@ tools/xml2lpc_test coreapi/help/filetransfer tester/receive_file.dump tester/tmp.db +.DS_Store +Linphone.app +*.dmg +tester/linphone*.log +tester/linphone_log.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 470df4585..4311101fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ # ############################################################################ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.12) project(LINPHONE C CXX) @@ -61,6 +61,13 @@ endif() find_package(BelleSIP REQUIRED) find_package(MS2 REQUIRED) find_package(XML2 REQUIRED) +if(ENABLE_TUNNEL) + find_package(Tunnel) + if(NOT TUNNEL_FOUND) + message(WARNING "Could not find the tunnel library!") + set(ENABLE_TUNNEL OFF CACHE BOOL "Enable tunnel support" FORCE) + endif() +endif() include_directories( @@ -72,6 +79,9 @@ include_directories( ${MS2_INCLUDE_DIRS} ${XML2_INCLUDE_DIRS} ) +if(ENABLE_TUNNEL) + include_directories(${TUNNEL_INCLUDE_DIRS}) +endif() if(MSVC) include_directories(${CMAKE_PREFIX_PATH}/include/MSVC) @@ -94,6 +104,9 @@ add_definitions(-DHAVE_CONFIG_H) add_subdirectory(coreapi) add_subdirectory(share) +if(ENABLE_TOOLS) + add_subdirectory(tools) +endif() install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/FindLinphone.cmake diff --git a/FindLinphone.cmake b/FindLinphone.cmake index fdb582c72..6c6871330 100644 --- a/FindLinphone.cmake +++ b/FindLinphone.cmake @@ -26,6 +26,7 @@ # LINPHONE_INCLUDE_DIRS - the linphone include directory # LINPHONE_LIBRARIES - The libraries needed to use linphone # LINPHONE_CPPFLAGS - The compilation flags needed to use linphone +# LINPHONE_LDFLAGS - The linking flags needed to use linphone find_package(ORTP REQUIRED) find_package(MS2 REQUIRED) @@ -55,15 +56,19 @@ find_library(LINPHONE_LIBRARIES list(APPEND LINPHONE_INCLUDE_DIRS ${ORTP_INCLUDE_DIRS} ${MS2_INCLUDE_DIRS} ${XML2_INCLUDE_DIRS} ${BELLESIP_INCLUDE_DIRS}) list(APPEND LINPHONE_LIBRARIES ${ORTP_LIBRARIES} ${MS2_LIBRARIES} ${XML2_LIBRARIES} ${BELLESIP_LIBRARIES}) +if(WIN32) + list(APPEND LINPHONE_LIBRARIES shlwapi) +endif(WIN32) list(REMOVE_DUPLICATES LINPHONE_INCLUDE_DIRS) list(REMOVE_DUPLICATES LINPHONE_LIBRARIES) -set(LINPHONE_CPPFLAGS ${MS2_CPPFLAGS}) +set(LINPHONE_CPPFLAGS "${MS2_CPPFLAGS}") +set(LINPHONE_LDFLAGS "${MS2_LDFLAGS} ${BELLESIP_LDFLAGS}") include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Linphone DEFAULT_MSG - LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS + LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES ) -mark_as_advanced(LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS) +mark_as_advanced(LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS LINPHONE_LDFLAGS) diff --git a/Makefile.am b/Makefile.am index ff729400c..dd66874b2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -51,7 +51,7 @@ PACKAGE_BUNDLE_FILE=$(top_srcdir)/build/macos/$(PACKAGE).bundle EXTRA_DIST = BUGS \ README.arm \ README.mingw \ - README.macos \ + README.macos.md \ autogen.sh \ linphone.spec \ linphone.spec.in \ @@ -172,7 +172,7 @@ filelist: zip setup.exe: filelist cp $(ISS_SCRIPT) $(INSTALLDIR_WITH_PREFIX)/. cd $(INSTALLDIR_WITH_PREFIX) && \ - $(ISCC) $(ISS_SCRIPT) + $(ISCC) $(ISS_SCRIPT) mv $(INSTALLDIR_WITH_PREFIX)/Output/setup.exe $(PACKAGE)-$(VERSION)-setup.exe rm -rf $(INSTALLDIR_WITH_PREFIX)/Output rm -f $(INSTALLDIR_WITH_PREFIX)/$(PACKAGE_WIN32_FILELIST) diff --git a/README b/README index a2fe5301e..30666070a 100644 --- a/README +++ b/README @@ -11,12 +11,12 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol. - belle-sip>=1.3.0 - speex>=1.2.0 (including libspeexdsp part) - libxml2 - + + if you want the gtk/glade interface: - libgtk >=2.16.0 + if you want video support: - libvpx (VP8 codec) - - libavcodec (ffmpeg) + - libavcodec (ffmpeg) - libswscale (part of ffmpeg too) for better scaling performance - libxv (x11 video extension) - libgl1-mesa (OpenGL API -- GLX development files) @@ -31,31 +31,31 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol. + if you want uPnP support (optional): - libupnp (version 1.6 branch (not patched with 18-url-upnpstrings.patch)) - Here is the command line to get these dependencies installed for Ubuntu && Debian + Here is the command line to get these dependencies installed for Ubuntu && Debian - $ sudo apt-get install libtool intltool libgtk2.0-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev libglew1.6-dev libv4l-dev libxml2-dev + $ sudo apt-get install libtool intltool libgtk2.0-dev libspeexdsp-dev \ +libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev \ +libglew1.6-dev libv4l-dev libxml2-dev + for optional library - $ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev libsoup2.4-dev libsqlite3-dev libupnp4-dev + $ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev \ +libsoup2.4-dev libsqlite3-dev libupnp4-dev + Install srtp (optional) for call encryption : $ git clone git://git.linphone.org/srtp.git - $ cd srtp && autoconf && ./configure && make - $ sudo make install + $ cd srtp && autoconf && ./configure && make + $ sudo make install - + Install zrtpcpp (optional), for unbreakable call encryption - $ sudo apt-get install cmake - $ git clone https://github.com/wernerd/ZRTPCPP.git - $ cd ZRTPCPP - $ cmake -DCORE_LIB=true -DSDES=false . && make - $ sudo make install - If you get this error: "cc1plus: error: unrecognized command line option ‘-std=c++11’", edit CMakeLists.txt and replace c++11 by c++0x . + + Install zrtp (optional), for unbreakable call encryption + $ git clone git://git.linphone.org:bzrtp + $ cd bzrtp && ./autogen.sh && ./configure && make + $ sudo make install - Compile linphone $ ./autogen.sh - $ ./configure - $ make && sudo make install + $ ./configure + $ make && sudo make install $ sudo ldconfig @@ -68,10 +68,10 @@ For macOS X, see README.macos Here is a short description of the content of the source tree. -- oRTP/ is a poweful implementation of the RTP protocol. See the oRTP/README for more details. +- oRTP/ is a poweful implementation of the RTP protocol. See the oRTP/README for more details. It is used by the mediastreamer to send and receive streams to the network. -- mediastreamer2/ is one of the important part of linphone. It is a framework library for audio +- mediastreamer2/ is one of the important part of linphone. It is a framework library for audio and video processing. It contains several objects for grabing audio and video and outputing it (through rtp, to file). It contains also codec objects to compress audio and video streams. @@ -86,6 +86,6 @@ Here is a short description of the content of the source tree. * linphonec.c is the main file for the console version of linphone. * sipomatic.c / sipomatic.h contains the code for sipomatic, the test program that auto-answer to linphone calls. * shell.c (program name: linphonecsh) is a small utilities to send interactive commands to a running linphonec daemon. - + - share/ contains translation, documentation, rings and hello sound files. diff --git a/README.macos b/README.macos deleted file mode 100644 index 05a00e080..000000000 --- a/README.macos +++ /dev/null @@ -1,145 +0,0 @@ -********************************** -* Compiling linphone on macos X * -********************************** - -You need: - - Xcode (download from apple or using appstore application) - - Macports: http://www.macports.org/ - Download and install macports using its user friendly installer. - -- In order to enable generation of bundle for multiple macos version and 32 bit processors, it is recommended to: - 1) edit /opt/local/etc/macports/macports.conf to add the following line: - macosx_deployment_target 10.6 - 2) edit /opt/local/etc/macports/variants.conf to add the following line: - +universal - -- Install build time dependencies - $ sudo port install automake autoconf libtool intltool wget cunit - -- Install some linphone dependencies with macports - $ sudo port install antlr3 speex libvpx readline sqlite3 libsoup openldap - $ sudo port install ffmpeg-devel -gpl2 - -- Install gtk. It is recommended to use the quartz backend for better integration. - $ sudo port install gtk2 +quartz +no_x11 - $ sudo port install gtk-osx-application -python27 - $ sudo port install hicolor-icon-theme - -The next pieces need to be compiled manually. To ensure compatibility with multiple mac os version it is recommended to do: - $ export MACOSX_DEPLOYMENT_TARGET=10.6 - $ export CFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" - $ export OBJCFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" - $ export CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" - $ export LDFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5 -Wl,-headerpad_max_install_names -Wl,-read_only_relocs -Wl,suppress" - -- (Optional) libvpx-1.2 has a bug on macos resulting in ugly video. It is recommended to upgrade it manually to 1.3 from source. - The libvpx build isn't able to produce dual architecture files. To workaround this, configure libvpx twice and use lipo to create a dual architecture - libvpx.a . - -- Install libantlr3c (library used by belle-sip for parsing) - $ git clone -b linphone git://git.linphone.org/antlr3.git - $ cd antlr3/runtime/C - $ ./autogen.sh - $ ./configure --disable-static --prefix=/opt/local && make - $ sudo make install - -- Install polarssl (encryption library used by belle-sip) - $ git clone git://git.linphone.org/polarssl.git -b linphone - $ cd polarssl - $ ./autogen.sh && ./configure --prefix=/opt/local && make - $ sudo make install - -- Install belle-sip (sip stack) - $ git clone git://git.linphone.org/belle-sip.git - $ cd belle-sip - $ ./autogen.sh && ./configure --prefix=/opt/local && make - $ sudo make install - -- Install srtp (optional) for call encryption - $ git clone git://git.linphone.org/srtp.git - $ cd srtp && autoconf && ./configure --prefix=/opt/local && make libsrtp.a - $ sudo make install - -- Install zrtpcpp (optional), for unbreakable call encryption - $ sudo port install cmake - $ git clone https://github.com/wernerd/ZRTPCPP.git - $ cd ZRTPCPP - $ cmake -DCORE_LIB=true -DSDES=false CMAKE_INSTALL_NAME_DIR=/usr/local/lib/ -DCMAKE_C_FLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" -DCMAKE_CXX_FLAGS="-arch i386 -arch x86_64 --stdlib=libstdc++ -std=c++11 -lstdc++ -mmacosx-version-min=10.5" -DCMAKE_C_COMPILER=`xcrun --find clang` -DCMAKE_CXX_COMPILER=`xcrun --find clang` . -$ sudo make install - - -- Install gsm codec (optional) - $ git clone git://git.linphone.org/gsm.git - $ cd gsm - $ make CCFLAGS="$CFLAGS -c -O2 -DNeedFunctionPrototypes=1" - $ sudo make install INSTALL_ROOT=/opt/local GSM_INSTALL_INC=/opt/local/include - -- Compile and install the tunnel library (optional, proprietary extension only) - - If you got the source code from git, run ./autogen.sh first. - Then or otherwise, do: - - $ ./configure --prefix=/opt/local && make && sudo make install - -- Compile linphone - - If you got the source code from git, run ./autogen.sh first. - - Then or otherwise, do: - - $ PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --prefix=/opt/local --with-readline=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp --disable-strict && make - - Install to /opt/local - - $ sudo make install - - Done. - -If you want to generate a portable bundle, then install gtk-mac-bundler. -Use git: - $ git clone https://github.com/jralls/gtk-mac-bundler.git - $ cd gtk-mac-bundler && make install - $ export PATH=$PATH:~/.local/bin - #make this dummy charset.alias file for the bundler to be happy: - $ sudo touch touch /opt/local/lib/charset.alias - -The bundler file in build/macos/linphone.bundle expects some plugins to be installed in /opt/local/lib/mediastreamer/plugins . -If you don't need plugins, remove or comment out this line from the bundler file: - - ${prefix:ms2plugins}/lib/mediastreamer/plugins/*.*.so - - -Then run, inside linphone source tree: - Run configure as told before but with "--enable-relativeprefix" appended. - $ make - $ make bundle - -The resulting bundle is located in linphone build directory, together with a zipped version. - -For a better appearance, you can install the gtk-quartz-engine (a gtk theme) that make gtk application more similar to other mac applications (but not perfect). - - $ git clone https://github.com/jralls/gtk-quartz-engine.git - $ cd gtk-quartz-engine - $ autoreconf -i - $ ./configure --prefix=/opt/local CFLAGS="$CFLAGS -Wno-error" && make - $ sudo make install - -Generate a new bundle to have it included. - -libiconv hack -************* - -The Makefile.am rules used to generate the bundle fetch a libiconv.2.dylib from a linphone download page. -This library adds some additional symbols so that dependencies requiring the iconv from /usr/lib and the ones requiring from the bundle are both satisfied. -In case this library needs to generated, here are the commands: - $ wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz - $ cd libiconv-1.14 - $ patch -p1 < ../linphone/build/macos/libiconv-macos.patch - $ ./configure --prefix=/opt/local --disable-static 'CFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' 'LDFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" && make - $ make install DESTDIR=/tmp - -The resulted library can be found in /tmp/opt/local/lib - - - - diff --git a/README.macos.md b/README.macos.md new file mode 100644 index 000000000..cbdd4c24c --- /dev/null +++ b/README.macos.md @@ -0,0 +1,184 @@ +# Compiling Linphone on MacOS X + +## Dependencies + +* Xcode (download from apple or using appstore application) +* Java SE +* [HomeBrew](http://brew.sh) or [Macports](http://www.macports.org/). + +### Multiple MacOS version support + +In order to enable generation of bundle for multiple MacOS version and 32 bit processors, it is recommended to: + +1. Edit `/opt/local/etc/macports/macports.conf` to add the following line: + + > macosx_deployment_target 10.6 + +2. Edit `/opt/local/etc/macports/variants.conf` to add the following line: + + > +universal + +### Build time dependencies + +#### Using MacPorts + +* Linphone core dependencies + + sudo port install automake autoconf libtool intltool wget cunit \ + antlr3 speex libvpx readline sqlite3 libsoup openldap libupnp \ + ffmpeg-devel -gpl2 + +* UI dependencies: install `GTK`. It is recommended to use the `quartz` backend for better integration. + + sudo port install gtk2 +quartz +no_x11 + sudo port install gtk-osx-application -python27 + sudo port install hicolor-icon-theme + + #### Using HomeBrew + + brew install automake intltool libtool pkg-config coreutils \ + yasm nasm wget imagemagick gettext gtk+ speex ffmpeg pygtk + brew link gettext --force + # readline is required from linphonec.c otherwise compilation will fail + brew link readline --force + + # then you have to install antlr3 from a tap. + wget https://gist.githubusercontent.com/Gui13/f5cf103f50d34c28c7be/raw/f50242f5e0c3a6d25ed7fca1462bce3a7b738971/antlr3.rb + mv antlr3.rb /usr/local/Library/Formula/ + brew install antlr3 + + brew tap marekjelen/gtk + brew install gtk+-quartz + + # gtk-mac-integration is not available in main repository or Brew yet. + wget https://gist.github.com/Gui13/cdcad37faa6b8ffa0588/raw/bf2277d45e261ad48ae1344c4c97f2684974ed87/gtk-mac-integration.rb + mv gtk-mac-integration.rb /usr/local/Library/Formula/ + brew install gtk-mac-integration + +### Building Linphone + +The next pieces need to be compiled manually. + +* To ensure compatibility with multiple MacOS versions it is recommended to do: + + export MACOSX_DEPLOYMENT_TARGET=10.6 + export CFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" + export OBJCFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" + export CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" + export LDFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5 -Wl,-headerpad_max_install_names -Wl,-read_only_relocs -Wl,suppress" + +* Install libantlr3c (library used by belle-sip for parsing) + + git clone -b linphone git://git.linphone.org/antlr3.git + cd antlr3/runtime/C + ./autogen.sh + ./configure --disable-static --prefix=/opt/local && make + sudo make install + +* Install polarssl (encryption library used by belle-sip) + + git clone git://git.linphone.org/polarssl.git -b linphone + cd polarssl + ./autogen.sh && ./configure --prefix=/opt/local && make + sudo make install + +* Install belle-sip (sip stack) + + git clone git://git.linphone.org/belle-sip.git + cd belle-sip + ./autogen.sh && ./configure --prefix=/opt/local && make + sudo make install + +* (Optional) Install srtp for call encryption + + git clone git://git.linphone.org/srtp.git + cd srtp && autoconf && ./configure --prefix=/opt/local && make libsrtp.a + sudo make install + +* (Optional) Install zrtp, for unbreakable call encryption + + git clone git://git.linphone.org:bzrtp + cd bzrtp && ./autogen.sh && ./configure --prefix=/opt/local && make + sudo make install + +* (Optional) Install gsm codec + + git clone git://git.linphone.org/gsm.git + cd gsm + make CCFLAGS="$CFLAGS -c -O2 -DNeedFunctionPrototypes=1" + sudo make install INSTALL_ROOT=/opt/local GSM_INSTALL_INC=/opt/local/include + +* (Optional) libvpx-1.2 has a bug on MacOS resulting in ugly video. It is recommended to upgrade it manually to 1.3 from source. +The libvpx build isn't able to produce dual architecture files. To workaround this, configure libvpx twice and use lipo to create a dual architecture `libvpx.a`. + +* (Optional, proprietary extension only) Compile and install the tunnel library + + If you got the source code from git, run `./autogen.sh` first. + Then or otherwise, do: + + ./configure --prefix=/opt/local && make && sudo make install + +* Compile Linphone + + If you got the source code from git, run `./autogen.sh` first. + + Then or otherwise, do: + + PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --prefix=/opt/local --with-readline=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp --disable-strict && make + +* Install on the system + + sudo make install + +You are done. + +### Generate portable bundle + +If you want to generate a portable bundle, then install `gtk-mac-bundler`: + + git clone https://github.com/jralls/gtk-mac-bundler.git + cd gtk-mac-bundler && make install + export PATH=$PATH:~/.local/bin + #make this dummy charset.alias file for the bundler to be happy: + sudo touch /opt/local/lib/charset.alias + +The bundler file in `build/MacOS/linphone.bundle` expects some plugins to be installed in `/opt/local/lib/mediastreamer/plugins`. +If you don't need plugins, remove or comment out this line from the bundler file: + + + ${prefix:ms2plugins}/lib/mediastreamer/plugins/*.*.so + + +Then run, inside Linphone source tree configure as told before but with `--enable-relativeprefix` appended. + + make && make bundle + +The resulting bundle is located in Linphone build directory, together with a zipped version. + +* For a better appearance, you can install `gtk-quartz-engine` (a GTK theme) that makes GTK application more similar to other Mac applications (but not perfect). + + git clone https://github.com/jralls/gtk-quartz-engine.git + cd gtk-quartz-engine + autoreconf -i + ./configure --prefix=/opt/local CFLAGS="$CFLAGS -Wno-error" && make + sudo make install + +Generate a new bundle to have it included. + +### libiconv hack + +The `Makefile.am` rules used to generate the bundle fetch a `libiconv.2.dylib` from a Linphone download page. +This library adds some additional symbols so that dependencies requiring the `iconv` from `/usr/lib` and the ones requiring from the bundle are both satisfied. +In case this library needs to generated, here are the commands: + + wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz + cd libiconv-1.14 + patch -p1 < ../linphone/build/MacOS/libiconv-MacOS.patch + ./configure --prefix=/opt/local --disable-static 'CFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' 'LDFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" && make + make install DESTDIR=/tmp + +The resulted library can be found in `/tmp/opt/local/lib`. + + + + diff --git a/README.mingw b/README.mingw index 8b97ea1ef..5e859680b 100644 --- a/README.mingw +++ b/README.mingw @@ -29,7 +29,7 @@ Download lastest linphone-deps-win32 zip from http://download.savannah.gnu.org/releases-noredirect/linphone/misc using your browser. -Download lastest gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org +Download gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org, direct link: http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.24/gtk+-bundle_2.24.10-20120208_win32.zip Install all these three package in /: @@ -60,9 +60,12 @@ General rules for compilation - all other commands (configure, autogen.sh, make) must be done within the mingw shell (msys). In both msys and msys-git windows, change into the directory you created for sources: cd /c/sources +- make sure pkg-config works by adding this env variable to your terminal: + export PKG_CONFIG_PATH=/usr/lib/pkgconfig Building belle-sip ****************** + * make sure that java version 1.6 is available in the PATH. java-1.7 will not work with antlr generator. * download the sources with msys-git shell using the following command: $ git clone git://git.linphone.org/belle-sip.git * compile and install diff --git a/autogen.sh b/autogen.sh index cf357cd66..9cedbf164 100755 --- a/autogen.sh +++ b/autogen.sh @@ -22,6 +22,7 @@ if test -f /opt/local/bin/glibtoolize ; then else LIBTOOLIZE=libtoolize fi + if test -d /opt/local/share/aclocal ; then ACLOCAL_ARGS="-I /opt/local/share/aclocal" fi @@ -30,13 +31,7 @@ if test -d /share/aclocal ; then ACLOCAL_ARGS="$ACLOCAL_ARGS -I /share/aclocal" fi -if test -f /opt/local/bin/intltoolize ; then - #darwin - INTLTOOLIZE=/opt/local/bin/intltoolize -else - #on mingw, it is important to invoke intltoolize with an absolute path to avoid a bug - INTLTOOLIZE=/usr/bin/intltoolize -fi +INTLTOOLIZE=$(which intltoolize) echo "Generating build scripts in linphone..." set -x diff --git a/build/android/Android.mk b/build/android/Android.mk index 817aba539..c281b241d 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -65,10 +65,14 @@ LOCAL_SRC_FILES := \ xml2lpc.c \ lpc2xml.c \ remote_provisioning.c \ - quality_reporting.c - -ifndef LINPHONE_VERSION -LINPHONE_VERSION = "Devel" + quality_reporting.c \ + call_log.c \ + call_params.c \ + player.c \ + localplayer.c + +ifndef LIBLINPHONE_VERSION +LIBLINPHONE_VERSION = "Devel" endif LOCAL_CFLAGS += \ @@ -77,7 +81,7 @@ LOCAL_CFLAGS += \ -DINET6 \ -DENABLE_TRACE \ -DHAVE_CONFIG_H \ - -DLINPHONE_VERSION=\"$(LINPHONE_VERSION)\" \ + -DLIBLINPHONE_VERSION=\"$(LIBLINPHONE_VERSION)\" \ -DLINPHONE_PLUGINS_DIR=\"\\tmp\" \ -DUSE_BELLESIP @@ -262,5 +266,8 @@ LOCAL_MODULE_FILENAME := liblinphone-$(TARGET_ARCH_ABI) include $(BUILD_SHARED_LIBRARY) +LOCAL_CPPFLAGS=$(LOCAL_CFLAGS) +LOCAL_CFLAGS += -Wdeclaration-after-statement + $(call import-module,android/cpufeatures) diff --git a/build/android/liblinphone_gitversion.h b/build/android/liblinphone_gitversion.h deleted file mode 100644 index 50e8a106e..000000000 --- a/build/android/liblinphone_gitversion.h +++ /dev/null @@ -1 +0,0 @@ -#define LIBLINPHONE_GIT_VERSION "unknown" diff --git a/build/android/liblinphone_tester.mk b/build/android/liblinphone_tester.mk index cada1aba4..5ca3732be 100644 --- a/build/android/liblinphone_tester.mk +++ b/build/android/liblinphone_tester.mk @@ -13,7 +13,10 @@ common_SRC_FILES := \ flexisip_tester.c \ tester.c \ remote_provisioning_tester.c \ - quality_reporting_tester.c + quality_reporting_tester.c \ + log_collection_tester.c \ + transport_tester.c \ + player_tester.c common_C_INCLUDES += \ $(LOCAL_PATH) \ diff --git a/build/wp8/LibLinphone.vcxproj b/build/wp8/LibLinphone.vcxproj index 797b2517d..cca41bb87 100644 --- a/build/wp8/LibLinphone.vcxproj +++ b/build/wp8/LibLinphone.vcxproj @@ -53,8 +53,8 @@ Level4 - $(ProjectDir)..\..\..\belle-sip\include;$(ProjectDir)..\..\oRTP\include;$(ProjectDir)..\..\mediastreamer2\include;$(ProjectDIr)..\..\..\tunnel\include;$(ProjectDir)..\..\coreapi;$(ProjectDir)..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;%(AdditionalIncludeDirectories) - __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) + $(ProjectDir)..\..\..\belle-sip\include;$(ProjectDir)..\..\oRTP\include;$(ProjectDir)..\..\mediastreamer2\include;$(ProjectDir)..\..\..\tunnel\include;$(ProjectDir)..\..\coreapi;$(ProjectDir)..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\zlib;$(ProjectDir)..\..\..\sqlite\;$(ProjectDir);%(AdditionalIncludeDirectories) + __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";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR=".";UNICODE;_XKEYCHECK_H;HAVE_ZLIB;HAVE_CONFIG_H;%(PreprocessorDefinitions) Default NotUsing false @@ -68,13 +68,16 @@ $(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) $(TargetDir)$(TargetName).lib - - $(TargetDir)$(TargetName)_dll.lib;%(Outputs) - + + version.bat + + + Batch script to get the git version + - _DEBUG;%(PreprocessorDefinitions) + _DEBUG;MSG_STORAGE_ENABLED;%(PreprocessorDefinitions) true @@ -82,7 +85,7 @@ - NDEBUG;%(PreprocessorDefinitions) + NDEBUG;MSG_STORAGE_ENABLED;%(PreprocessorDefinitions) MaxSpeed true true @@ -107,6 +110,8 @@ + + @@ -119,11 +124,13 @@ + + @@ -148,6 +155,8 @@ + + @@ -186,6 +195,9 @@ {0565952a-ea62-46a2-8261-f5b4b490da42} + + {a45d63b9-60de-476c-8836-f8eedbe139d0} + {59500dd1-b192-4ddf-a402-8a8e3739e032} @@ -198,6 +210,9 @@ {5dfa07b4-0be9-46a9-ba32-fdf5a55c580b} + + {7afac3bb-d97b-4578-b9fe-5e1d2b94ea2f} + diff --git a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj index 424044515..021ab6328 100644 --- a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj +++ b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj @@ -100,11 +100,13 @@ + + true @@ -153,4 +155,4 @@ - \ No newline at end of file + diff --git a/build/wp8/version.bat b/build/wp8/version.bat new file mode 100644 index 000000000..55ee42831 --- /dev/null +++ b/build/wp8/version.bat @@ -0,0 +1,22 @@ +@ECHO off + +SET gitlog= +FOR /f "delims=" %%a IN ('git log -1 "--pretty=format:%%H" ../../configure.ac') DO SET gitlog=%%a + +IF [%gitlog%] == [] GOTO UnknownGitVersion + +FOR /f "delims=" %%a IN ('git describe --always') DO SET gitdescribe=%%a +GOTO End + +:UnknownGitVersion +SET gitdescribe=unknown + +:End +ECHO #define LIBLINPHONE_GIT_VERSION "%gitdescribe%" > liblinphone_gitversion.h + + +FOR /F "delims=" %%a IN ('findstr /B AC_INIT ..\..\configure.ac') DO ( + FOR /F "tokens=1,2,3 delims=[,]" %%1 IN ("%%a") DO ( + ECHO #define LIBLINPHONE_VERSION "%%3" > config.h + ) +) diff --git a/build/wp8/zlib/zconf.h b/build/wp8/zlib/zconf.h new file mode 100644 index 000000000..a3a6b54fc --- /dev/null +++ b/build/wp8/zlib/zconf.h @@ -0,0 +1,513 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2013 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H +/* #undef Z_PREFIX */ +#define Z_HAVE_UNISTD_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/build/wp8/zlib/zlib.sln b/build/wp8/zlib/zlib.sln new file mode 100644 index 000000000..97b0cc6a9 --- /dev/null +++ b/build/wp8/zlib/zlib.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2012 for Windows Phone +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib.vcxproj", "{7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|Win32 = Debug|Win32 + Release|ARM = Release|ARM + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Debug|ARM.ActiveCfg = Debug|ARM + {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Debug|ARM.Build.0 = Debug|ARM + {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Debug|Win32.ActiveCfg = Debug|Win32 + {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Debug|Win32.Build.0 = Debug|Win32 + {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Release|ARM.ActiveCfg = Release|ARM + {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Release|ARM.Build.0 = Release|ARM + {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Release|Win32.ActiveCfg = Release|Win32 + {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/build/wp8/zlib/zlib.vcxproj b/build/wp8/zlib/zlib.vcxproj new file mode 100644 index 000000000..34c9aa46f --- /dev/null +++ b/build/wp8/zlib/zlib.vcxproj @@ -0,0 +1,135 @@ + + + + + Debug + Win32 + + + Debug + ARM + + + Release + Win32 + + + Release + ARM + + + + {7afac3bb-d97b-4578-b9fe-5e1d2b94ea2f} + zlib + en-US + 11.0 + + + + DynamicLibrary + true + v110_wp80 + false + + + DynamicLibrary + false + true + v110_wp80 + false + + + + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(TargetName)\ + + + false + + + + Level4 + $(ProjectDir);$(ProjectDir)..\..\..\..\zlib;%(AdditionalIncludeDirectories) + _WIN32;_WINDLL;_USRDLL;_CRT_SECURE_NO_WARNINGS;UNICODE;%(PreprocessorDefinitions) + Default + NotUsing + false + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + + + Console + false + false + $(TargetDir)$(TargetName).lib + Ws2_32.lib;%(AdditionalDependencies) + $(ProjectDir)..\..\..\..\zlib\win32\zlib.def + + + + + _DEBUG;%(PreprocessorDefinitions) + + + true + + + + + NDEBUG;%(PreprocessorDefinitions) + MaxSpeed + true + true + true + + + false + + + + + true + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config.h.cmake b/config.h.cmake index aa49b3b98..f348cf3f9 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -24,6 +24,7 @@ #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}" diff --git a/configure.ac b/configure.ac index 6d295b694..02452ce7c 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) AC_SUBST([docdir], [${datadir}/doc]) AC_CONFIG_HEADERS(config.h) AC_CONFIG_MACRO_DIR([m4]) -dnl don't put anythingelse before AC_PROG_CC unless checking if macro still work for clang +dnl do not put anythingelse before AC_PROG_CC unless checking if macro still work for clang AC_PROG_CXX(["xcrun clang++" g++]) AC_PROG_CC(["xcrun clang" gcc]) @@ -135,7 +135,7 @@ AC_DEFINE_UNQUOTED(LINPHONE_ALL_LANGS, "$ALL_LINGUAS", [All supported languages] if test "$mingw_found" != "yes" ; then dnl gettext macro does not work properly under mingw. And we want to use the one provided by GTK. - + dnl AM_GNU_GETTEXT pollutes CPPFLAGS: workaround this. CPPFLAGS_save=$CPPFLAGS AM_GNU_GETTEXT([external]) @@ -185,29 +185,29 @@ if test "$enable_ldap" = "true"; then [AC_MSG_ERROR([You need libldap for LDAP support])] ) AC_CHECK_HEADERS(ldap.h, [foo=bar], [AC_MSG_ERROR( [ldap.h not found] ) ] ) - found_ldap=yes + found_ldap=yes fi - + PKG_CHECK_MODULES(SASL, [libsasl2],[found_sasl=yes],[found_sasl=no] ) - + if test "$found_sasl" = "no"; then AC_CHECK_LIB(sasl2, sasl_client_init , [SASL_LIBS="-lsasl2"], [AC_MSG_ERROR([You need SASL for LDAP support] ) ] ) AC_CHECK_HEADERS(sasl/sasl.h,foo=bar, [AC_MSG_ERROR([sasl/sasl.h not found])]) - found_sasl=yes + found_sasl=yes fi - + AC_SUBST(LDAP_CFLAGS) AC_SUBST(LDAP_LIBS) - + AC_SUBST(SASL_CFLAGS) AC_SUBST(SASL_LIBS) - + if test "$found_ldap$found_sasl" = "yesyes"; then AC_DEFINE(BUILD_LDAP,1,[Defined if LDAP build option enabled]) else - AC_MSG_ERROR([Can't use LDAP due to previous errors]) + AC_MSG_ERROR([Cannot use LDAP due to previous errors]) fi fi @@ -248,7 +248,7 @@ AC_ARG_ENABLE(upnp, ) if test "$build_upnp" != "false" ; then - PKG_CHECK_MODULES([LIBUPNP], [libupnp], + PKG_CHECK_MODULES([LIBUPNP], [libupnp], [if pkg-config --atleast-version=1.6 "libupnp < 1.7"; then build_upnp=true else @@ -277,7 +277,7 @@ fi AM_CONDITIONAL(BUILD_TOOLS, test x$build_tools != xfalse) if test "$build_tools" != "false" ; then build_tools=true - AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] ) + AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] ) fi dnl conditionnal build of gtk interface. @@ -553,10 +553,10 @@ AC_ARG_WITH(ffmpeg, ) if test "$video" = "true"; then - + if test "$enable_x11" = "true"; then AC_CHECK_HEADERS(X11/Xlib.h) - if test "$build_macos" = "yes"; then + if test "$build_macos" = "yes"; then X11_LIBS="-L/usr/X11/lib -lX11" else AC_CHECK_LIB(X11,XUnmapWindow, X11_LIBS="-lX11") @@ -644,7 +644,7 @@ AC_SUBST(LIBSOUP_LIBS) AM_CONDITIONAL(BUILD_WIZARD, test x$build_wizard != xfalse) if test "$build_wizard" != "false" ; then build_wizard=true - AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] ) + AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] ) fi AC_CHECK_HEADERS(libudev.h) @@ -656,27 +656,42 @@ AC_CHECK_LIB(udev,udev_new) AC_ARG_ENABLE(strict, - AC_HELP_STRING([--enable-strict], [Build with stricter options (gcc only) @<:@yes@:>@]), + AC_HELP_STRING([--enable-strict], [Build with stricter options @<:@yes@:>@]), [strictness="${enableval}"], [strictness=yes] ) -STRICT_OPTIONS="-Wall" +STRICT_OPTIONS="-Wall -Wuninitialized" +STRICT_OPTIONS_CC="-Wdeclaration-after-statement " +STRICT_OPTIONS_CXX="" #for clang -case $CC in +case $CC in *clang*) - STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments" + STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments " + #disabled due to wrong optimization false positive with small string + #(cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35903) + STRICT_OPTIONS="$STRICT_OPTIONS -Wno-array-bounds " + ;; +esac +# because Darwin's gcc is actually clang, we need to check it... +case "$target_os" in + *darwin*) + STRICT_OPTIONS="$STRICT_OPTIONS -Wno-error=unknown-warning-option -Qunused-arguments -Wno-tautological-compare -Wno-unused-function " + #disabled due to wrong optimization false positive with small string + #(cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35903) + STRICT_OPTIONS="$STRICT_OPTIONS -Wno-array-bounds " ;; esac - if test "$strictness" = "yes" ; then STRICT_OPTIONS="$STRICT_OPTIONS -Werror" CFLAGS="$CFLAGS -fno-strict-aliasing" fi AC_SUBST(STRICT_OPTIONS) +AC_SUBST(STRICT_OPTIONS_CC) +AC_SUBST(STRICT_OPTIONS_CXX) top_srcdir=`dirname $0` @@ -794,13 +809,13 @@ if test x$enable_msg_storage != xfalse; then fi enable_msg_storage=false fi - + AC_SUBST(SQLITE3_CFLAGS) AC_SUBST(SQLITE3_LIBS) fi - + PKG_CHECK_MODULES(BELLESIP, [belle-sip >= 1.3.1]) SIPSTACK_CFLAGS="$BELLESIP_CFLAGS" @@ -894,11 +909,11 @@ dnl ################################################## dnl # Check for doxygen dnl ################################################## -AC_PATH_PROG(DOXYGEN,doxygen,false) -AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false) +AC_CHECK_PROG(DOXYGEN,doxygen,doxygen,false) +AM_CONDITIONAL(HAVE_DOXYGEN, test "$DOXYGEN" != "false") -AC_CONFIG_FILES([ +AC_CONFIG_FILES([ Makefile build/Makefile build/macos/Makefile diff --git a/console/Makefile.am b/console/Makefile.am index 314f5d612..482948329 100644 --- a/console/Makefile.am +++ b/console/Makefile.am @@ -3,12 +3,13 @@ AM_CPPFLAGS=\ -I$(top_srcdir) \ -I$(top_srcdir)/coreapi \ - -I$(top_srcdir)/include + -I$(top_srcdir)/include COMMON_CFLAGS=\ -DIN_LINPHONE \ -D_ORTP_SOURCE \ $(STRICT_OPTIONS) \ + $(STRICT_OPTIONS_CC) \ $(ORTP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ $(VIDEO_CFLAGS) \ diff --git a/console/commands.c b/console/commands.c index f0b44bdd5..9f6d0c1c2 100644 --- a/console/commands.c +++ b/console/commands.c @@ -603,6 +603,7 @@ lpc_cmd_chat(LinphoneCore *lc, char *args) char *arg1 = args; char *arg2 = NULL; char *ptr = args; + LinphoneChatRoom *cr; if (!args) return 0; @@ -619,7 +620,7 @@ lpc_cmd_chat(LinphoneCore *lc, char *args) /* missing one parameter */ return 0; } - LinphoneChatRoom *cr = linphone_core_create_chat_room(lc,arg1); + cr = linphone_core_create_chat_room(lc,arg1); linphone_chat_room_send_message(cr,arg2); return 1; } @@ -1600,7 +1601,7 @@ linphonec_proxy_add(LinphoneCore *lc) */ if ( enable_register==TRUE ) { - long int expires=0; + int expires=0; while (1) { char *input=linphonec_readline("Specify register expiration time" @@ -1612,13 +1613,8 @@ linphonec_proxy_add(LinphoneCore *lc) return; } - expires=strtol(input, (char **)NULL, 10); - if ( expires == LONG_MIN || expires == LONG_MAX ) - { - linphonec_out("Invalid value: %s\n", strerror(errno)); - free(input); - continue; - } + expires=atoi(input); + if (expires==0) expires=600; linphone_proxy_config_set_expires(cfg, expires); linphonec_out("Expiration: %d seconds\n", linphone_proxy_config_get_expires (cfg)); @@ -2441,8 +2437,9 @@ static void lpc_display_call_states(LinphoneCore *lc){ }else{ for(;elem!=NULL;elem=elem->next){ const char *flag; + bool_t in_conference; call=(LinphoneCall*)elem->data; - bool_t in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); + in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); tmp=linphone_call_get_remote_address_as_string (call); flag=in_conference ? "conferencing" : ""; flag=linphone_call_has_transfer_pending(call) ? "transfer pending" : flag; diff --git a/console/linphonec.c b/console/linphonec.c index ff16e1387..439702b85 100644 --- a/console/linphonec.c +++ b/console/linphonec.c @@ -367,8 +367,8 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L if ( auto_answer) { answer_call=TRUE; } else if (real_early_media_sending) { - linphonec_out("Sending early media using real hardware\n"); LinphoneCallParams* callparams = linphone_core_create_default_call_parameters(lc); + linphonec_out("Sending early media using real hardware\n"); linphone_call_params_enable_early_media_sending(callparams, TRUE); if (vcap_enabled) linphone_call_params_enable_video(callparams, TRUE); linphone_core_accept_early_media_with_params(lc, call, callparams); @@ -500,7 +500,6 @@ static void *pipe_thread(void*p){ } static void start_pipe_reader(void){ - ms_mutex_init(&prompt_mutex,NULL); pipe_reader_run=TRUE; ortp_thread_create(&pipe_reader_th,NULL,pipe_thread,NULL); } @@ -536,6 +535,7 @@ char *linphonec_readline(char *prompt){ fprintf(stdout,"%s",prompt); fflush(stdout); while(1){ + ms_mutex_lock(&prompt_mutex); if (have_prompt){ char *ret=strdup(received_prompt); @@ -546,15 +546,17 @@ char *linphonec_readline(char *prompt){ ms_mutex_unlock(&prompt_mutex); linphonec_idle_call(); #ifdef WIN32 - Sleep(20); - /* Following is to get the video window going as it - should. Maybe should we only have this on when the option -V - or -D is on? */ - MSG msg; - - if (PeekMessage(&msg, NULL, 0, 0,1)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + { + MSG msg; + Sleep(20); + /* Following is to get the video window going as it + should. Maybe should we only have this on when the option -V + or -D is on? */ + + if (PeekMessage(&msg, NULL, 0, 0,1)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } #else usleep(20000); @@ -802,6 +804,7 @@ linphonec_finish(int exit_status) if (mylogfile != NULL && mylogfile != stdout) { fclose (mylogfile); + mylogfile=stdout; } printf("\n"); exit(exit_status); @@ -828,12 +831,13 @@ linphonec_prompt_for_auth_final(LinphoneCore *lc) #ifdef HAVE_READLINE rl_hook_func_t *old_event_hook; #endif + LinphoneAuthInfo *pending_auth; if (reentrancy!=0) return 0; reentrancy++; - LinphoneAuthInfo *pending_auth=auth_stack.elem[auth_stack.nitems-1]; + pending_auth=auth_stack.elem[auth_stack.nitems-1]; snprintf(auth_prompt, 256, "Password for %s on %s: ", pending_auth->username, pending_auth->realm); diff --git a/console/shell.c b/console/shell.c index bfc758bf8..016992397 100644 --- a/console/shell.c +++ b/console/shell.c @@ -177,12 +177,14 @@ static void spawn_linphonec(int argc, char *argv[]){ static void spawn_linphonec(int argc, char *argv[]){ PROCESS_INFORMATION pinfo; STARTUPINFO si; + BOOL ret; + ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pinfo, sizeof(pinfo) ); - BOOL ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL", + ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL", NULL, NULL, FALSE, diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 2be82be73..8ed8185ab 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -42,6 +42,8 @@ set(SOURCE_FILES bellesip_sal/sal_op_registration.c bellesip_sal/sal_sdp.c callbacks.c + call_log.c + call_params.c chat.c conference.c ec-calibrator.c @@ -51,13 +53,13 @@ set(SOURCE_FILES info.c linphonecall.c linphonecore.c - linphone_tunnel_stubs.c linphone_tunnel_config.c lpconfig.c lsd.c message_storage.c misc.c offeranswer.c + player.c presence.c proxy.c quality_reporting.c @@ -86,6 +88,8 @@ if(ENABLE_TUNNEL) TunnelManager.cc ) add_definitions(-DTUNNEL_ENABLED) +else() + list(APPEND SOURCE_FILES linphone_tunnel_stubs.c) endif() set(GENERATED_SOURCE_FILES @@ -94,7 +98,7 @@ set(GENERATED_SOURCE_FILES 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} -DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/gitversion.cmake) + 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( -DIN_LINPHONE @@ -113,6 +117,12 @@ set(LIBS ${MS2_LIBRARIES} ${XML2_LIBRARIES} ) +if(ENABLE_TUNNEL) + list(APPEND LIBS ${TUNNEL_LIBRARIES}) +endif() +if(WIN32) + list(APPEND LIBS shlwapi) +endif() if(ENABLE_STATIC) add_library(linphone STATIC ${SOURCE_FILES} ${GENERATED_SOURCE_FILES}) @@ -139,7 +149,20 @@ install(TARGETS linphone ) -file(GLOB HEADER_FILES "*.h") +set(HEADER_FILES + call_log.h + call_params.h + event.h + linphonecore.h + linphonecore_utils.h + linphonefriend.h + linphonepresence.h + linphone_tunnel.h + lpc2xml.h + lpconfig.h + sipsetup.h + xml2lpc.h +) install(FILES ${HEADER_FILES} DESTINATION include/linphone diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 5b4460c79..2bb8498d9 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -6,10 +6,10 @@ 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, +## 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) +GITLOG=$(shell git log -1 --pretty=format:%H $(top_srcdir)/configure.ac) ECHO=/bin/echo @@ -24,7 +24,7 @@ CLEANFILES=$(GITVERSION_FILE) ## Process this file with automake to produce Makefile.in linphone_includedir=$(includedir)/linphone -linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h +linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h call_log.h call_params.h lib_LTLIBRARIES=liblinphone.la @@ -59,12 +59,16 @@ liblinphone_la_SOURCES=\ lpc2xml.c \ remote_provisioning.c \ quality_reporting.c quality_reporting.h\ + call_log.c \ + call_params.c \ + player.c \ + localplayer.c \ $(GITVERSION_FILE) if BUILD_UPNP liblinphone_la_SOURCES+=upnp.c upnp.h endif - + liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \ bellesip_sal/sal_impl.c bellesip_sal/sal_impl.h \ bellesip_sal/sal_op_impl.c \ @@ -79,7 +83,7 @@ liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \ bellesip_sal/sal_op_events.c if BUILD_WIZARD -liblinphone_la_SOURCES+=sipwizard.c +liblinphone_la_SOURCES+=sipwizard.c endif liblinphone_la_SOURCES+=linphone_tunnel_config.c @@ -138,8 +142,9 @@ endif AM_CPPFLAGS=\ -I$(top_srcdir) -I$(top_srcdir)/include -I$(builddir) -AM_CFLAGS=\ - $(STRICT_OPTIONS) -DIN_LINPHONE \ +COMMON_CFLAGS=\ + $(STRICT_OPTIONS) \ + -DIN_LINPHONE \ $(ORTP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ $(SIPSTACK_CFLAGS) \ @@ -155,15 +160,16 @@ AM_CFLAGS=\ $(LDAP_CFLAGS) $(SASL_CFLAGS) if BUILD_WIZARD -AM_CFLAGS+= -DBUILD_WIZARD +COMMON_CFLAGS+= -DBUILD_WIZARD endif -AM_CFLAGS+= -DUSE_BELLESIP +COMMON_CFLAGS+= -DUSE_BELLESIP -AM_CXXFLAGS=$(AM_CFLAGS) +AM_CFLAGS=$(COMMON_CFLAGS) $(STRICT_OPTIONS_CC) +AM_CXXFLAGS=$(COMMON_CFLAGS) $(STRICT_OPTIONS_CXX) #Make sure that we are in linphone's git tree by doing git log $(top_srcdir)/configure.ac. -#if it is something known to git, then that will be ok to check the git describe number and make sure it is consistent with +#if it is something known to git, then that will be ok to check the git describe number and make sure it is consistent with #the PACKAGE_VERSION given in configure.ac make_gitversion_h: diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index 2bc8cd3e0..77e26fb1b 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -1,7 +1,7 @@ /* * C Implementation: tunnel * - * Description: + * Description: * * * Author: Simon Morlat , (C) 2009 @@ -19,18 +19,17 @@ #ifndef USE_BELLESIP #include "eXosip2/eXosip_transport_hook.h" #endif -#include "tunnel/udp_mirror.hh" #include "private.h" #ifdef ANDROID #include #endif +belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel); using namespace belledonnecomm; using namespace ::std; - void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) { if (ip == NULL) { ip = ""; @@ -53,7 +52,6 @@ void TunnelManager::cleanServers() { mServerAddrs.clear(); UdpMirrorClientList::iterator it; - mAutoDetectStarted=false; for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) { UdpMirrorClient& s=*it++; s.stop(); @@ -67,11 +65,6 @@ void TunnelManager::reconnect(){ mTunnelClient->reconnect(); } -void TunnelManager::setCallback(StateCallback cb, void *userdata) { - mCallback=cb; - mCallbackData=userdata; -} - static void sCloseRtpTransport(RtpTransport *t, void *userData){ TunnelSocket *s=(TunnelSocket*)userData; TunnelManager *manager=(TunnelManager*)s->getUserPointer(); @@ -79,13 +72,16 @@ static void sCloseRtpTransport(RtpTransport *t, void *userData){ } void TunnelManager::closeRtpTransport(RtpTransport *t, TunnelSocket *s){ mTunnelClient->closeSocket(s); - ms_free(t); } static RtpTransport *sCreateRtpTransport(void* userData, int port){ return ((TunnelManager *) userData)->createRtpTransport(port); } +void sDestroyRtpTransport(RtpTransport *t){ + ms_free(t); +} + RtpTransport *TunnelManager::createRtpTransport(int port){ TunnelSocket *socket=mTunnelClient->createSocket(port); socket->setUserPointer(this); @@ -94,30 +90,26 @@ RtpTransport *TunnelManager::createRtpTransport(int port){ t->t_recvfrom=customRecvfrom; t->t_sendto=customSendto; t->t_close=sCloseRtpTransport; + t->t_destroy=sDestroyRtpTransport; t->data=socket; return t; } -void TunnelManager::start() { - if (!mTunnelClient) { - mTunnelClient = new TunnelClient(); - mTunnelClient->setCallback((StateCallback)tunnelCallback,this); - list::iterator it; - for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){ - const ServerAddr &addr=*it; - mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort); - } - mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str()); +void TunnelManager::startClient() { + ms_message("TunnelManager: Starting tunnel client"); + mTunnelClient = new TunnelClient(); + mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this); + list::iterator it; + for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){ + const ServerAddr &addr=*it; + mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort); } + mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str()); mTunnelClient->start(); } -bool TunnelManager::isStarted() { - return mTunnelClient != 0 && mTunnelClient->isStarted(); -} - -bool TunnelManager::isReady() const { - return mTunnelClient && mTunnelClient->isReady() && mReady; +bool TunnelManager::isConnected() const { + return mTunnelClient != NULL && mTunnelClient->isReady(); } int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){ @@ -135,15 +127,19 @@ int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flag } -TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController() -,mCore(lc) -,mCallback(NULL) -,mEnabled(false) -,mTunnelClient(NULL) -,mAutoDetectStarted(false) -,mReady(false) -,mHttpProxyPort(0){ - +TunnelManager::TunnelManager(LinphoneCore* lc) : + mCore(lc), +#ifndef USE_BELLESIP + mSipSocket(NULL), + mExosipTransport(NULL), +#endif + mMode(LinphoneTunnelModeDisable), + mState(disabled), + mTunnelizeSipPackets(true), + mTunnelClient(NULL), + mHttpProxyPort(0), + mVTable(NULL) +{ linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this); mTransportFactories.audio_rtcp_func=sCreateRtpTransport; mTransportFactories.audio_rtcp_func_data=this; @@ -153,104 +149,103 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController() mTransportFactories.video_rtcp_func_data=this; mTransportFactories.video_rtp_func=sCreateRtpTransport; mTransportFactories.video_rtp_func_data=this; + mVTable = linphone_core_v_table_new(); + mVTable->network_reachable = networkReachableCb; + linphone_core_add_listener(mCore, mVTable); } TunnelManager::~TunnelManager(){ - stopClient(); -} - -void TunnelManager::stopClient(){ - sal_disable_tunnel(mCore->sal); - if (mTunnelClient){ - delete mTunnelClient; - mTunnelClient=NULL; + for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) { + udpMirror->stop(); } + if(mTunnelClient) delete mTunnelClient; + linphone_core_remove_listener(mCore, mVTable); + linphone_core_v_table_destroy(mVTable); } -void TunnelManager::processTunnelEvent(const Event &ev){ +void TunnelManager::doRegistration(){ LinphoneProxyConfig* lProxy; linphone_core_get_default_proxy(mCore, &lProxy); + if (lProxy) { + ms_message("TunnelManager: New registration"); + lProxy->commit = TRUE; + } +} - if (mEnabled && mTunnelClient->isReady()){ - ms_message("Tunnel is up, registering now"); - linphone_core_set_firewall_policy(mCore,LinphonePolicyNoFirewall); - linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories); - - sal_enable_tunnel(mCore->sal, mTunnelClient); +void TunnelManager::doUnregistration() { + LinphoneProxyConfig *lProxy; + linphone_core_get_default_proxy(mCore, &lProxy); + if(lProxy) { + _linphone_proxy_config_unregister(lProxy); + } +} - //register - if (lProxy) { - linphone_proxy_config_refresh_register(lProxy); +void TunnelManager::processTunnelEvent(const Event &ev){ + if (ev.mData.mConnected){ + ms_message("TunnelManager: tunnel is connected"); + if(mState == connecting) { + linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories); + if(mTunnelizeSipPackets) { + doUnregistration(); + sal_enable_tunnel(mCore->sal, mTunnelClient); + doRegistration(); + } + mState = ready; } - mReady=true; - }else if (mEnabled && !mTunnelClient->isReady()){ - /* we got disconnected from the tunnel */ - mReady=false; + } else { + ms_error("TunnelManager: tunnel has been disconnected"); } } -void TunnelManager::waitUnRegistration(){ - LinphoneProxyConfig* lProxy; - linphone_core_get_default_proxy(mCore, &lProxy); - if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) { - int i=0; - linphone_proxy_config_edit(lProxy); - linphone_proxy_config_enable_register(lProxy,FALSE); - linphone_proxy_config_done(lProxy); - //make sure unregister is sent and authenticated - do{ - linphone_core_iterate(mCore); - ms_usleep(20000); - if (i>100){ - ms_message("tunnel: timeout for unregistration expired, giving up"); - break; +void TunnelManager::setMode(LinphoneTunnelMode mode) { + if(mMode == mode) return; + if((mode==LinphoneTunnelModeDisable && mState==disabled) + || (mode==LinphoneTunnelModeEnable && mState==ready)) { + return; + } + ms_message("TunnelManager: switching mode from %s to %s", + tunnel_mode_to_string(mMode), + tunnel_mode_to_string(mode)); + switch(mode) { + case LinphoneTunnelModeEnable: + if(mState == disabled) { + startClient(); + mState = connecting; + mMode = mode; + } else { + ms_error("TunnelManager: could not change mode. Bad state"); + } + break; + case LinphoneTunnelModeDisable: + if(mState == ready) { + linphone_core_set_rtp_transport_factories(mCore,NULL); + if(mTunnelizeSipPackets) { + doUnregistration(); + sal_disable_tunnel(mCore->sal); } - i++; - }while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared); - } -} - -void TunnelManager::enable(bool isEnable) { - ms_message("Turning tunnel [%s]",(isEnable?"on":"off")); - if (isEnable && !mEnabled){ - mEnabled=true; - //1 save transport and firewall policy - linphone_core_get_sip_transports(mCore, &mRegularTransport); - mPreviousFirewallPolicy=linphone_core_get_firewall_policy(mCore); - //2 unregister - waitUnRegistration(); - //3 insert tunnel - start(); - }else if (!isEnable && mEnabled){ - //1 unregister - waitUnRegistration(); - - mEnabled=false; - stopClient(); - mReady=false; - linphone_core_set_rtp_transport_factories(mCore,NULL); - - sal_disable_tunnel(mCore->sal); - // Set empty transports to force the setting of regular transport, otherwise it is not applied - LCSipTransports lTransport; - lTransport.udp_port = 0; - lTransport.tcp_port = 0; - lTransport.tls_port = 0; - lTransport.dtls_port = 0; - linphone_core_set_sip_transports(mCore, &lTransport); - - //Restore transport and firewall policy - linphone_core_set_sip_transports(mCore, &mRegularTransport); - linphone_core_set_firewall_policy(mCore, mPreviousFirewallPolicy); - //register - LinphoneProxyConfig* lProxy; - linphone_core_get_default_proxy(mCore, &lProxy); - if (lProxy) { - linphone_proxy_config_edit(lProxy); - linphone_proxy_config_enable_register(lProxy,TRUE); - linphone_proxy_config_done(lProxy); + delete mTunnelClient; + mTunnelClient=NULL; + if(mTunnelizeSipPackets) { + doRegistration(); + } + mState = disabled; + mMode = mode; + } else { + ms_error("TunnelManager: could not change mode. Bad state"); } - + break; + case LinphoneTunnelModeAuto: + if(mState == disabled || mState == ready) { + if(startAutoDetection()) { + mState = autodetecting; + mMode = mode; + } + } else { + ms_error("TunnelManager: could not change mode. Bad state"); + } + break; + default: + ms_error("TunnelManager::setMode(): invalid mode (%d)", mode); } } @@ -320,30 +315,39 @@ void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) { SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN); } } - -bool TunnelManager::isEnabled() { - return mEnabled; + +LinphoneTunnelMode TunnelManager::getMode() const { + return mMode; } void TunnelManager::processUdpMirrorEvent(const Event &ev){ + if(mState != autodetecting) return; if (ev.mData.mHaveUdp) { - LOGI("Tunnel is not required, disabling"); - enable(false); - mAutoDetectStarted = false; + ms_message("TunnelManager: UDP mirror test succeed"); + if(mTunnelClient) { + if(mTunnelizeSipPackets) doUnregistration(); + delete mTunnelClient; + mTunnelClient = NULL; + if(mTunnelizeSipPackets) doRegistration(); + } + mState = disabled; } else { + ms_message("TunnelManager: UDP mirror test failed"); mCurrentUdpMirrorClient++; if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) { - // enable tunnel but also try backup server - LOGI("Tunnel is required, enabling; Trying backup udp mirror"); - + ms_message("TunnelManager: trying another UDP mirror"); UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient; lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this); } else { - LOGI("Tunnel is required, enabling; no backup udp mirror available"); - mAutoDetectStarted = false; + ms_message("TunnelManager: all UDP mirror tests failed"); + if(mTunnelClient==NULL) { + startClient(); + mState = connecting; + } else { + mState = ready; + } } - enable(true); } } @@ -361,21 +365,24 @@ void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) { thiz->postEvent(ev); } -void TunnelManager::autoDetect() { - // first check if udp mirrors was provisionned - if (mUdpMirrorClients.empty()) { - LOGE("No UDP mirror server configured aborting auto detection"); - return; +void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) { + TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc)); + if(reachable && tunnel->getMode() == LinphoneTunnelModeAuto && tunnel->mState != connecting && tunnel->mState != autodetecting) { + tunnel->startAutoDetection(); + tunnel->mState = autodetecting; } - if (mAutoDetectStarted) { - LOGE("auto detection already in progress, restarting"); - (*mCurrentUdpMirrorClient).stop(); +} + +bool TunnelManager::startAutoDetection() { + if (mUdpMirrorClients.empty()) { + ms_error("TunnelManager: No UDP mirror server configured aborting auto detection"); + return false; } - mAutoDetectStarted=true; - mCurrentUdpMirrorClient =mUdpMirrorClients.begin(); + ms_message("TunnelManager: Starting auto-detection"); + mCurrentUdpMirrorClient = mUdpMirrorClients.begin(); UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient; lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this); - + return true; } void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) { @@ -384,6 +391,14 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd); } +void TunnelManager::tunnelizeSipPackets(bool enable){ + mTunnelizeSipPackets = enable; +} + +bool TunnelManager::tunnelizeSipPacketsEnabled() const { + return mTunnelizeSipPackets; +} + void TunnelManager::setHttpProxy(const char *host,int port, const char *username, const char *passwd){ mHttpUserName=username?username:""; mHttpPasswd=passwd?passwd:""; @@ -392,6 +407,6 @@ void TunnelManager::setHttpProxy(const char *host,int port, const char *username if (mTunnelClient) mTunnelClient->setHttpProxy(host, port, username, passwd); } -LinphoneCore *TunnelManager::getLinphoneCore(){ +LinphoneCore *TunnelManager::getLinphoneCore() const{ return mCore; } diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh index 9ca29ad86..58475aab3 100644 --- a/coreapi/TunnelManager.hh +++ b/coreapi/TunnelManager.hh @@ -1,7 +1,7 @@ /* * C Implementation: tunnel * - * Description: + * Description: * * * @@ -12,35 +12,35 @@ #define __TUNNEL_CLIENT_MANAGER_H__ #include #include -#include "tunnel/client.hh" +#include +#include #include "linphonecore.h" +#include "linphone_tunnel.h" #ifndef USE_BELLESIP extern "C" { - #include "eXosip2/eXosip_transport_hook.h" + #include } #endif namespace belledonnecomm { -class TunnelClient; -class UdpMirrorClient; /** - * @addtogroup tunnel_client + * @addtogroup tunnel_client * @{ **/ /** - * The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to + * The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to * - provision tunnel servers ip addresses and ports * - start/stop the tunneling service - * - be informed of of connection and disconnection events to the tunnel server + * - be informed of connection and disconnection events to the tunnel server * - perform auto-detection whether tunneling is required, based on a test of sending/receiving a flow of UDP packets. - * + * * It takes in charge automatically the SIP registration procedure when connecting or disconnecting to a tunnel server. * No other action on LinphoneCore is required to enable full operation in tunnel mode. **/ - class TunnelManager : public TunnelClientController{ - + class TunnelManager { + public: /** * Add a tunnel server. At least one should be provided to be able to connect. @@ -61,20 +61,8 @@ class UdpMirrorClient; void addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay); /** * Removes all tunnel server address previously entered with addServer() - **/ - void cleanServers(); - /** - * Register a state callback to be notified whenever the tunnel client is connected or disconnected to the tunnel server. - * @param cb application callback function to use for notifying of connection/disconnection events. - * @param userdata An opaque pointer passed to the callback, used optionally by the application to retrieve a context. - **/ - void setCallback(StateCallback cb, void *userdata); - /** - * Start connecting to a tunnel server. - * At this step, nothing is tunneled yet. The enable() method must be used to state whether SIP and RTP traffic - * need to be tunneled or not. **/ - void start(); + void cleanServers(); /** * Forces reconnection to the tunnel server. * This method is useful when the device switches from wifi to Edge/3G or vice versa. In most cases the tunnel client socket @@ -83,22 +71,15 @@ class UdpMirrorClient; **/ void reconnect(); /** - * Sets whether tunneling of SIP and RTP is required. - * @param isEnabled If true enter in tunneled mode, if false exits from tunneled mode. - * The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode. - * - **/ - void enable(bool isEnabled); - /** - * In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port. - *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on. - *
Call this method each time to run the auto detection algorithm + * @brief setMode + * @param mode */ - void autoDetect(); + void setMode(LinphoneTunnelMode mode); /** - * Returns a boolean indicating whether tunneled operation is enabled. - **/ - bool isEnabled(); + * @brief Return the tunnel mode + * @return #LinphoneTunnelMode + */ + LinphoneTunnelMode getMode() const; /** * Enables debug logs of the Tunnel subsystem. **/ @@ -115,25 +96,60 @@ class UdpMirrorClient; * @param passwd The password. **/ void setHttpProxyAuthInfo(const char* username,const char* passwd); - ~TunnelManager(); + void setHttpProxy(const char *host,int port, const char *username, const char *passwd); + /** + * Indicate to the tunnel manager whether SIP packets must pass + * through the tunnel. That featurte is automatically enabled at + * the creation of the TunnelManager instance. + * @param enable If set to TRUE, SIP packets will pass through the tunnel. + * If set to FALSE, SIP packets will pass by the configured proxies. + */ + void tunnelizeSipPackets(bool enable); + /** + * @brief Check whether the tunnel manager is set to tunnelize SIP packets + * @return True, SIP packets pass through the tunnel + */ + bool tunnelizeSipPacketsEnabled() const; + /** + * @brief Constructor + * @param lc The LinphoneCore instance of which the TunnelManager will be associated to. + */ TunnelManager(LinphoneCore* lc); /** - * Destroy the given RtpTransport. + * @brief Destructor */ - void closeRtpTransport(RtpTransport *t, TunnelSocket *s); - + ~TunnelManager(); /** - * Create an RtpTransport. + * @brief Create an RtpTransport + * @param port + * @return */ RtpTransport *createRtpTransport(int port); - /** - * Get associated Linphone Core. + * @brief Destroy the given RtpTransport + * @param t + * @param s */ - LinphoneCore *getLinphoneCore(); - virtual void setHttpProxy(const char *host,int port, const char *username, const char *passwd); - virtual bool isReady() const; + void closeRtpTransport(RtpTransport *t, TunnelSocket *s); + /** + * @brief Get associated Linphone Core + * @return pointer on the associated LinphoneCore + */ + LinphoneCore *getLinphoneCore() const; + /** + * @brief Check wehter the tunnel is connected + * @return True whether the tunnel is connected + */ + bool isConnected() const; + private: + enum State { + disabled, + connecting, + ready, + autodetecting + }; + enum EventType{ UdpMirrorClientEvent, TunnelEvent, @@ -146,8 +162,6 @@ class UdpMirrorClient; }mData; }; typedef std::list UdpMirrorClientList; - virtual bool isStarted(); - void onIterate(); static int customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen); static int customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen); static int eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata); @@ -156,35 +170,39 @@ class UdpMirrorClient; static void tunnelCallback(bool connected, TunnelManager *zis); static void sOnIterate(TunnelManager *zis); static void sUdpMirrorClientCallback(bool result, void* data); - void waitUnRegistration(); + static void networkReachableCb(LinphoneCore *lc, bool_t reachable); + + private: + void onIterate(); + void doRegistration(); + void doUnregistration(); + void startClient(); + bool startAutoDetection(); void processTunnelEvent(const Event &ev); void processUdpMirrorEvent(const Event &ev); void postEvent(const Event &ev); + + private: LinphoneCore* mCore; - LCSipTransports mRegularTransport; -#ifndef USE_BELLESIP - TunnelSocket *mSipSocket; - eXosip_transport_hooks_t mExosipTransport; -#endif - StateCallback mCallback; - void * mCallbackData; - bool mEnabled; - std::queue mEvq; - std::list mServerAddrs; - UdpMirrorClientList mUdpMirrorClients; - UdpMirrorClientList::iterator mCurrentUdpMirrorClient; + LinphoneTunnelMode mMode; + State mState; + bool mTunnelizeSipPackets; TunnelClient* mTunnelClient; - void stopClient(); - Mutex mMutex; - static Mutex sMutex; - bool mAutoDetectStarted; - bool mReady; - LinphoneRtpTransportFactories mTransportFactories; std::string mHttpUserName; std::string mHttpPasswd; std::string mHttpProxyHost; int mHttpProxyPort; - LinphoneFirewallPolicy mPreviousFirewallPolicy; + LinphoneCoreVTable *mVTable; + std::list mServerAddrs; + UdpMirrorClientList mUdpMirrorClients; + UdpMirrorClientList::iterator mCurrentUdpMirrorClient; + LinphoneRtpTransportFactories mTransportFactories; + Mutex mMutex; + std::queue mEvq; +#ifndef USE_BELLESIP + TunnelSocket *mSipSocket; + eXosip_transport_hooks_t mExosipTransport; +#endif }; /** diff --git a/coreapi/authentication.c b/coreapi/authentication.c index 59b3ea1b5..de7248316 100644 --- a/coreapi/authentication.c +++ b/coreapi/authentication.c @@ -378,6 +378,8 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in /** * Returns an unmodifiable list of currently entered LinphoneAuthInfo. + * @param[in] lc The LinphoneCore object + * @return \mslist{LinphoneAuthInfo} **/ const MSList *linphone_core_get_auth_info_list(const LinphoneCore *lc){ return lc->auth_info; diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index ab7714fa9..6c2e84483 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -98,12 +98,16 @@ void sal_disable_logs() { void sal_add_pending_auth(Sal *sal, SalOp *op){ if (ms_list_find(sal->pending_auths,op)==NULL){ sal->pending_auths=ms_list_append(sal->pending_auths,op); + op->has_auth_pending=TRUE; } } void sal_remove_pending_auth(Sal *sal, SalOp *op){ - if (ms_list_find(sal->pending_auths,op)){ - sal->pending_auths=ms_list_remove(sal->pending_auths,op); + if (op->has_auth_pending){ + op->has_auth_pending=FALSE; + if (ms_list_find(sal->pending_auths,op)){ + sal->pending_auths=ms_list_remove(sal->pending_auths,op); + } } } @@ -432,8 +436,8 @@ Sal * sal_init(){ sal->stack = belle_sip_stack_new(NULL); sal->user_agent=belle_sip_header_user_agent_new(); -#if defined(PACKAGE_NAME) && defined(LINPHONE_VERSION) - belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LINPHONE_VERSION); +#if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION) + belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION); #endif sal_append_stack_string_to_user_agent(sal); belle_sip_object_ref(sal->user_agent); @@ -530,6 +534,8 @@ void sal_uninit(Sal* sal){ belle_sip_object_unref(sal->prov); belle_sip_object_unref(sal->stack); belle_sip_object_unref(sal->listener); + if (sal->supported) belle_sip_object_unref(sal->supported); + ms_list_free_with_data(sal->supported_tags,ms_free); if (sal->uuid) ms_free(sal->uuid); if (sal->root_ca) ms_free(sal->root_ca); ms_free(sal); @@ -555,7 +561,7 @@ int sal_add_listen_port(Sal *ctx, SalAddress* addr){ sal_address_get_port(addr), sal_transport_to_string(sal_address_get_transport(addr))); if (sal_address_get_port(addr)==-1 && lp==NULL){ - int random_port=(0xDFFF&random())+1024; + int random_port=(0xDFFF&ortp_random())+1024; ms_warning("This version of belle-sip doesn't support random port, choosing one here."); lp = belle_sip_stack_create_listening_point(ctx->stack, sal_address_get_domain(addr), @@ -639,28 +645,42 @@ void sal_set_keepalive_period(Sal *ctx,unsigned int value){ belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive); } } - return ; } int sal_enable_tunnel(Sal *ctx, void *tunnelclient) { #ifdef TUNNEL_ENABLED - belle_sip_listening_point_t *lp; - int result; - - sal_unlisten_ports(ctx); - lp = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient); - if (lp == NULL) return -1; - - belle_sip_listening_point_set_keep_alive(lp, ctx->keep_alive); - result = belle_sip_provider_add_listening_point(ctx->prov, lp); - set_tls_properties(ctx); - return result; + belle_sip_listening_point_t *lp_udp = NULL; + if(ctx->lp_tunnel != NULL) { + ortp_error("sal_enable_tunnel(): tunnel is already enabled"); + return -1; + } + while((lp_udp = belle_sip_provider_get_listening_point(ctx->prov, "udp")) != NULL) { + belle_sip_object_ref(lp_udp); + belle_sip_provider_remove_listening_point(ctx->prov, lp_udp); + ctx->udp_listening_points = ms_list_append(ctx->udp_listening_points, lp_udp); + } + ctx->lp_tunnel = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient); + if(ctx->lp_tunnel == NULL) return -1; + belle_sip_listening_point_set_keep_alive(ctx->lp_tunnel, ctx->keep_alive); + belle_sip_provider_add_listening_point(ctx->prov, ctx->lp_tunnel); + belle_sip_object_ref(ctx->lp_tunnel); + return 0; #else return 0; #endif } void sal_disable_tunnel(Sal *ctx) { #ifdef TUNNEL_ENABLED - sal_unlisten_ports(ctx); + MSList *it; + if(ctx->lp_tunnel) { + belle_sip_provider_remove_listening_point(ctx->prov, ctx->lp_tunnel); + belle_sip_object_unref(ctx->lp_tunnel); + ctx->lp_tunnel = NULL; + for(it=ctx->udp_listening_points; it!=NULL; it=it->next) { + belle_sip_provider_add_listening_point(ctx->prov, (belle_sip_listening_point_t *)it->data); + } + ms_list_free_with_data(ctx->udp_listening_points, belle_sip_object_unref); + ctx->udp_listening_points = NULL; + } #endif } /** @@ -928,10 +948,79 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){ return 0; } +static void make_supported_header(Sal *sal){ + MSList *it; + char *alltags=NULL; + size_t buflen=64; + size_t written=0; + + if (sal->supported){ + belle_sip_object_unref(sal->supported); + sal->supported=NULL; + } + for(it=sal->supported_tags;it!=NULL;it=it->next){ + const char *tag=(const char*)it->data; + size_t taglen=strlen(tag); + if (alltags==NULL || (written+taglen+1>=buflen)) alltags=ms_realloc(alltags,(buflen=buflen*2)); + snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag); + } + if (alltags){ + sal->supported=belle_sip_header_create("Supported",alltags); + if (sal->supported){ + belle_sip_object_ref(sal->supported); + } + ms_free(alltags); + } +} + +void sal_set_supported_tags(Sal *ctx, const char* tags){ + ctx->supported_tags=ms_list_free_with_data(ctx->supported_tags,ms_free); + if (tags){ + char *iter; + char *buffer=ms_strdup(tags); + char *tag; + char *context=NULL; + iter=buffer; + while((tag=strtok_r(iter,", ",&context))!=NULL){ + iter=NULL; + ctx->supported_tags=ms_list_append(ctx->supported_tags,ms_strdup(tag)); + } + ms_free(buffer); + } + make_supported_header(ctx); +} + +const char *sal_get_supported_tags(Sal *ctx){ + if (ctx->supported){ + return belle_sip_header_get_unparsed_value(ctx->supported); + } + return NULL; +} + +void sal_add_supported_tag(Sal *ctx, const char* tag){ + MSList *elem=ms_list_find_custom(ctx->supported_tags,(MSCompareFunc)strcasecmp,tag); + if (!elem){ + ctx->supported_tags=ms_list_append(ctx->supported_tags,ms_strdup(tag)); + make_supported_header(ctx); + } + +} + +void sal_remove_supported_tag(Sal *ctx, const char* tag){ + MSList *elem=ms_list_find_custom(ctx->supported_tags,(MSCompareFunc)strcasecmp,tag); + if (elem){ + ms_free(elem->data); + ctx->supported_tags=ms_list_remove_link(ctx->supported_tags,elem); + make_supported_header(ctx); + } +} + + + belle_sip_response_t* sal_create_response_from_request ( Sal* sal, belle_sip_request_t* req, int code ) { belle_sip_response_t *resp=belle_sip_response_create_from_request(req,code); belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(sal->user_agent)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal_make_supported_header(sal)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal->supported); return resp; } diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index a20150de2..07124feb3 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -33,12 +33,16 @@ struct Sal{ belle_sip_provider_t *prov; belle_sip_header_user_agent_t* user_agent; belle_sip_listener_t *listener; + belle_sip_listening_point_t *lp_tunnel; + MSList *udp_listening_points; void *up; /*user pointer*/ int session_expires; unsigned int keep_alive; char *root_ca; char *uuid; int refresher_retry_after; /*retry after value for refresher*/ + MSList *supported_tags;/*list of char * */ + belle_sip_header_t *supported; bool_t one_matching_codec; bool_t use_tcp_tls_keep_alive; bool_t nat_helper_enabled; @@ -102,6 +106,7 @@ struct SalOp{ bool_t sdp_offering; bool_t call_released; bool_t manual_refresher; + bool_t has_auth_pending; int auth_requests; /*number of auth requested for this op*/ }; @@ -164,8 +169,6 @@ bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody); SalReason sal_reason_to_sip_code(SalReason r); -belle_sip_header_t * sal_make_supported_header(Sal *sal); - void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg); #endif /* SAL_IMPL_H_ */ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 26bbdb038..fbed2cf18 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -75,22 +75,33 @@ static void sdp_process(SalOp *h){ static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) { belle_sip_header_content_type_t* content_type ; belle_sip_header_content_length_t* content_length; - belle_sip_error_code error = BELLE_SIP_OK; + belle_sip_error_code error = BELLE_SIP_BUFFER_OVERFLOW; size_t length = 0; - char buff[2048]; if (session_desc) { + size_t bufLen = 2048; + size_t hardlimit = 16*1024; /* 16k SDP limit seems reasonable */ + char* buff = belle_sip_malloc(bufLen); content_type = belle_sip_header_content_type_create("application","sdp"); - error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,sizeof(buff),&length); - if (error != BELLE_SIP_OK) { - ms_error("Buffer too small or sdp too big"); + + /* try to marshal the description. This could go higher than 2k so we iterate */ + while( error != BELLE_SIP_OK && bufLen <= hardlimit && buff != NULL){ + error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,bufLen,&length); + if( error != BELLE_SIP_OK ){ + bufLen *= 2; + buff = belle_sip_realloc(buff,bufLen); + } + } + /* give up if hard limit reached */ + if (error != BELLE_SIP_OK || buff == NULL) { + ms_error("Buffer too small (%d) or not enough memory, giving up SDP", (int)bufLen); return -1; } - content_length= belle_sip_header_content_length_create(length); + content_length = belle_sip_header_content_length_create(length); belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_type)); belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_length)); - belle_sip_message_set_body(msg,buff,length); + belle_sip_message_assign_body(msg,buff,length); return 0; } else { return -1; @@ -185,6 +196,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ int code = belle_sip_response_get_status_code(response); belle_sip_header_content_type_t *header_content_type=NULL; belle_sip_dialog_t *dialog=belle_sip_response_event_get_dialog(event); + const char *method; if (!client_transaction) { ms_warning("Discarding stateless response [%i] on op [%p]",code,op); @@ -193,13 +205,13 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); set_or_update_dialog(op,dialog); dialog_state=dialog ? belle_sip_dialog_get_state(dialog) : BELLE_SIP_DIALOG_NULL; - + method=belle_sip_request_get_method(req); ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,dialog,belle_sip_dialog_state_to_string(dialog_state)); switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: case BELLE_SIP_DIALOG_EARLY: { - if (strcmp("INVITE",belle_sip_request_get_method(req))==0 ) { + if (strcmp("INVITE",method)==0 ) { if (op->state == SalOpStateTerminating) { /*check if CANCEL was sent before*/ if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_client_trans))))!=0) { @@ -238,28 +250,28 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ case BELLE_SIP_DIALOG_CONFIRMED: { switch (op->state) { case SalOpStateEarly:/*invite case*/ - case SalOpStateActive: /*re-invite case*/ - if (code >=200 - && code<300 - && strcmp("INVITE",belle_sip_request_get_method(req))==0) { - handle_sdp_from_response(op,response); - ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); - if (ack==NULL) { - ms_error("This call has been already terminated."); - return ; + case SalOpStateActive: /*re-invite, INFO, UPDATE case*/ + if (strcmp("INVITE",method)==0){ + if (code >=200 && code<300) { + handle_sdp_from_response(op,response); + ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); + if (ack==NULL) { + ms_error("This call has been already terminated."); + return ; + } + if (op->sdp_answer){ + set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer); + belle_sip_object_unref(op->sdp_answer); + op->sdp_answer=NULL; + } + belle_sip_dialog_send_ack(op->dialog,ack); + op->base.root->callbacks.call_accepted(op); /*INVITE*/ + op->state=SalOpStateActive; + }else if (code >= 300){ + call_set_error(op,response); } - if (op->sdp_answer){ - set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer); - belle_sip_object_unref(op->sdp_answer); - op->sdp_answer=NULL; - } - belle_sip_dialog_send_ack(op->dialog,ack); - op->base.root->callbacks.call_accepted(op); /*INVITE*/ - op->state=SalOpStateActive; - } else if (code >= 300 && strcmp("INVITE",belle_sip_request_get_method(req))==0){ - call_set_error(op,response); - } else if (code == 491 - && strcmp("INFO",belle_sip_request_get_method(req)) == 0 + }else if (strcmp("INFO",method)==0){ + if (code == 491 && (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t)) && strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0 && strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) { @@ -267,8 +279,11 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry"); ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in); belle_sip_object_unref(s); - }else { - /*ignoring*/ + }else { + /*ignoring*/ + } + }else if (strcmp("UPDATE",method)==0){ + op->base.root->callbacks.call_accepted(op); /*INVITE*/ } break; case SalOpStateTerminating: @@ -314,6 +329,8 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_ belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event); belle_sip_request_t* req; belle_sip_response_t* resp; + bool_t release_call=FALSE; + if (client_transaction) { req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction)); @@ -324,9 +341,21 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_ if (op->state ==SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(req))==0 && (!resp || (belle_sip_response_get_status_code(resp) !=401 - && belle_sip_response_get_status_code(resp) !=407))) { - if (op->dialog==NULL) call_set_released(op); + && belle_sip_response_get_status_code(resp) !=407)) + && op->dialog==NULL) { + release_call=TRUE; + } + if (server_transaction){ + if (op->pending_server_trans==server_transaction){ + belle_sip_object_unref(op->pending_server_trans); + op->pending_server_trans=NULL; + } + if (op->pending_update_server_trans==server_transaction){ + belle_sip_object_unref(op->pending_update_server_trans); + op->pending_update_server_trans=NULL; + } } + if (release_call) call_set_released(op); } static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, belle_sip_request_t* request,int status_code) { @@ -419,6 +448,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t belle_sip_response_t* resp; belle_sip_header_t* call_info; const char *method=belle_sip_request_get_method(req); + bool_t is_update=FALSE; if (strcmp("ACK",method)!=0){ /*ACK does'nt create srv transaction*/ server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); @@ -490,7 +520,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } else if (strcmp("UPDATE",method)==0) { sal_op_reset_descriptions(op); if (process_sdp_for_invite(op,req)==0) - op->base.root->callbacks.call_updating(op); + op->base.root->callbacks.call_updating(op,TRUE); } else { belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req)); unsupported_method(server_transaction,req); @@ -522,11 +552,20 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); op->state=SalOpStateTerminating; /*call end not notified by dialog deletion because transaction can end before dialog*/ - } else if(strcmp("INVITE",method)==0) { - /*re-invite*/ - sal_op_reset_descriptions(op); - if (process_sdp_for_invite(op,req)==0) - op->base.root->callbacks.call_updating(op); + } else if(strcmp("INVITE",method)==0 || (is_update=(strcmp("UPDATE",method)==0)) ) { + if (is_update && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) { + /*session timer case*/ + /*session expire should be handled. to be done when real session timer (rfc4028) will be implemented*/ + resp=sal_op_create_response_from_request(op,req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + belle_sip_object_unref(op->pending_update_server_trans); + op->pending_update_server_trans=NULL; + } else { + /*re-invite*/ + sal_op_reset_descriptions(op); + if (process_sdp_for_invite(op,req)==0) + op->base.root->callbacks.call_updating(op,is_update); + } } else if (strcmp("INFO",method)==0){ if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)) && strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) { @@ -564,22 +603,6 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481)); } else if (strcmp("MESSAGE",method)==0){ sal_process_incoming_message(op,event); - } else if (strcmp("UPDATE",method)==0) { - - /*FIXME jehan: It might be better to silently accept UPDATE which do not modify either the number or the nature of streams*/ - - /*rfc 3311 - * 5.2 Receiving an UPDATE - * ... - * If the UAS cannot change the session parameters without prompting the user, it SHOULD reject - * the request with a 504 response. - */ - resp=sal_op_create_response_from_request(op,req,504); - belle_sip_response_set_reason_phrase(resp,"Cannot change the session parameters without prompting the user"); - /*belle_sip_message_add_header( BELLE_SIP_MESSAGE(resp) - ,belle_sip_header_create( "Warning", "Cannot change the session parameters without prompting the user"));*/ - belle_sip_server_transaction_send_response(server_transaction,resp); - return; }else{ ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); unsupported_method(server_transaction,req); @@ -627,7 +650,7 @@ static void sal_op_fill_invite(SalOp *op, belle_sip_request_t* invite) { belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(create_allow(op->base.root->enable_sip_update))); if (op->base.root->session_expires!=0){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "200")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "600;refresher=uas")); belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer")); } if (op->base.local_media){ @@ -754,9 +777,10 @@ int sal_call_accept(SalOp*h){ } belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(create_allow(h->base.root->enable_sip_update))); if (h->base.root->session_expires!=0){ - if (h->supports_session_timers) { +/* if (h->supports_session_timers) {*/ belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create("Supported", "timer")); - } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Session-expires", "600;refresher=uac")); + /*}*/ } if ((contact_header=sal_op_create_contact(h))) { @@ -779,6 +803,7 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti belle_sip_response_t* response; belle_sip_header_contact_t* contact=NULL; int status=sal_reason_to_sip_code(reason); + belle_sip_transaction_t *trans; if (reason==SalReasonRedirect){ if (redirection!=NULL) { @@ -790,19 +815,27 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti ms_error("Cannot redirect to null"); } } - response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status); + trans=(belle_sip_transaction_t*)op->pending_server_trans; + if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans; + if (!trans){ + ms_error("sal_call_decline(): no pending transaction to decline."); + return -1; + } + response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status); if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); - belle_sip_server_transaction_send_response(op->pending_server_trans,response); + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); return 0; } -int sal_call_update(SalOp *op, const char *subject){ - +int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){ belle_sip_request_t *update; belle_sip_dialog_state_t state=belle_sip_dialog_get_state(op->dialog); /*check for dialog state*/ if ( state == BELLE_SIP_DIALOG_CONFIRMED) { - update=belle_sip_dialog_create_request(op->dialog,"INVITE"); + if (no_user_consent) + update=belle_sip_dialog_create_request(op->dialog,"UPDATE"); + else + update=belle_sip_dialog_create_request(op->dialog,"INVITE"); } else if (state == BELLE_SIP_DIALOG_EARLY) { update=belle_sip_dialog_create_request(op->dialog,"UPDATE"); } else { diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index e548cec43..ed18f52d0 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -118,9 +118,7 @@ belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){ return contact_header; } -belle_sip_header_t * sal_make_supported_header(Sal *sal){ - return belle_sip_header_create("Supported","replaces, outbound"); -} + static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){ const MSList *elem; @@ -201,7 +199,7 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyUser)); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(privacy_header)); } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),sal_make_supported_header(op->base.root)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->base.root->supported); return req; } diff --git a/coreapi/call_log.c b/coreapi/call_log.c new file mode 100644 index 000000000..7ce488096 --- /dev/null +++ b/coreapi/call_log.c @@ -0,0 +1,300 @@ +/* +linphone +Copyright (C) 2010-2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#define _XOPEN_SOURCE 700 /*required for strptime of GNU libc*/ + +#include +#include "private.h" + + +/******************************************************************************* + * Internal functions * + ******************************************************************************/ + +/*prevent a gcc bug with %c*/ +static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){ + return strftime(s, max, fmt, tm); +} + +static time_t string_to_time(const char *date){ +#ifndef WIN32 + struct tm tmtime={0}; + strptime(date,"%c",&tmtime); + return mktime(&tmtime); +#else + return 0; +#endif +} + +static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){ + struct tm loctime; +#ifdef WIN32 +#if !defined(_WIN32_WCE) + loctime=*localtime(&start_time); + /*FIXME*/ +#endif /*_WIN32_WCE*/ +#else + localtime_r(&start_time,&loctime); +#endif + my_strftime(cl->start_date,sizeof(cl->start_date),"%c",&loctime); +} + +/******************************************************************************* + * Private functions * + ******************************************************************************/ + +void call_logs_write_to_config_file(LinphoneCore *lc){ + MSList *elem; + char logsection[32]; + int i; + char *tmp; + LpConfig *cfg=lc->config; + + if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return; + + for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){ + LinphoneCallLog *cl=(LinphoneCallLog*)elem->data; + snprintf(logsection,sizeof(logsection),"call_log_%i",i); + lp_config_clean_section(cfg,logsection); + lp_config_set_int(cfg,logsection,"dir",cl->dir); + lp_config_set_int(cfg,logsection,"status",cl->status); + tmp=linphone_address_as_string(cl->from); + lp_config_set_string(cfg,logsection,"from",tmp); + ms_free(tmp); + tmp=linphone_address_as_string(cl->to); + lp_config_set_string(cfg,logsection,"to",tmp); + ms_free(tmp); + if (cl->start_date_time) + lp_config_set_int64(cfg,logsection,"start_date_time",(int64_t)cl->start_date_time); + else lp_config_set_string(cfg,logsection,"start_date",cl->start_date); + lp_config_set_int(cfg,logsection,"duration",cl->duration); + if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey); + lp_config_set_float(cfg,logsection,"quality",cl->quality); + lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled); + lp_config_set_string(cfg,logsection,"call_id",cl->call_id); + } + for(;imax_call_logs;++i){ + snprintf(logsection,sizeof(logsection),"call_log_%i",i); + lp_config_clean_section(cfg,logsection); + } +} + +void call_logs_read_from_config_file(LinphoneCore *lc){ + char logsection[32]; + int i; + const char *tmp; + uint64_t sec; + LpConfig *cfg=lc->config; + for(i=0;;++i){ + snprintf(logsection,sizeof(logsection),"call_log_%i",i); + if (lp_config_has_section(cfg,logsection)){ + LinphoneCallLog *cl; + LinphoneAddress *from=NULL,*to=NULL; + tmp=lp_config_get_string(cfg,logsection,"from",NULL); + if (tmp) from=linphone_address_new(tmp); + tmp=lp_config_get_string(cfg,logsection,"to",NULL); + if (tmp) to=linphone_address_new(tmp); + if (!from || !to) + continue; + cl=linphone_call_log_new(lp_config_get_int(cfg,logsection,"dir",0),from,to); + cl->status=lp_config_get_int(cfg,logsection,"status",0); + sec=lp_config_get_int64(cfg,logsection,"start_date_time",0); + if (sec) { + /*new call log format with date expressed in seconds */ + cl->start_date_time=(time_t)sec; + set_call_log_date(cl,cl->start_date_time); + }else{ + tmp=lp_config_get_string(cfg,logsection,"start_date",NULL); + if (tmp) { + strncpy(cl->start_date,tmp,sizeof(cl->start_date)); + cl->start_date_time=string_to_time(cl->start_date); + } + } + cl->duration=lp_config_get_int(cfg,logsection,"duration",0); + tmp=lp_config_get_string(cfg,logsection,"refkey",NULL); + if (tmp) cl->refkey=ms_strdup(tmp); + cl->quality=lp_config_get_float(cfg,logsection,"quality",-1); + cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0); + tmp=lp_config_get_string(cfg,logsection,"call_id",NULL); + if (tmp) cl->call_id=ms_strdup(tmp); + lc->call_logs=ms_list_append(lc->call_logs,cl); + }else break; + } +} + + +/******************************************************************************* + * Public functions * + ******************************************************************************/ + +const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){ + return cl->call_id; +} + +LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){ + return cl->dir; +} + +int linphone_call_log_get_duration(LinphoneCallLog *cl){ + return cl->duration; +} + +LinphoneAddress *linphone_call_log_get_from_address(LinphoneCallLog *cl){ + return cl->from; +} + +const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){ + return &cl->local_stats; +} + +float linphone_call_log_get_quality(LinphoneCallLog *cl){ + return cl->quality; +} + +const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){ + return cl->refkey; +} + +LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){ + return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to; +} + +const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){ + return &cl->remote_stats; +} + +time_t linphone_call_log_get_start_date(LinphoneCallLog *cl){ + return cl->start_date_time; +} + +LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){ + return cl->status; +} + +LinphoneAddress *linphone_call_log_get_to_address(LinphoneCallLog *cl){ + return cl->to; +} + +void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){ + if (cl->refkey!=NULL){ + ms_free(cl->refkey); + cl->refkey=NULL; + } + if (refkey) cl->refkey=ms_strdup(refkey); +} + +char * linphone_call_log_to_str(LinphoneCallLog *cl){ + char *status; + char *tmp; + char *from=linphone_address_as_string (cl->from); + char *to=linphone_address_as_string (cl->to); + switch(cl->status){ + case LinphoneCallAborted: + status=_("aborted"); + break; + case LinphoneCallSuccess: + status=_("completed"); + break; + case LinphoneCallMissed: + status=_("missed"); + break; + default: + status="unknown"; + } + tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"), + (cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"), + cl->start_date, + from, + to, + status, + cl->duration/60, + cl->duration%60); + ms_free(from); + ms_free(to); + return tmp; +} + +bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) { + return cl->video_enabled; +} + + +/******************************************************************************* + * Reference and user data handling functions * + ******************************************************************************/ + +void *linphone_call_log_get_user_data(const LinphoneCallLog *cl) { + return cl->user_data; +} + +void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *ud) { + cl->user_data = ud; +} + +LinphoneCallLog * linphone_call_log_ref(LinphoneCallLog *cl) { + belle_sip_object_ref(cl); + return cl; +} + +void linphone_call_log_unref(LinphoneCallLog *cl) { + belle_sip_object_unref(cl); +} + +/******************************************************************************* + * Constructor and destructor functions * + ******************************************************************************/ + +static void _linphone_call_log_destroy(LinphoneCallLog *cl){ + if (cl->from!=NULL) linphone_address_destroy(cl->from); + if (cl->to!=NULL) linphone_address_destroy(cl->to); + if (cl->refkey!=NULL) ms_free(cl->refkey); + if (cl->call_id) ms_free(cl->call_id); + if (cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]); + if (cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]); +} + +LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to){ + LinphoneCallLog *cl=belle_sip_object_new(LinphoneCallLog); + cl->dir=dir; + cl->start_date_time=time(NULL); + set_call_log_date(cl,cl->start_date_time); + cl->from=from; + cl->to=to; + cl->status=LinphoneCallAborted; /*default status*/ + cl->quality=-1; + + cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new(); + cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new(); + cl->connected_date_time=0; + return cl; +} + +/* DEPRECATED */ +void linphone_call_log_destroy(LinphoneCallLog *cl) { + belle_sip_object_unref(cl); +} + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallLog); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallLog, belle_sip_object_t, + (belle_sip_object_destroy_t)_linphone_call_log_destroy, + NULL, // clone + NULL, // marshal + FALSE +); diff --git a/coreapi/call_log.h b/coreapi/call_log.h new file mode 100644 index 000000000..6a3ec8dab --- /dev/null +++ b/coreapi/call_log.h @@ -0,0 +1,244 @@ +/* +linphone +Copyright (C) 2010-2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#ifndef __LINPHONE_CALL_LOG_H__ +#define __LINPHONE_CALL_LOG_H__ + +/** + * @addtogroup call_logs + * @{ +**/ + + +/******************************************************************************* + * Structures and enums * + ******************************************************************************/ + +/** + * Enum representing the direction of a call. +**/ +enum _LinphoneCallDir { + LinphoneCallOutgoing, /**< outgoing calls*/ + LinphoneCallIncoming /**< incoming calls*/ +}; + +/** + * Typedef for enum +**/ +typedef enum _LinphoneCallDir LinphoneCallDir; + +/** + * Enum representing the status of a call +**/ +typedef enum _LinphoneCallStatus { + LinphoneCallSuccess, /**< The call was sucessful */ + LinphoneCallAborted, /**< The call was aborted */ + LinphoneCallMissed, /**< The call was missed (unanswered) */ + LinphoneCallDeclined /**< The call was declined, either locally or by remote end */ +} LinphoneCallStatus; + +/** + * Structure representing a call log. +**/ +typedef struct _LinphoneCallLog LinphoneCallLog; + + +/******************************************************************************* + * Public functions * + ******************************************************************************/ + +/** + * Get the call ID used by the call. + * @param[in] cl LinphoneCallLog object + * @return The call ID used by the call as a string. +**/ +LINPHONE_PUBLIC const char * linphone_call_log_get_call_id(const LinphoneCallLog *cl); + +/** + * Get the direction of the call. + * @param[in] cl LinphoneCallLog object + * @return The direction of the call. +**/ +LINPHONE_PUBLIC LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl); + +/** + * Get the duration of the call since connected. + * @param[in] cl LinphoneCallLog object + * @return The duration of the call in seconds. +**/ +LINPHONE_PUBLIC int linphone_call_log_get_duration(LinphoneCallLog *cl); + +/** + * Get the origin address (ie from) of the call. + * @param[in] cl LinphoneCallLog object + * @return The origin address (ie from) of the call. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_from_address(LinphoneCallLog *cl); + +/** + * Get the RTP statistics computed locally regarding the call. + * @param[in] cl LinphoneCallLog object + * @return The RTP statistics that have been computed locally for the call. +**/ +LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_local_stats(const LinphoneCallLog *cl); + +/** + * Get the overall quality indication of the call. + * @param[in] cl LinphoneCallLog object + * @return The overall quality indication of the call. +**/ +LINPHONE_PUBLIC float linphone_call_log_get_quality(LinphoneCallLog *cl); + +/** + * Get the persistent reference key associated to the call log. + * + * The reference key can be for example an id to an external database. + * It is stored in the config file, thus can survive to process exits/restarts. + * + * @param[in] cl LinphoneCallLog object + * @return The reference key string that has been associated to the call log, or NULL if none has been associated. +**/ +LINPHONE_PUBLIC const char * linphone_call_log_get_ref_key(const LinphoneCallLog *cl); + +/** + * Get the remote address (that is from or to depending on call direction). + * @param[in] cl LinphoneCallLog object + * @return The remote address of the call. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_remote_address(LinphoneCallLog *cl); + +/** + * Get the RTP statistics computed by the remote end and sent back via RTCP. + * @note Not implemented yet. + * @param[in] cl LinphoneCallLog object + * @return The RTP statistics that have been computed by the remote end for the call. +**/ +LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_remote_stats(const LinphoneCallLog *cl); + +/** + * Get the start date of the call. + * @param[in] cl LinphoneCallLog object + * @return The date of the beginning of the call. +**/ +LINPHONE_PUBLIC time_t linphone_call_log_get_start_date(LinphoneCallLog *cl); + +/** + * Get the status of the call. + * @param[in] cl LinphoneCallLog object + * @return The status of the call. +**/ +LINPHONE_PUBLIC LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl); + +/** + * Get the destination address (ie to) of the call. + * @param[in] cl LinphoneCallLog object + * @return The destination address (ie to) of the call. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_to_address(LinphoneCallLog *cl); + +/** + * Associate a persistent reference key to the call log. + * + * The reference key can be for example an id to an external database. + * It is stored in the config file, thus can survive to process exits/restarts. + * + * @param[in] cl LinphoneCallLog object + * @param[in] refkey The reference key string to associate to the call log. +**/ +LINPHONE_PUBLIC void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey); + +/** + * Tell whether video was enabled at the end of the call or not. + * @param[in] cl LinphoneCallLog object + * @return A boolean value telling whether video was enabled at the end of the call. +**/ +LINPHONE_PUBLIC bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl); + +/** + * Get a human readable string describing the call. + * @note: the returned string must be freed by the application (use ms_free()). + * @param[in] cl LinphoneCallLog object + * @return A human readable string describing the call. +**/ +LINPHONE_PUBLIC char * linphone_call_log_to_str(LinphoneCallLog *cl); + + +/******************************************************************************* + * Reference and user data handling functions * + ******************************************************************************/ + +/** + * Get the user data associated with the call log. + * @param[in] cl LinphoneCallLog object + * @return The user data associated with the call log. +**/ +LINPHONE_PUBLIC void *linphone_call_log_get_user_data(const LinphoneCallLog *cl); + +/** + * Assign a user data to the call log. + * @param[in] cl LinphoneCallLog object + * @param[in] ud The user data to associate with the call log. +**/ +LINPHONE_PUBLIC void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *ud); + +/** + * Acquire a reference to the call log. + * @param[in] cl LinphoneCallLog object + * @return The same LinphoneCallLog object +**/ +LINPHONE_PUBLIC LinphoneCallLog * linphone_call_log_ref(LinphoneCallLog *cl); + +/** + * Release a reference to the call log. + * @param[in] cl LinphoneCallLog object +**/ +LINPHONE_PUBLIC void linphone_call_log_unref(LinphoneCallLog *cl); + + +/******************************************************************************* + * DEPRECATED * + ******************************************************************************/ + +/** @deprecated Use linphone_call_log_get_from_address() instead. */ +#define linphone_call_log_get_from(cl) linphone_call_log_get_from_address(cl) + +/** @deprecated Use linphone_call_log_get_to_address() instead. */ +#define linphone_call_log_get_to(cl) linphone_call_log_get_to_address(cl) + +/** @deprecated Use linphone_call_log_set_user_data() instead. */ +#define linphone_call_log_set_user_pointer(cl, ud) linphone_call_log_set_user_data(cl, ud) + +/** @deprecated Use linphone_call_log_get_user_data() instead. */ +#define linphone_call_log_get_user_pointer(cl) linphone_call_log_get_user_data(cl) + +/** + * Destroy a LinphoneCallLog. + * @param cl LinphoneCallLog object + * @deprecated Use linphone_call_log_unref() instead. + */ +LINPHONE_PUBLIC void linphone_call_log_destroy(LinphoneCallLog *cl); + + +/** + * @} +**/ + + +#endif /* __LINPHONE_CALL_LOG_H__ */ diff --git a/coreapi/call_params.c b/coreapi/call_params.c new file mode 100644 index 000000000..a48066169 --- /dev/null +++ b/coreapi/call_params.c @@ -0,0 +1,207 @@ +/* +linphone +Copyright (C) 2010-2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "private.h" + + +/******************************************************************************* + * Internal functions * + ******************************************************************************/ + +SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) { + if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf; + if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp; + if (params->avpf_enabled) return SalProtoRtpAvpf; + return SalProtoRtpAvp; +} + + +/******************************************************************************* + * Public functions * + ******************************************************************************/ + +void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value){ + params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value); +} + +LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){ + LinphoneCallParams *ncp=linphone_call_params_new(); + memcpy(ncp,cp,sizeof(LinphoneCallParams)); + if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file); + if (cp->session_name) ncp->session_name=ms_strdup(cp->session_name); + /* + * The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient. + */ + if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers); + return ncp; +} + +bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){ + return cp->real_early_media; +} + +void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){ + cp->real_early_media=enabled; +} + +void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){ + cp->low_bandwidth=enabled; +} + +void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){ + cp->has_video=enabled; +} + +const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){ + return sal_custom_header_find(params->custom_headers,header_name); +} + +bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){ + return cp->in_conference; +} + +LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) { + return cp->media_encryption; +} + +LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) { + return params->privacy; +} + +float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp){ + return cp->received_fps; +} + +MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp) { + return cp->recv_vsize; +} + +const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){ + return cp->record_file; +} + +const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp) { + return sal_media_proto_to_string(get_proto_from_call_params(cp)); +} + +float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp){ + return cp->sent_fps; +} + +MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp) { + return cp->sent_vsize; +} + +const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){ + return cp->session_name; +} + +const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) { + return cp->audio_codec; +} + +const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) { + return cp->video_codec; +} + +bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) { + return cp->low_bandwidth; +} + +void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){ + cp->audio_bw=bandwidth; +} + +void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e) { + cp->media_encryption = e; +} + +void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) { + params->privacy=privacy; +} + +void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){ + if (cp->record_file){ + ms_free(cp->record_file); + cp->record_file=NULL; + } + if (path) cp->record_file=ms_strdup(path); +} + +void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){ + if (cp->session_name){ + ms_free(cp->session_name); + cp->session_name=NULL; + } + if (name) cp->session_name=ms_strdup(name); +} + +bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){ + return cp->has_video; +} + + + +/******************************************************************************* + * Reference and user data handling functions * + ******************************************************************************/ + +void *linphone_call_params_get_user_data(const LinphoneCallParams *cp) { + return cp->user_data; +} + +void linphone_call_params_set_user_data(LinphoneCallParams *cp, void *ud) { + cp->user_data = ud; +} + +LinphoneCallParams * linphone_call_params_ref(LinphoneCallParams *cp) { + belle_sip_object_ref(cp); + return cp; +} + +void linphone_call_params_unref(LinphoneCallParams *cp) { + belle_sip_object_unref(cp); +} + +/******************************************************************************* + * Constructor and destructor functions * + ******************************************************************************/ + +static void _linphone_call_params_destroy(LinphoneCallParams *cp){ + if (cp->record_file) ms_free(cp->record_file); + if (cp->custom_headers) sal_custom_header_free(cp->custom_headers); +} + +LinphoneCallParams * linphone_call_params_new(void) { + return belle_sip_object_new(LinphoneCallParams); +} + +/* DEPRECATED */ +void linphone_call_params_destroy(LinphoneCallParams *cp) { + linphone_call_params_unref(cp); +} + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallParams); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallParams, belle_sip_object_t, + (belle_sip_object_destroy_t)_linphone_call_params_destroy, + NULL, // clone + NULL, // marshal + FALSE +); diff --git a/coreapi/call_params.h b/coreapi/call_params.h new file mode 100644 index 000000000..9c942826b --- /dev/null +++ b/coreapi/call_params.h @@ -0,0 +1,303 @@ +/* +linphone +Copyright (C) 2010-2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#ifndef __LINPHONE_CALL_PARAMS_H__ +#define __LINPHONE_CALL_PARAMS_H__ + +/** + * @addtogroup call_control + * @{ +**/ + + +/******************************************************************************* + * Structures and enums * + ******************************************************************************/ + +/** + * Private structure definition for LinphoneCallParams. +**/ +struct _LinphoneCallParams; + +/** + * The LinphoneCallParams is an object containing various call related parameters. + * It can be used to retrieve parameters from a currently running call or modify + * the call's characteristics dynamically. +**/ +typedef struct _LinphoneCallParams LinphoneCallParams; + + +/******************************************************************************* + * Public functions * + ******************************************************************************/ + +/** + * Add a custom SIP header in the INVITE for a call. + * @param[in] cp The #LinphoneCallParams to add a custom SIP header to. + * @param[in] header_name The name of the header to add. + * @param[in] header_value The content of the header to add. +**/ +LINPHONE_PUBLIC void linphone_call_params_add_custom_header(LinphoneCallParams *cp, const char *header_name, const char *header_value); + +/** + * Copy an existing LinphoneCallParams object to a new LinphoneCallParams object. + * @param[in] cp The LinphoneCallParams object to copy. + * @return A copy of the LinphoneCallParams object. +**/ +LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp); + +/** + * Indicate whether sending of early media was enabled. + * @param[in] cp LinphoneCallParams object + * @return A boolean value telling whether sending of early media was enabled. +**/ +LINPHONE_PUBLIC bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp); + +/** + * Enable sending of real early media (during outgoing calls). + * @param[in] cp LinphoneCallParams object + * @param[in] enabled A boolean value telling whether to enable early media sending or not. +**/ +LINPHONE_PUBLIC void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled); + +/** + * Indicate low bandwith mode. + * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage + * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided + * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled. + * @param[in] cp LinphoneCallParams object + * @param[in] enabled A boolean value telling whether to activate the low bandwidth mode or not. +**/ +LINPHONE_PUBLIC void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled); + +/** + * Enable video stream. + * @param[in] cp LinphoneCallParams object + * @param[in] enabled A boolean value telling whether to enable video or not. +**/ +LINPHONE_PUBLIC void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled); + +/** + * Get a custom SIP header. + * @param[in] cp The #LinphoneCallParams to get the custom SIP header from. + * @param[in] header_name The name of the header to get. + * @return The content of the header or NULL if not found. +**/ +LINPHONE_PUBLIC const char *linphone_call_params_get_custom_header(const LinphoneCallParams *cp, const char *header_name); + +/** + * Tell whether the call is part of the locally managed conference. + * @param[in] cp LinphoneCallParams object + * @return A boolean value telling whether the call is part of the locally managed conference. +**/ +LINPHONE_PUBLIC bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp); + +/** + * Get the kind of media encryption selected for the call. + * @param[in] cp LinphoneCallParams object + * @return The kind of media encryption selected for the call. +**/ +LINPHONE_PUBLIC LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp); + +/** + * Get requested level of privacy for the call. + * @param[in] cp LinphoneCallParams object + * @return The privacy mode used for the call. +**/ +LINPHONE_PUBLIC LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *cp); + +/** + * Get the framerate of the video that is received. + * @param[in] cp LinphoneCallParams object + * @return The actual received framerate in frames per seconds, 0 if not available. + */ +LINPHONE_PUBLIC float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp); + +/** + * Get the size of the video that is received. + * @param[in] cp LinphoneCallParams object + * @return The received video size or MS_VIDEO_SIZE_UNKNOWN if not available. + */ +LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp); + +/** + * Get the path for the audio recording of the call. + * @param[in] cp LinphoneCallParams object + * @return The path to the audio recording of the call. +**/ +LINPHONE_PUBLIC const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp); + +/** + * Get the RTP profile being used. + * @param[in] cp #LinphoneCallParams object + * @return The RTP profile. + */ +LINPHONE_PUBLIC const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp); + +/** + * Get the framerate of the video that is sent. + * @param[in] cp LinphoneCallParams object + * @return The actual sent framerate in frames per seconds, 0 if not available. + */ +LINPHONE_PUBLIC float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp); + +/** + * Gets the size of the video that is sent. + * @param[in] cp LinphoneCalParams object + * @return The sent video size or MS_VIDEO_SIZE_UNKNOWN if not available. + */ +LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp); + +/** + * Get the session name of the media session (ie in SDP). + * Subject from the SIP message can be retrieved using linphone_call_params_get_custom_header() and is different. + * @param[in] cp LinphoneCallParams object + * @return The session name of the media session. +**/ +LINPHONE_PUBLIC const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp); + +/** + * Get the audio codec used in the call, described as a LinphonePayloadType object. + * @param[in] cp LinphoneCallParams object + * @return The LinphonePayloadType object corresponding to the audio codec being used in the call. +**/ +LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp); + +/** + * Get the video codec used in the call, described as a LinphonePayloadType structure. + * @param[in] cp LinphoneCallParams object + * @return The LinphonePayloadType object corresponding to the video codec being used in the call. +**/ +LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp); + +/** + * Tell whether the call has been configured in low bandwidth mode or not. + * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file. + * An application that would have reliable way to know network capacity may not use activate_edge_workarounds=1 but instead manually configure + * low bandwidth mode with linphone_call_params_enable_low_bandwidth(). + * When enabled, this param may transform a call request with video in audio only mode. + * @param[in] cp LinphoneCallParams object + * @return A boolean value telling whether the low bandwidth mode has been configured/detected. + */ +LINPHONE_PUBLIC bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp); + +/** + * Refine bandwidth settings for this call by setting a bandwidth limit for audio streams. + * As a consequence, codecs whose bitrates are not compatible with this limit won't be used. + * @param[in] cp LinphoneCallParams object + * @param[in] bw The audio bandwidth limit to set in kbit/s. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bw); + +/** + * Set requested media encryption for a call. + * @param[in] cp LinphoneCallParams object + * @param[in] enc The media encryption to use for the call. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption enc); + +/** + * Set requested level of privacy for the call. + * \xmlonly javascript \endxmlonly + * @param[in] cp LinphoneCallParams object + * @param[in] privacy The privacy mode to used for the call. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy); + +/** + * Enable recording of the call. + * This function must be used before the call parameters are assigned to the call. + * The call recording can be started and paused after the call is established with + * linphone_call_start_recording() and linphone_call_pause_recording(). + * @param[in] cp LinphoneCallParams object + * @param[in] path A string containing the path and filename of the file where audio/video streams are to be written. + * The filename must have either .mkv or .wav extention. The video stream will be written only if a MKV file is given. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path); + +/** + * Set the session name of the media session (ie in SDP). + * Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header(). + * @param[in] cp LinphoneCallParams object + * @param[in] name The session name to be used. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name); + +/** + * Tell whether video is enabled or not. + * @param[in] cp LinphoneCallParams object + * @return A boolean value telling whether video is enabled or not. +**/ +LINPHONE_PUBLIC bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp); + + +/******************************************************************************* + * Reference and user data handling functions * + ******************************************************************************/ + +/** + * Get the user data associated with the call params. + * @param[in] cl LinphoneCallParams object + * @return The user data associated with the call params. +**/ +LINPHONE_PUBLIC void *linphone_call_params_get_user_data(const LinphoneCallParams *cp); + +/** + * Assign a user data to the call params. + * @param[in] cl LinphoneCallParams object + * @param[in] ud The user data to associate with the call params. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_user_data(LinphoneCallParams *cp, void *ud); + +/** + * Acquire a reference to the call params. + * @param[in] cl LinphoneCallParams object + * @return The same LinphoneCallParams object +**/ +LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_ref(LinphoneCallParams *cp); + +/** + * Release a reference to the call params. + * @param[in] cl LinphoneCallParams object +**/ +LINPHONE_PUBLIC void linphone_call_params_unref(LinphoneCallParams *cp); + + +/******************************************************************************* + * DEPRECATED * + ******************************************************************************/ + +/** @deprecated Use linphone_call_params_get_local_conference_mode() instead. */ +#define linphone_call_params_local_conference_mode linphone_call_params_get_local_conference_mode + +/** + * Destroy a LinphoneCallParams object. + * @param[in] cp LinphoneCallParams object + * @deprecated Use linphone_call_params_unref() instead. +**/ +LINPHONE_PUBLIC void linphone_call_params_destroy(LinphoneCallParams *cp); + + +/** + * @} +**/ + + +#endif /* __LINPHONE_CALL_PARAMS_H__ */ diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index c64a5d7e3..bb6b5b9fb 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void register_failure(SalOp *op); static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) { - if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED; + if (call->params->in_conference != call->current_params->in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED; if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_CHANGED; if (call->localdesc_changed) ms_message("Local description has changed: %i", call->localdesc_changed); return call->localdesc_changed | sal_media_description_equals(oldmd, newmd); @@ -96,7 +96,7 @@ static void prepare_early_media_forking(LinphoneCall *call){ if (call->videostream){ rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,FALSE); } - + } void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){ @@ -152,7 +152,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia ms_message("Network parameters have changed, update them."); linphone_core_update_streams_destinations(lc, call, oldmd, new_md); } - if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) { + if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) { ms_message("Crypto parameters have changed, update them."); linphone_call_update_crypto_parameters(call, oldmd, new_md); } @@ -163,7 +163,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia linphone_call_stop_media_streams (call); linphone_call_init_media_streams (call); } - + if (call->audiostream==NULL){ /*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/ linphone_call_init_media_streams (call); @@ -171,10 +171,10 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){ send_ringbacktone=TRUE; } - if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params.real_early_media){ + if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params->real_early_media){ all_muted=TRUE; } - if (call->params.real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){ + if (call->params->real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){ prepare_early_media_forking(call); } linphone_call_start_media_streams(call,all_muted,send_ringbacktone); @@ -182,9 +182,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia linphone_core_play_named_tone(lc,LinphoneToneCallOnHold); } end: - if (oldmd) + if (oldmd) sal_media_description_unref(oldmd); - + } #if 0 static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){ @@ -192,7 +192,7 @@ static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, c for(elem=lc->calls;elem!=NULL;elem=elem->next){ LinphoneCall *call=(LinphoneCall*)elem->data; if (linphone_address_weak_equal(call->log->from,from) && - linphone_address_weak_equal(call->log->to, to)){ + linphone_address_weak_equal(call->log->to, to)){ return TRUE; } } @@ -220,11 +220,11 @@ static bool_t already_a_call_pending(LinphoneCore *lc){ for(elem=lc->calls;elem!=NULL;elem=elem->next){ LinphoneCall *call=(LinphoneCall*)elem->data; if (call->state==LinphoneCallIncomingReceived - || call->state==LinphoneCallIncomingEarlyMedia - || call->state==LinphoneCallOutgoingInit - || call->state==LinphoneCallOutgoingProgress - || call->state==LinphoneCallOutgoingEarlyMedia - || call->state==LinphoneCallOutgoingRinging){ + || call->state==LinphoneCallIncomingEarlyMedia + || call->state==LinphoneCallOutgoingInit + || call->state==LinphoneCallOutgoingProgress + || call->state==LinphoneCallOutgoingEarlyMedia + || call->state==LinphoneCallOutgoingRinging){ return TRUE; } } @@ -234,12 +234,12 @@ static bool_t already_a_call_pending(LinphoneCore *lc){ static void call_received(SalOp *h){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); LinphoneCall *call; - const char *from,*to; char *alt_contact; - LinphoneAddress *from_addr, *to_addr; + LinphoneAddress *from_addr=NULL; + LinphoneAddress *to_addr=NULL; /*this mode is deprcated because probably useless*/ bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",FALSE); - + /* first check if we can answer successfully to this invite */ if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) { LinphonePresenceActivity *activity = linphone_presence_model_get_activity(lc->presence_model); @@ -272,10 +272,26 @@ static void call_received(SalOp *h){ sal_op_release(h); return; } - from=sal_op_get_from(h); - to=sal_op_get_to(h); - from_addr=linphone_address_new(from); - to_addr=linphone_address_new(to); + /*in some situation, better to trust the network rather than the UAC*/ + if (lp_config_get_int(lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0)) { + const char * p_asserted_id = sal_custom_header_find(sal_op_get_recv_custom_header(h),"P-Asserted-Identity"); + LinphoneAddress *p_asserted_id_addr; + if (!p_asserted_id) { + ms_warning("No P-Asserted-Identity header found so cannot use it for op [%p] instead of from",h); + } else { + p_asserted_id_addr = linphone_address_new(p_asserted_id); + if (!p_asserted_id_addr) { + ms_warning("Unsupported P-Asserted-Identity header for op [%p] ",h); + } else { + ms_message("Using P-Asserted-Identity [%s] instead of from [%s] for op [%p]",p_asserted_id,sal_op_get_from(h),h); + from_addr=p_asserted_id_addr; + } + } + } + + if (!from_addr) + from_addr=linphone_address_new(sal_op_get_from(h)); + to_addr=linphone_address_new(sal_op_get_to(h)); if ((already_a_call_with_remote_address(lc,from_addr) && prevent_colliding_calls) || already_a_call_pending(lc)){ ms_warning("Receiving another call while one is ringing or initiated, refusing this one with busy message."); @@ -285,14 +301,14 @@ static void call_received(SalOp *h){ linphone_address_destroy(to_addr); return; } - + call=linphone_call_new_incoming(lc,from_addr,to_addr,h); - + /* the call is acceptable so we can now add it to our list */ linphone_core_add_call(lc,call); linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */ - if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) { + if ((_linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) { /* Defer ringing until the end of the ICE candidates gathering process. */ ms_message("Defer ringing to gather ICE candidates"); return; @@ -313,7 +329,7 @@ static void try_early_media_forking(LinphoneCall *call, SalMediaDescription *md) int i; SalStreamDescription *ref_stream,*new_stream; ms_message("Early media response received from another branch, checking if media can be forked to this new destination."); - + for (i=0;inb_streams;++i){ if (!sal_stream_description_active(&cur_md->streams[i])) continue; ref_stream=&cur_md->streams[i]; @@ -345,15 +361,14 @@ static void call_ringing(SalOp *h){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(h); SalMediaDescription *md; - + if (call==NULL) return; - + /*set privacy*/ - call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); + call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); + + linphone_core_notify_display_status(lc,_("Remote ringing.")); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Remote ringing.")); - md=sal_call_get_final_media_description(h); if (md==NULL){ linphone_core_stop_dtmf_stream(lc); @@ -364,11 +379,12 @@ static void call_ringing(SalOp *h){ /*we release sound before playing ringback tone*/ if (call->audiostream) audio_stream_unprepare_sound(call->audiostream); - lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard); + if( lc->sound_conf.remote_ring ){ + lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard); + } } ms_message("Remote ringing..."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Remote ringing...")); + linphone_core_notify_display_status(lc,_("Remote ringing...")); linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing"); }else{ /*accept early media */ @@ -377,9 +393,8 @@ static void call_ringing(SalOp *h){ try_early_media_forking(call,md); return; } - if (lc->vtable.show) lc->vtable.show(lc); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Early media.")); + linphone_core_notify_show_interface(lc); + linphone_core_notify_display_status(lc,_("Early media.")); linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media"); linphone_core_stop_ringing(lc); ms_message("Doing early media..."); @@ -396,13 +411,14 @@ static void call_accepted(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); SalMediaDescription *md; - + bool_t update_state=TRUE; + if (call==NULL){ ms_warning("No call to accept."); return ; } /*set privacy*/ - call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); + call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); /* Handle remote ICE attributes if any. */ if (call->ice_session != NULL) { @@ -416,51 +432,58 @@ static void call_accepted(SalOp *op){ md=sal_call_get_final_media_description(op); if (md) /*make sure re-invite will not propose video again*/ - call->params.has_video &= linphone_core_media_description_contains_video_stream(md); - - if (call->state==LinphoneCallOutgoingProgress || - call->state==LinphoneCallOutgoingRinging || - call->state==LinphoneCallOutgoingEarlyMedia){ - linphone_call_set_state(call,LinphoneCallConnected,"Connected"); - if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); + call->params->has_video &= linphone_core_media_description_contains_video_stream(md); + + switch (call->state){ + case LinphoneCallOutgoingProgress: + case LinphoneCallOutgoingRinging: + case LinphoneCallOutgoingEarlyMedia: + linphone_call_set_state(call,LinphoneCallConnected,"Connected"); + if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); + break; + case LinphoneCallEarlyUpdating: + linphone_call_set_state(call,call->prevstate,"Early update accepted"); + update_state=FALSE; + break; + default: + break; } + if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){ linphone_call_update_remote_session_id_and_ver(call); if (sal_media_description_has_dir(md,SalStreamSendOnly) || - sal_media_description_has_dir(md,SalStreamInactive)){ - if (lc->vtable.display_status){ + sal_media_description_has_dir(md,SalStreamInactive)){ + { char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(tmp); ms_free(msg); } linphone_core_update_streams (lc,call,md); - linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); + if (update_state) linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL); }else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){ /*we are put on hold when the call is initially accepted */ - if (lc->vtable.display_status){ + { char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(tmp); ms_free(msg); } linphone_core_update_streams (lc,call,md); - linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote"); + if (update_state) linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote"); }else{ if (call->state!=LinphoneCallUpdating){ if (call->state==LinphoneCallResuming){ - if (lc->vtable.display_status){ - lc->vtable.display_status(lc,_("Call resumed.")); - } + linphone_core_notify_display_status(lc,_("Call resumed.")); }else{ - if (lc->vtable.display_status){ + { char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call answered by %s."),tmp); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(tmp); ms_free(msg); } @@ -470,10 +493,9 @@ static void call_accepted(SalOp *op){ /*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again * further in the call, for example during pause,resume, conferencing reINVITEs*/ linphone_call_fix_call_parameters(call); - if (!call->current_params.in_conference) + if (!call->current_params->in_conference) lc->current_call=call; - if (call->prevstate != LinphoneCallIncomingEarlyMedia) /*don't change state in aswer to a SIP UPDATE in early media*/ - linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); + if (update_state) linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); } }else{ /*send a bye*/ @@ -503,81 +525,74 @@ static void call_ack(SalOp *op){ } } -static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){ - SalMediaDescription *md; - SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op); - if (rmd!=NULL && call->ice_session!=NULL) { - linphone_core_update_ice_from_remote_media_description(call,rmd); - linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session); - } -#ifdef BUILD_UPNP - if(call->upnp_session != NULL) { - linphone_core_update_upnp_from_remote_media_description(call, rmd); - linphone_core_update_local_media_description_from_upnp(call->localdesc,call->upnp_session); - } -#endif //BUILD_UPNP - linphone_call_update_remote_session_id_and_ver(call); - sal_call_accept(call->op); - md=sal_call_get_final_media_description(call->op); - if (md && !sal_media_description_empty(md)){ - linphone_core_update_streams(lc,call,md); - } -} - static void call_resumed(LinphoneCore *lc, LinphoneCall *call){ /*when we are resumed, increment session id, because sdp is changed (a=recvonly disapears)*/ linphone_call_increment_local_media_description(call); - call_accept_update(lc,call); - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("We have been resumed.")); - linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); + linphone_core_notify_display_status(lc,_("We have been resumed.")); + _linphone_core_accept_call_update(lc,call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)"); } static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){ - /*when we are resumed, increment session id, because sdp is changed (a=recvonly appears)*/ + /*when we are paused, increment session id, because sdp is changed (a=recvonly appears)*/ linphone_call_increment_local_media_description(call); - call_accept_update(lc,call); /* we are being paused */ - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("We are paused by other party.")); - linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote"); + linphone_core_notify_display_status(lc,_("We are paused by other party.")); + _linphone_core_accept_call_update(lc,call,NULL,LinphoneCallPausedByRemote,"Call paused by remote"); + } -static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call,bool_t notify_application){ +static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t is_update){ /*first check if media capabilities are compatible*/ - SalMediaDescription* md; - linphone_call_make_local_media_description(lc,call); - sal_call_set_local_media_description(call->op,call->localdesc); - md=sal_call_get_final_media_description(call->op); - if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); - return; + SalMediaDescription *md; + SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op); + SalMediaDescription *prev_result_desc=call->resultdesc; + + if (rmd!=NULL){ + if (call->state!=LinphoneCallPaused){ + /*in paused state, we must stay in paused state.*/ + linphone_call_make_local_media_description(lc,call); + sal_call_set_local_media_description(call->op,call->localdesc); + } + md=sal_call_get_final_media_description(call->op); + if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ + sal_call_decline(call->op,SalReasonNotAcceptable,NULL); + return; + } + if (is_update && prev_result_desc && md){ + int diff=sal_media_description_equals(prev_result_desc,md); + if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ + ms_warning("Cannot accept this update, it is changing parameters that require user approval"); + sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/ + return; + } + } } - if (notify_application) { - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("Call is updated by remote.")); + if (call->state==LinphoneCallStreamsRunning) { + /*reINVITE and in-dialogs UPDATE go here*/ + linphone_core_notify_display_status(lc,_("Call is updated by remote.")); call->defer_update=FALSE; linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); if (call->defer_update==FALSE){ linphone_core_accept_call_update(lc,call,NULL); } - } else { /*SIP UPDATE case*/ - /*can be call from any state*/ - _linphone_core_accept_call_update(lc,call,NULL); + if (rmd==NULL) + call->expect_media_in_ack=TRUE; + } else if (is_update){ /*SIP UPDATE case, can occur in early states*/ + linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote"); + _linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate)); } } /* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ -static void call_updating(SalOp *op){ +static void call_updating(SalOp *op, bool_t is_update){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); SalMediaDescription *rmd=sal_call_get_remote_media_description(op); if (rmd==NULL){ - /* case of a reINVITE without SDP */ - call_accept_update(lc,call); - call->expect_media_in_ack=TRUE; + /* case of a reINVITE or UPDATE without SDP */ + call_updated_by_remote(lc,call,is_update); return; } @@ -585,22 +600,47 @@ static void call_updating(SalOp *op){ case LinphoneCallPausedByRemote: if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){ call_resumed(lc,call); - }else call_paused_by_remote(lc,call); + }else call_updated_by_remote(lc,call,is_update); break; /*SIP UPDATE CASE*/ + case LinphoneCallOutgoingRinging: case LinphoneCallOutgoingEarlyMedia: - call_updated_by_remote(lc,call,FALSE); + case LinphoneCallIncomingEarlyMedia: + if (is_update) call_updated_by_remote(lc,call,is_update); break; case LinphoneCallStreamsRunning: case LinphoneCallConnected: if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){ call_paused_by_remote(lc,call); }else{ - call_updated_by_remote(lc,call,TRUE); + call_updated_by_remote(lc,call,is_update); } break; - default: - call_accept_update(lc,call); + case LinphoneCallPaused: + if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){ + call_paused_by_remote(lc,call); + }else{ + call_updated_by_remote(lc,call,is_update); + } + break; + case LinphoneCallUpdating: + case LinphoneCallPausing: + case LinphoneCallResuming: + case LinphoneCallUpdatedByRemote: + sal_call_decline(call->op,SalReasonNotImplemented,NULL); + /*no break*/ + case LinphoneCallIdle: + case LinphoneCallOutgoingInit: + case LinphoneCallEnd: + case LinphoneCallIncomingReceived: + case LinphoneCallOutgoingProgress: + case LinphoneCallRefered: + case LinphoneCallError: + case LinphoneCallReleased: + case LinphoneCallEarlyUpdatedByRemote: + case LinphoneCallEarlyUpdating: + ms_warning("Receiving reINVITE or UPDATE while in state [%s], should not happen.",linphone_call_state_to_string(call->state)); + break; } } @@ -609,7 +649,7 @@ static void call_terminated(SalOp *op, const char *from){ LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); if (call==NULL) return; - + switch(linphone_call_get_state(call)){ case LinphoneCallEnd: case LinphoneCallError: @@ -632,10 +672,8 @@ static void call_terminated(SalOp *op, const char *from){ linphone_core_stop_ringing(lc); } linphone_call_stop_media_streams(call); - if (lc->vtable.show!=NULL) - lc->vtable.show(lc); - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Call terminated.")); + linphone_core_notify_show_interface(lc); + linphone_core_notify_display_status(lc,_("Call terminated.")); #ifdef BUILD_UPNP linphone_call_delete_upnp_session(call); @@ -645,15 +683,14 @@ static void call_terminated(SalOp *op, const char *from){ } static int resume_call_after_failed_transfer(LinphoneCall *call){ - ms_message("!!!!!!!!!!resume_call_after_failed_transfer"); if (call->was_automatically_paused && call->state==LinphoneCallPausing) return BELLE_SIP_CONTINUE; /*was still in pausing state*/ - + if (call->was_automatically_paused && call->state==LinphoneCallPaused){ if (sal_op_is_idle(call->op)){ linphone_core_resume_call(call->core,call); }else { - ms_message("!!!!!!!!!!resume_call_after_failed_transfer, salop was busy"); + ms_message("resume_call_after_failed_transfer(), salop was busy"); return BELLE_SIP_CONTINUE; } } @@ -677,25 +714,22 @@ static void call_failure(SalOp *op){ ms_warning("Call faillure reported on already terminated call."); return ; } - - if (lc->vtable.show) lc->vtable.show(lc); + + linphone_core_notify_show_interface(lc); switch(ei->reason){ case SalReasonNone: break; case SalReasonRequestTimeout: msg=_("Request timeout."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); break; case SalReasonDeclined: msg=msg603; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg603); + linphone_core_notify_display_status(lc,msg603); break; case SalReasonBusy: msg=msg486; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg486); + linphone_core_notify_display_status(lc,msg486); break; case SalReasonRedirect: { @@ -715,23 +749,19 @@ static void call_failure(SalOp *op){ } } msg=_("Redirected"); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); } break; case SalReasonTemporarilyUnavailable: msg=msg480; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg480); + linphone_core_notify_display_status(lc,msg480); break; case SalReasonNotFound: - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); break; case SalReasonDoNotDisturb: msg=msg600; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg600); + linphone_core_notify_display_status(lc,msg600); break; case SalReasonUnsupportedContent: /*localdesc->nb_streams; i++) { if (!sal_stream_description_active(&call->localdesc->streams[i])) continue; - if (call->params.media_encryption == LinphoneMediaEncryptionSRTP) { - if (call->params.avpf_enabled == TRUE) { + if (call->params->media_encryption == LinphoneMediaEncryptionSRTP) { + if (call->params->avpf_enabled == TRUE) { if (i == 0) ms_message("Retrying call [%p] with SAVP", call); - call->params.avpf_enabled = FALSE; + call->params->avpf_enabled = FALSE; linphone_core_restart_invite(lc, call); return; } else if (!linphone_core_is_media_encryption_mandatory(lc)) { if (i == 0) ms_message("Retrying call [%p] with AVP", call); - call->params.media_encryption = LinphoneMediaEncryptionNone; + call->params->media_encryption = LinphoneMediaEncryptionNone; memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto)); linphone_core_restart_invite(lc, call); return; } - } else if (call->params.avpf_enabled == TRUE) { + } else if (call->params->avpf_enabled == TRUE) { if (i == 0) ms_message("Retrying call [%p] with AVP", call); - call->params.avpf_enabled = FALSE; + call->params->avpf_enabled = FALSE; linphone_core_restart_invite(lc, call); return; } } } msg=_("Incompatible media parameters."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); break; case SalReasonRequestPending: /*restore previous state, the application will decide to resubmit the action if relevant*/ @@ -774,8 +803,7 @@ static void call_failure(SalOp *op){ return; break; default: - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Call failed.")); + linphone_core_notify_display_status(lc,_("Call failed.")); } /*some call error are not fatal*/ @@ -796,7 +824,7 @@ static void call_failure(SalOp *op){ #ifdef BUILD_UPNP linphone_call_delete_upnp_session(call); #endif //BUILD_UPNP - + if (call->state!=LinphoneCallEnd && call->state!=LinphoneCallError){ if (ei->reason==SalReasonDeclined){ linphone_call_set_state(call,LinphoneCallEnd,"Call declined."); @@ -805,7 +833,7 @@ static void call_failure(SalOp *op){ } if (ei->reason!=SalReasonNone) linphone_core_play_call_error_tone(lc,linphone_reason_from_sal(ei->reason)); } - + if (referer){ /*notify referer of the failure*/ linphone_core_notify_refer_state(lc,referer,call); @@ -827,35 +855,38 @@ static void call_released(SalOp *op){ static void auth_failure(SalOp *op, SalAuthInfo* info) { LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain); - if (ai){ - ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain); - /*ask again for password if auth info was already supplied but apparently not working*/ - if (lc->vtable.auth_info_requested) { - lc->vtable.auth_info_requested(lc,info->realm,info->username,info->domain); + LinphoneAuthInfo *ai=NULL; + + if( info != NULL ){ + ai = (LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain); + + if (ai){ + ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain); + /*ask again for password if auth info was already supplied but apparently not working*/ + linphone_core_notify_auth_info_requested(lc,info->realm,info->username,info->domain); } } - + } static void register_success(SalOp *op, bool_t registered){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); char *msg; - - if (!cfg || cfg->deletion_date!=0){ - ms_message("Registration success for removed proxy config, ignored"); + + if (!cfg){ + ms_message("Registration success for deleted proxy config, ignored"); return; } linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared , - registered ? "Registration successful" : "Unregistration done"); - if (lc->vtable.display_status){ + registered ? "Registration successful" : "Unregistration done"); + { if (registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op)); else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op)); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(msg); } - + } static void register_failure(SalOp *op){ @@ -868,16 +899,12 @@ static void register_failure(SalOp *op){ ms_warning("Registration failed for unknown proxy config."); return ; } - if (cfg->deletion_date!=0){ - ms_message("Registration failed for removed proxy config, ignored"); - return; - } if (details==NULL) details=_("no response timeout"); - - if (lc->vtable.display_status) { + + { char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op), details); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(msg); } @@ -910,8 +937,7 @@ static void vfu_request(SalOp *op){ static void dtmf_received(SalOp *op, char dtmf){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - if (lc->vtable.dtmf_received != NULL) - lc->vtable.dtmf_received(lc, call, dtmf); + linphone_core_notify_dtmf_received(lc, call, dtmf); } static void refer_received(Sal *sal, SalOp *op, const char *referto){ @@ -924,14 +950,14 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){ call->refer_to=ms_strdup(referto); call->refer_pending=TRUE; linphone_call_set_state(call,LinphoneCallRefered,"Refered"); - if (lc->vtable.display_status){ + { char *msg=ms_strdup_printf(_("We are transferred to %s"),referto); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(msg); } if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL); - }else if (lc->vtable.refer_received){ - lc->vtable.refer_received(lc,referto); + }else { + linphone_core_notify_refer_received(lc,referto); } } @@ -1051,8 +1077,8 @@ static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) { if (fill_auth_info(lc,sai)) { return TRUE; } else { - if (lc->vtable.auth_info_requested) { - lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain); + { + linphone_core_notify_auth_info_requested(lc,sai->realm,sai->username,sai->domain); if (fill_auth_info(lc,sai)) { return TRUE; } @@ -1135,9 +1161,9 @@ static void info_received(SalOp *op, const SalBody *body){ static void subscribe_response(SalOp *op, SalSubscribeStatus status){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); const SalErrorInfo *ei=sal_op_get_error_info(op); - + if (lev==NULL) return; - + if (status==SalSubscribeActive){ linphone_event_set_state(lev,LinphoneSubscriptionActive); }else if (status==SalSubscribePending){ @@ -1153,15 +1179,15 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status){ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneContent content; - + LinphoneContent content={0}; + if (lev==NULL) { /*out of subscribe notify */ lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname); } - if (lc->vtable.notify_received){ + { const LinphoneContent *ct=linphone_content_from_sal_body(&content,body); - if (ct) lc->vtable.notify_received(lc,lev,eventname,ct); + if (ct) linphone_core_notify_notify_received(lc,lev,eventname,ct); } if (st!=SalSubscribeNone){ linphone_event_set_state(lev,linphone_subscription_state_from_sal(st)); @@ -1171,31 +1197,31 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - + if (lev==NULL) { lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionIncoming,eventname); linphone_event_set_state(lev,LinphoneSubscriptionIncomingReceived); }else{ /*subscribe refresh, unhandled*/ } - + } static void subscribe_closed(SalOp *op){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - + linphone_event_set_state(lev,LinphoneSubscriptionTerminated); } static void on_publish_response(SalOp* op){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); const SalErrorInfo *ei=sal_op_get_error_info(op); - + if (lev==NULL) return; if (ei->reason==SalReasonNone){ if (!lev->terminating) linphone_event_set_publish_state(lev,LinphonePublishOk); - else + else linphone_event_set_publish_state(lev,LinphonePublishCleared); }else{ if (lev->publish_state==LinphonePublishOk){ @@ -1208,9 +1234,9 @@ static void on_publish_response(SalOp* op){ static void on_expire(SalOp *op){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - + if (lev==NULL) return; - + if (linphone_event_get_publish_state(lev)==LinphonePublishOk){ linphone_event_set_publish_state(lev,LinphonePublishExpiring); }else if (linphone_event_get_subscription_state(lev)==LinphoneSubscriptionActive){ diff --git a/coreapi/chat.c b/coreapi/chat.c index c9ec8b6d5..45e1fc1ce 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -36,29 +36,19 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg); -#define MULTIPART_BOUNDARY "---------------------------14737809831466499882746641449" -#define FILEPART_HEADER_1 "Content-Disposition: form-data; name=\"File\"; filename=\"" -#define FILEPART_HEADER_2 "\"\r\n" \ - "Content-Type: " -#define FILEPART_HEADER_3 "\r\n\r\n" -const char *multipart_boundary=MULTIPART_BOUNDARY; - -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_upload(void *data, const belle_sip_io_error_event_t *event){ LinphoneChatMessage* msg=(LinphoneChatMessage *)data; - 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); + ms_error("I/O Error during file upload to %s - msg [%p] chat room[%p]", linphone_core_get_file_transfer_server(msg->chat_room->lc), msg, msg->chat_room); if (msg->cb) { - msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc); + msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->cb_ud); } } 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); + ms_error("Error during file upload : auth requested to connect %s - msg [%p] chat room[%p]", linphone_core_get_file_transfer_server(msg->chat_room->lc), msg, msg->chat_room); if (msg->cb) { - msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc); + msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->cb_ud); } } @@ -66,14 +56,14 @@ static void process_io_error_download(void *data, const belle_sip_io_error_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); + msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->cb_ud); } } 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); + msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->cb_ud); } } @@ -85,9 +75,7 @@ static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handl LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data; LinphoneCore *lc = chatMsg->chat_room->lc; /* call back given by application level */ - if (lc->vtable.file_transfer_progress_indication != NULL) { - lc->vtable.file_transfer_progress_indication(lc, chatMsg, chatMsg->file_transfer_information, (size_t)(((double)offset/(double)total)*100.0)); - } + linphone_core_notify_file_transfer_progress_indication(lc, chatMsg, chatMsg->file_transfer_information, offset, total); return; } @@ -107,28 +95,12 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_ LinphoneCore *lc = chatMsg->chat_room->lc; char *buf = (char *)buffer; - char *content_type=belle_sip_strdup_printf("%s/%s", chatMsg->file_transfer_information->type, chatMsg->file_transfer_information->subtype); - size_t end_of_file=linphone_chat_message_compute_filepart_header_size(chatMsg->file_transfer_information->name, content_type)+chatMsg->file_transfer_information->size; - - if (offset==0){ - int partlen=linphone_chat_message_compute_filepart_header_size(chatMsg->file_transfer_information->name, content_type); - memcpy(buf,FILEPART_HEADER_1,strlen(FILEPART_HEADER_1)); - buf += strlen(FILEPART_HEADER_1); - memcpy(buf,chatMsg->file_transfer_information->name,strlen(chatMsg->file_transfer_information->name)); - buf += strlen(chatMsg->file_transfer_information->name); - memcpy(buf,FILEPART_HEADER_2,strlen(FILEPART_HEADER_2)); - buf += strlen(FILEPART_HEADER_2); - memcpy(buf,content_type,strlen(content_type)); - buf += strlen(content_type); - memcpy(buf,FILEPART_HEADER_3,strlen(FILEPART_HEADER_3)); - - *size=partlen; - }else if (offsetfile_transfer_information->size){ /* get data from call back */ - lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size); + linphone_core_notify_file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size); } - belle_sip_free(content_type); return BELLE_SIP_CONTINUE; } @@ -152,29 +124,35 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co belle_http_request_listener_t *l; belle_generic_uri_t *uri; belle_http_request_t *req; - char *content_type=belle_sip_strdup_printf("%s/%s", msg->file_transfer_information->type, msg->file_transfer_information->subtype); - - /* create a user body handler to take care of the file */ - size_t body_size = msg->file_transfer_information->size+linphone_chat_message_compute_filepart_header_size(msg->file_transfer_information->name, content_type); - - 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); + belle_sip_multipart_body_handler_t *bh; + char* ua; + char *first_part_header; + belle_sip_body_handler_t *first_part_bh; - char* ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version()); + /* temporary storage for the Content-disposition header value */ + first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"", msg->file_transfer_information->name); - belle_sip_free(content_type); - content_type=belle_sip_strdup_printf("multipart/form-data; boundary=%s",multipart_boundary); + /* create a user body handler to take care of the file and add the content disposition and content-type headers */ + if (msg->file_transfer_filepath != NULL) { + first_part_bh=(belle_sip_body_handler_t *)belle_sip_file_body_handler_new(msg->file_transfer_filepath,NULL,msg); + } else { + first_part_bh=(belle_sip_body_handler_t *)belle_sip_user_body_handler_new(msg->file_transfer_information->size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg); + } + belle_sip_body_handler_add_header(first_part_bh, belle_sip_header_create("Content-disposition", first_part_header)); + belle_sip_free(first_part_header); + belle_sip_body_handler_add_header(first_part_bh, (belle_sip_header_t *)belle_sip_header_content_type_create(msg->file_transfer_information->type, msg->file_transfer_information->subtype)); - uri=belle_generic_uri_parse(msg->chat_room->lc->file_transfer_server); + /* insert it in a multipart body handler which will manage the boundaries of multipart message */ + bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, first_part_bh); + /* create the http request: do not include the message header at this point, it is done by bellesip when setting the multipart body handler in the message */ + ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version()); + uri=belle_generic_uri_parse(linphone_core_get_file_transfer_server(msg->chat_room->lc)); req=belle_http_request_create("POST", uri, belle_sip_header_create("User-Agent",ua), - belle_sip_header_create("Content-type",content_type), NULL); ms_free(ua); - 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_upload; @@ -191,10 +169,10 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co } 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); - msg->file_transfer_information = NULL; msg->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml"); + if (msg->cb) { + msg->cb(msg, LinphoneChatMessageStateFileTransferDone, msg->cb_ud); + } _linphone_chat_room_send_message(msg->chat_room, msg); } } @@ -246,44 +224,59 @@ bool_t linphone_core_chat_enabled(const LinphoneCore *lc){ /** * Returns an list of chat rooms - * @param lc #LinphoneCore object - * @return A list of #LinphoneChatRoom + * @param[in] lc #LinphoneCore object + * @return \mslist{LinphoneChatRoom} **/ MSList* linphone_core_get_chat_rooms(LinphoneCore *lc) { return lc->chatrooms; } -/** - * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org - * @param lc #LinphoneCore object - * @param to destination address for messages - * @return #LinphoneChatRoom where messaging can take place. - */ -LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){ - LinphoneAddress *parsed_url=NULL; - - if ((parsed_url=linphone_core_interpret_url(lc,to))!=NULL){ - LinphoneChatRoom *cr=ms_new0(LinphoneChatRoom,1); - cr->lc=lc; - cr->peer=linphone_address_as_string(parsed_url); - cr->peer_url=parsed_url; - lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr); - return cr; +static bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){ + return linphone_address_weak_equal(cr->peer_url,from); +} + +static void _linphone_chat_room_destroy(LinphoneChatRoom *obj); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatRoom); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatRoom, belle_sip_object_t, + (belle_sip_object_destroy_t)_linphone_chat_room_destroy, + NULL, // clone + NULL, // marshal + FALSE +); + +static LinphoneChatRoom * _linphone_core_create_chat_room(LinphoneCore *lc, LinphoneAddress *addr) { + LinphoneChatRoom *cr = belle_sip_object_new(LinphoneChatRoom); + cr->lc = lc; + cr->peer = linphone_address_as_string(addr); + cr->peer_url = addr; + lc->chatrooms = ms_list_append(lc->chatrooms, (void *)cr); + return cr; +} + +static LinphoneChatRoom * _linphone_core_create_chat_room_from_url(LinphoneCore *lc, const char *to) { + LinphoneAddress *parsed_url = NULL; + if ((parsed_url = linphone_core_interpret_url(lc, to)) != NULL) { + return _linphone_core_create_chat_room(lc, parsed_url); } return NULL; } -bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){ - return linphone_address_weak_equal(cr->peer_url,from); +LinphoneChatRoom * _linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){ + LinphoneChatRoom *cr=NULL; + MSList *elem; + for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){ + cr=(LinphoneChatRoom*)elem->data; + if (linphone_chat_room_matches(cr,addr)){ + break; + } + cr=NULL; + } + return cr; } -/** - * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one - * @param lc #LinphoneCore object - * @param to destination address for messages - * @return #LinphoneChatRoom where messaging can take place. - */ -LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) { +static LinphoneChatRoom * _linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) { LinphoneAddress *to_addr=linphone_core_interpret_url(lc,to); LinphoneChatRoom *ret; @@ -291,17 +284,63 @@ LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const ms_error("linphone_core_get_or_create_chat_room(): Cannot make a valid address with %s",to); return NULL; } - ret=linphone_core_get_chat_room(lc,to_addr); + ret=_linphone_core_get_chat_room(lc,to_addr); linphone_address_destroy(to_addr); if (!ret){ - ret=linphone_core_create_chat_room(lc,to); + ret=_linphone_core_create_chat_room_from_url(lc,to); } return ret; } +/** + * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one + * @param lc #LinphoneCore object + * @param to destination address for messages + * @return #LinphoneChatRoom where messaging can take place. + * @deprecated Use linphone_core_get_chat_room() or linphone_core_get_chat_room_from_uri() instead. + */ +LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) { + return _linphone_core_get_or_create_chat_room(lc, to); +} + +/** + * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org + * @param lc #LinphoneCore object + * @param to destination address for messages + * @return #LinphoneChatRoom where messaging can take place. + * @deprecated Use linphone_core_get_chat_room() or linphone_core_get_chat_room_from_uri() instead. + */ +LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to) { + return _linphone_core_get_or_create_chat_room(lc, to); +} + +/** + * Get a chat room whose peer is the supplied address. If it does not exist yet, it will be created. + * @param lc the linphone core + * @param addr a linphone address. + * @returns #LinphoneChatRoom where messaging can take place. +**/ +LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){ + LinphoneChatRoom *ret = _linphone_core_get_chat_room(lc, addr); + if (!ret) { + ret = _linphone_core_create_chat_room(lc, linphone_address_clone(addr)); + } + return ret; +} + +/** + * Get a chat room for messaging from a sip uri like sip:joe@sip.linphone.org. If it does not exist yet, it will be created. + * @param lc The linphone core + * @param to The destination address for messages. + * @returns #LinphoneChatRoom where messaging can take place. +**/ +LinphoneChatRoom * linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to) { + return _linphone_core_get_or_create_chat_room(lc, to); +} + static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) { if (cr->composing_idle_timer) { - if(cr->lc->sal) + if(cr-> lc && cr->lc->sal) sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer); belle_sip_object_unref(cr->composing_idle_timer); cr->composing_idle_timer = NULL; @@ -310,7 +349,7 @@ 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) { - if(cr->lc->sal) + if(cr->lc && cr->lc->sal) sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer); belle_sip_object_unref(cr->composing_refresh_timer); cr->composing_refresh_timer = NULL; @@ -319,29 +358,55 @@ static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom * static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) { if (cr->remote_composing_refresh_timer) { - if(cr->lc->sal) + if(cr->lc && cr->lc->sal) sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer); belle_sip_object_unref(cr->remote_composing_refresh_timer); cr->remote_composing_refresh_timer = NULL; } } -/** - * Destroy a LinphoneChatRoom. - * @param cr #LinphoneChatRoom object - */ -void linphone_chat_room_destroy(LinphoneChatRoom *cr){ - LinphoneCore *lc=cr->lc; +static void _linphone_chat_room_destroy(LinphoneChatRoom *cr){ ms_list_free_with_data(cr->transient_messages, (void (*)(void*))linphone_chat_message_unref); linphone_chat_room_delete_composing_idle_timer(cr); linphone_chat_room_delete_composing_refresh_timer(cr); linphone_chat_room_delete_remote_composing_refresh_timer(cr); - lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr); + if (cr->lc != NULL) { + cr->lc->chatrooms=ms_list_remove(cr->lc->chatrooms,(void *) cr); + } linphone_address_destroy(cr->peer_url); ms_free(cr->peer); - ms_free(cr); } +/** + * Destroy a LinphoneChatRoom. + * @param cr #LinphoneChatRoom object + * @deprecated Use linphone_chat_room_unref() instead. + */ +void linphone_chat_room_destroy(LinphoneChatRoom *cr) { + linphone_chat_room_unref(cr); +} + +void linphone_chat_room_release(LinphoneChatRoom *cr) { + cr->lc = NULL; + linphone_chat_room_unref(cr); +} + +LinphoneChatRoom * linphone_chat_room_ref(LinphoneChatRoom *cr) { + belle_sip_object_ref(cr); + return cr; +} + +void linphone_chat_room_unref(LinphoneChatRoom *cr) { + belle_sip_object_unref(cr); +} + +void * linphone_chat_room_get_user_data(const LinphoneChatRoom *cr) { + return cr->user_data; +} + +void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud) { + cr->user_data = ud; +} static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){ @@ -352,14 +417,14 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM time_t t=time(NULL); linphone_chat_message_ref(msg); /* Check if we shall upload a file to a server */ - if (msg->file_transfer_information != NULL) { + if (msg->file_transfer_information != NULL && msg->content_type == NULL) { /* open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */ belle_http_request_listener_callbacks_t cbs={0}; belle_http_request_listener_t *l; belle_generic_uri_t *uri; belle_http_request_t *req; - uri=belle_generic_uri_parse(cr->lc->file_transfer_server); + uri=belle_generic_uri_parse(linphone_core_get_file_transfer_server(cr->lc)); req=belle_http_request_create("POST", uri, @@ -409,6 +474,9 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM sal_text_send(op, identity, cr->peer,msg->message); } else { sal_message_send(op, identity, cr->peer, msg->content_type, msg->message); + // Remove the message to prevent the xml from the file uplaod to be stored in the database + ms_free(msg->message); + msg->message = NULL; } } msg->dir=LinphoneChatMessageOutgoing; @@ -439,31 +507,10 @@ void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) { void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, LinphoneChatMessage *msg){ if (msg->message) //legacy API - if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, msg->from, msg->message); - if (lc->vtable.message_received!=NULL) lc->vtable.message_received(lc, cr,msg); - if (cr->lc->vtable.is_composing_received != NULL) { - cr->remote_is_composing = LinphoneIsComposingIdle; - cr->lc->vtable.is_composing_received(cr->lc, cr); - } -} - -/** - * Retrieve an existing chat room whose peer is the supplied address, if exists. - * @param lc the linphone core - * @param addr a linphone address. - * @returns the matching chatroom, or NULL if no such chatroom exists. -**/ -LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){ - LinphoneChatRoom *cr=NULL; - MSList *elem; - for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){ - cr=(LinphoneChatRoom*)elem->data; - if (linphone_chat_room_matches(cr,addr)){ - break; - } - cr=NULL; - } - return cr; + linphone_core_notify_text_message_received(lc, cr, msg->from, msg->message); + linphone_core_notify_message_received(lc, cr,msg); + cr->remote_is_composing = LinphoneIsComposingIdle; + linphone_core_notify_is_composing_received(cr->lc, cr); } void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg){ @@ -567,6 +614,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag linphone_address_destroy(addr); msg->storage_id=linphone_chat_message_store(msg); linphone_chat_room_message_received(cr,lc,msg); + linphone_chat_message_unref(msg); ms_free(cleanfrom); ms_free(from); } @@ -576,8 +624,7 @@ static int linphone_chat_room_remote_refresh_composing_expired(void *data, unsig belle_sip_object_unref(cr->remote_composing_refresh_timer); cr->remote_composing_refresh_timer = NULL; cr->remote_is_composing = LinphoneIsComposingIdle; - if (cr->lc->vtable.is_composing_received != NULL) - cr->lc->vtable.is_composing_received(cr->lc, cr); + linphone_core_notify_is_composing_received(cr->lc, cr); return BELLE_SIP_STOP; } @@ -622,8 +669,7 @@ static void process_im_is_composing_notification(LinphoneChatRoom *cr, xmlparsin } cr->remote_is_composing = state; - if (cr->lc->vtable.is_composing_received != NULL) - cr->lc->vtable.is_composing_received(cr->lc, cr); + linphone_core_notify_is_composing_received(cr->lc, cr); } } @@ -665,20 +711,6 @@ LinphoneCore* linphone_chat_room_get_core(LinphoneChatRoom *cr){ return cr->lc; } -/** - * Assign a user pointer to the chat room. -**/ -void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud){ - cr->user_data=ud; -} - -/** - * Retrieve the user pointer associated with the chat room. -**/ -void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr){ - return cr->user_data; -} - /** * get peer address \link linphone_core_create_chat_room() associated to \endlink this #LinphoneChatRoom * @param cr #LinphoneChatRoom object @@ -995,9 +1027,7 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t return; } /* call back given by application level */ - if (lc->vtable.file_transfer_recv != NULL) { - lc->vtable.file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size); - } + linphone_core_notify_file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size); return; } @@ -1045,16 +1075,21 @@ static void linphone_chat_process_response_headers_from_get_file(void *data, con 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(body_size, linphone_chat_message_file_transfer_on_progress,on_recv_body,NULL,message) - ); + if (message->file_transfer_filepath == NULL) { + belle_sip_message_set_body_handler( + (belle_sip_message_t*)event->response, + (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) + ); + } else { + belle_sip_message_set_body_handler( + (belle_sip_message_t *)event->response, + (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(message->file_transfer_filepath, linphone_chat_message_file_transfer_on_progress, message) + ); + } } } static void linphone_chat_process_response_from_get_file(void *data, const belle_http_response_event_t *event){ - //LinphoneChatMessage* msg=(LinphoneChatMessage *)data; - /* check the answer code */ if (event->response){ int code=belle_http_response_get_status_code(event->response); @@ -1062,8 +1097,9 @@ 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_recv != NULL) { - lc->vtable.file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0); + linphone_core_notify_file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0); + if (chatMsg->cb) { + chatMsg->cb(chatMsg, LinphoneChatMessageStateFileTransferDone, chatMsg->cb_ud); } } } @@ -1075,7 +1111,7 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle * @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(LinphoneChatMessage *message, LinphoneChatMessageStateChangedCb status_cb) { +void linphone_chat_message_start_file_download(LinphoneChatMessage *message, LinphoneChatMessageStateChangedCb status_cb, void *ud) { belle_http_request_listener_callbacks_t cbs={0}; belle_http_request_listener_t *l; belle_generic_uri_t *uri; @@ -1100,6 +1136,7 @@ void linphone_chat_message_start_file_download(LinphoneChatMessage *message, Lin 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->cb_ud = ud; message->state = LinphoneChatMessageStateInProgress; /* start the download, status is In Progress */ belle_http_provider_send_request(message->chat_room->lc->http_provider,req,l); } @@ -1109,51 +1146,51 @@ void linphone_chat_message_start_file_download(LinphoneChatMessage *message, Lin * @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); + ms_message("Cancelled file transfer %s - msg [%p] chat room[%p]", (msg->external_body_url==NULL)?linphone_core_get_file_transfer_server(msg->chat_room->lc):msg->external_body_url, msg, msg->chat_room); /* 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); + msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->cb_ud); } } /** * Set origin of the message - *@param message #LinphoneChatMessage obj - *@param from #LinphoneAddress origin of this message (copied) + * @param[in] message #LinphoneChatMessage obj + * @param[in] from #LinphoneAddress origin of this message (copied) */ -void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from) { +void linphone_chat_message_set_from_address(LinphoneChatMessage* message, const LinphoneAddress* from) { if(message->from) linphone_address_destroy(message->from); message->from=linphone_address_clone(from); } /** * Get origin of the message - *@param message #LinphoneChatMessage obj - *@return #LinphoneAddress + * @param[in] message #LinphoneChatMessage obj + * @return #LinphoneAddress */ -const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) { +const LinphoneAddress* linphone_chat_message_get_from_address(const LinphoneChatMessage* message) { return message->from; } /** * Set destination of the message - *@param message #LinphoneChatMessage obj - *@param to #LinphoneAddress destination of this message (copied) + * @param[in] message #LinphoneChatMessage obj + * @param[in] to #LinphoneAddress destination of this message (copied) */ -void linphone_chat_message_set_to(LinphoneChatMessage* message, const LinphoneAddress* to) { +void linphone_chat_message_set_to_address(LinphoneChatMessage* message, const LinphoneAddress* to) { if(message->to) linphone_address_destroy(message->to); message->to=linphone_address_clone(to); } /** * Get destination of the message - *@param message #LinphoneChatMessage obj - *@return #LinphoneAddress + * @param[in] message #LinphoneChatMessage obj + * @return #LinphoneAddress */ -const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message){ +const LinphoneAddress* linphone_chat_message_get_to_address(const LinphoneChatMessage* message){ if (message->to) return message->to; if (message->dir==LinphoneChatMessageOutgoing){ return message->chat_room->peer_url; @@ -1265,6 +1302,7 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg) new_message->state=msg->state; new_message->storage_id=msg->storage_id; if (msg->from) new_message->from=linphone_address_clone(msg->from); + if (msg->file_transfer_filepath) new_message->file_transfer_filepath=ms_strdup(msg->file_transfer_filepath); return new_message; } @@ -1292,6 +1330,10 @@ static void _linphone_chat_message_destroy(LinphoneChatMessage* msg) { linphone_content_uninit(msg->file_transfer_information); ms_free(msg->file_transfer_information); } + if (msg->file_transfer_filepath != NULL) { + ms_free(msg->file_transfer_filepath); + } + ms_message("LinphoneChatMessage [%p] destroyed.",msg); } @@ -1327,6 +1369,27 @@ LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage* msg) { } +/** + * Set the path to the file to read from or write to during the file transfer. + * @param[in] msg LinphoneChatMessage object + * @param[in] filepath The path to the file to use for the file transfer. + */ +void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath) { + if (msg->file_transfer_filepath != NULL) { + ms_free(msg->file_transfer_filepath); + } + msg->file_transfer_filepath = ms_strdup(filepath); +} + +/** + * Get the path to the file to read from or write to during the file transfer. + * @param[in] msg LinphoneChatMessage object + * @return The path to the file to use for the file transfer. + */ +const char * linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg) { + return msg->file_transfer_filepath; +} + /** * Create a message attached to a dedicated chat room with a particular content. Use #linphone_chat_room_send_message2 to initiate the transfer @@ -1347,7 +1410,6 @@ LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneCha linphone_chat_message_set_from(msg, linphone_address_new(linphone_core_get_identity(cr->lc))); msg->content_type=NULL; /* this will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */ msg->http_request=NULL; /* this will store the http request during file upload to the server */ - return msg; } diff --git a/coreapi/conference.c b/coreapi/conference.c index 7bee313dd..f860c33ad 100644 --- a/coreapi/conference.c +++ b/coreapi/conference.c @@ -41,6 +41,7 @@ static void conference_check_init(LinphoneConference *ctx, int samplerate){ MSAudioConferenceParams params; params.samplerate=samplerate; ctx->conf=ms_audio_conference_new(¶ms); + ctx->terminated=FALSE; } } @@ -74,7 +75,7 @@ void linphone_core_conference_check_uninit(LinphoneCore *lc){ if (ctx->conf){ int remote_count=remote_participants_count(ctx); ms_message("conference_check_uninit(): size=%i",linphone_conference_get_size(ctx)); - if (remote_count==1){ + if (remote_count==1 && !ctx->terminated){ convert_conference_to_call(lc); } if (remote_count==0){ @@ -98,7 +99,7 @@ void linphone_call_add_to_conf(LinphoneCall *call, bool_t muted){ LinphoneCore *lc=call->core; LinphoneConference *conf=&lc->conf_ctx; MSAudioEndpoint *ep; - call->params.has_video = FALSE; + call->params->has_video = FALSE; call->camera_enabled = FALSE; ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE); ms_audio_conference_add_member(conf->conf,ep); @@ -184,15 +185,15 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){ int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){ LinphoneConference *conf=&lc->conf_ctx; - if (call->current_params.in_conference){ + if (call->current_params->in_conference){ ms_error("Already in conference"); return -1; } conference_check_init(&lc->conf_ctx, lp_config_get_int(lc->config, "sound","conference_rate",16000)); if (call->state==LinphoneCallPaused){ - call->params.in_conference=TRUE; - call->params.has_video=FALSE; + call->params->in_conference=TRUE; + call->params->has_video=FALSE; linphone_core_resume_call(lc,call); }else if (call->state==LinphoneCallStreamsRunning){ LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call)); @@ -222,8 +223,8 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a int err=0; char *str; - if (!call->current_params.in_conference){ - if (call->params.in_conference){ + if (!call->current_params->in_conference){ + if (call->params->in_conference){ ms_warning("Not (yet) in conference, be patient"); return -1; }else{ @@ -231,7 +232,7 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a return -1; } } - call->params.in_conference=FALSE; + call->params->in_conference=FALSE; str=linphone_call_get_remote_address_as_string(call); ms_message("%s will be removed from conference", str); @@ -251,7 +252,6 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a ms_message("Pausing call to actually remove from conference"); err=_linphone_core_pause_call(lc,call); } - return err; } @@ -267,7 +267,7 @@ static int convert_conference_to_call(LinphoneCore *lc){ while (calls) { LinphoneCall *rc=(LinphoneCall*)calls->data; calls=calls->next; - if (rc->params.in_conference) { // not using current_param + if (rc->params->in_conference) { // not using current_param bool_t active_after_removed=linphone_core_is_in_conference(lc); err=remove_from_conference(lc, rc, active_after_removed); break; @@ -370,7 +370,7 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) { while (calls) { LinphoneCall *call=(LinphoneCall*)calls->data; calls=calls->next; - if (!call->current_params.in_conference) { + if (!call->current_params->in_conference) { linphone_core_add_to_conference(lc, call); } } @@ -388,10 +388,13 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) { **/ int linphone_core_terminate_conference(LinphoneCore *lc) { MSList *calls=lc->calls; + LinphoneConference *conf=&lc->conf_ctx; + conf->terminated=TRUE; + while (calls) { LinphoneCall *call=(LinphoneCall*)calls->data; calls=calls->next; - if (call->current_params.in_conference) { + if (call->current_params->in_conference) { linphone_core_terminate_call(lc, call); } } diff --git a/coreapi/event.c b/coreapi/event.c index 992d058ab..372e0a953 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -89,13 +89,10 @@ LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp } void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){ - LinphoneCore *lc=lev->lc; if (lev->subscription_state!=state){ ms_message("LinphoneEvent [%p] moving to subscription state %s",lev,linphone_subscription_state_to_string(state)); lev->subscription_state=state; - if (lc->vtable.subscription_state_changed){ - lc->vtable.subscription_state_changed(lev->lc,lev,state); - } + linphone_core_notify_subscription_state_changed(lev->lc,lev,state); if (state==LinphoneSubscriptionTerminated){ linphone_event_unref(lev); } @@ -103,13 +100,10 @@ void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState stat } void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state){ - LinphoneCore *lc=lev->lc; if (lev->publish_state!=state){ ms_message("LinphoneEvent [%p] moving to publish state %s",lev,linphone_publish_state_to_string(state)); lev->publish_state=state; - if (lc->vtable.publish_state_changed){ - lc->vtable.publish_state_changed(lev->lc,lev,state); - } + linphone_core_notify_publish_state_changed(lev->lc,lev,state); switch(state){ case LinphonePublishCleared: linphone_event_unref(lev); diff --git a/coreapi/friend.c b/coreapi/friend.c index 7b0ddd816..d1ecd560c 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -253,8 +253,7 @@ static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ linphone_presence_model_unref(lf->presence); } lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity"); - if (lc->vtable.notify_presence_received) - lc->vtable.notify_presence_received(lc,lf); + linphone_core_notify_notify_presence_received(lc,lf); } lf->initial_subscribes_sent=FALSE; } diff --git a/coreapi/gitversion.cmake b/coreapi/gitversion.cmake index 1a6ec406c..5c6facdab 100644 --- a/coreapi/gitversion.cmake +++ b/coreapi/gitversion.cmake @@ -23,16 +23,17 @@ 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 GIT_VERSION \"${GIT_REVISION}\"" + 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 GIT_VERSION \"unknown\"" + COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"unknown\"" OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h ) endif() diff --git a/coreapi/help/CMakeLists.txt b/coreapi/help/CMakeLists.txt index 8f7b9b125..af624006e 100644 --- a/coreapi/help/CMakeLists.txt +++ b/coreapi/help/CMakeLists.txt @@ -26,9 +26,17 @@ 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) + file(GLOB DOC_INPUT_FILES + [^.]*.c + [^.]*.dox + ../[^.]*.h + ../[^.]*.c + ) + add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html" + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ${DOC_INPUT_FILES} + ) + add_custom_target(doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html") install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html" "${CMAKE_CURRENT_BINARY_DIR}/doc/xml" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/doc/linphone-${LINPHONE_VERSION}") else() diff --git a/coreapi/help/Doxyfile.in b/coreapi/help/Doxyfile.in index 27068c53d..12facea9b 100644 --- a/coreapi/help/Doxyfile.in +++ b/coreapi/help/Doxyfile.in @@ -34,7 +34,7 @@ DETAILS_AT_TOP = NO INHERIT_DOCS = YES DISTRIBUTE_GROUP_DOC = NO TAB_SIZE = 8 -ALIASES = +ALIASES = mslist{1}="A list of \ref \1 objects. \xmlonly \1 \endxmlonly" OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO SUBGROUPING = YES diff --git a/coreapi/help/Makefile.am b/coreapi/help/Makefile.am index 84822e51c..479d2b31d 100644 --- a/coreapi/help/Makefile.am +++ b/coreapi/help/Makefile.am @@ -1,7 +1,7 @@ EXTRA_DIST=Doxyfile.in doxygen.dox -SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h +SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h # html doc @@ -84,6 +84,7 @@ filetransfer_LDADD=$(helloworld_LDADD) AM_CFLAGS=\ -I$(top_srcdir)/coreapi \ $(STRICT_OPTIONS) \ + $(STRICT_OPTIONS_CC) \ -DIN_LINPHONE \ $(ORTP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ @@ -98,4 +99,4 @@ AM_CFLAGS=\ tutodir=$(datadir)/tutorials/linphone tuto_DATA=$(LINPHONE_TUTOS) -endif +endif diff --git a/coreapi/help/buddy_status.c b/coreapi/help/buddy_status.c index 40db6458e..cd7f13d52 100644 --- a/coreapi/help/buddy_status.c +++ b/coreapi/help/buddy_status.c @@ -1,7 +1,7 @@ /* buddy_status -Copyright (C) 2010 Belledonne Communications SARL +Copyright (C) 2010 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -73,7 +73,7 @@ static void new_subscription_requested (LinphoneCore *lc, LinphoneFriend *frien * Registration state notification callback */ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){ - printf("New registration state %s for user id [%s] at proxy [%s]\n" + printf("New registration state %s for user id [%s] at proxy [%s]" ,linphone_registration_state_to_string(cstate) ,linphone_proxy_config_get_identity(cfg) ,linphone_proxy_config_get_addr(cfg)); @@ -87,6 +87,8 @@ int main(int argc, char *argv[]){ char* identity=NULL; char* password=NULL; + LinphoneFriend* my_friend=NULL; + /* takes sip uri identity from the command line arguments */ if (argc>1){ dest_friend=argv[1]; @@ -104,7 +106,7 @@ int main(int argc, char *argv[]){ #ifdef DEBUG linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif - /* + /* Fill the LinphoneCoreVTable with application callbacks. All are optional. Here we only use the both notify_presence_received and new_subscription_requested callbacks in order to get notifications about friend status. @@ -123,11 +125,11 @@ int main(int argc, char *argv[]){ LinphoneProxyConfig* proxy_cfg = linphone_proxy_config_new(); /*parse identity*/ LinphoneAddress *from = linphone_address_new(identity); + LinphoneAuthInfo *info; if (from==NULL){ printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity); goto end; } - LinphoneAuthInfo *info; if (password!=NULL){ info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ @@ -152,7 +154,6 @@ int main(int argc, char *argv[]){ while( running && linphone_proxy_config_get_state(proxy_cfg) == LinphoneRegistrationProgress); } - LinphoneFriend* my_friend=NULL; if (dest_friend) { my_friend = linphone_friend_new_with_address(dest_friend); /*creates friend object from dest*/ diff --git a/coreapi/help/chatroom.c b/coreapi/help/chatroom.c index 51fc4a237..1f0f200a0 100644 --- a/coreapi/help/chatroom.c +++ b/coreapi/help/chatroom.c @@ -1,7 +1,7 @@ /* linphone -Copyright (C) 2010 Belledonne Communications SARL +Copyright (C) 2010 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -55,7 +55,7 @@ int main(int argc, char *argv[]){ LinphoneCoreVTable vtable={0}; char* dest_friend=NULL; - + LinphoneChatRoom* chat_room; /* takes sip uri identity from the command line arguments */ if (argc>1){ @@ -67,7 +67,7 @@ int main(int argc, char *argv[]){ #ifdef DEBUG linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif - /* + /* Fill the LinphoneCoreVTable with application callbacks. All are optional. Here we only use the text_received callback in order to get notifications about incoming message. @@ -81,7 +81,7 @@ int main(int argc, char *argv[]){ /*Next step is to create a chat root*/ - LinphoneChatRoom* chat_room = linphone_core_create_chat_room(lc,dest_friend); + chat_room = linphone_core_create_chat_room(lc,dest_friend); linphone_chat_room_send_message(chat_room,"Hello world"); /*sending message*/ diff --git a/coreapi/help/filetransfer.c b/coreapi/help/filetransfer.c index 25edc2d39..035a05597 100644 --- a/coreapi/help/filetransfer.c +++ b/coreapi/help/filetransfer.c @@ -1,7 +1,7 @@ /* linphone -Copyright (C) 2010 Belledonne Communications SARL +Copyright (C) 2010 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -48,11 +48,11 @@ static void stop(int signum){ /** * function invoked to report file transfer progress. * */ -static void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) { +static void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) { const LinphoneAddress* from_address = linphone_chat_message_get_from(message); const LinphoneAddress* to_address = linphone_chat_message_get_to(message); char *address = linphone_chat_message_is_outgoing(message)?linphone_address_as_string(to_address):linphone_address_as_string(from_address); - printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress + printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)((offset *100)/total) ,(linphone_chat_message_is_outgoing(message)?"sent":"received") , content->type , content->subtype @@ -133,7 +133,7 @@ static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneCha 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); + linphone_chat_message_start_file_download(msg, linphone_file_transfer_state_changed, NULL); } @@ -144,6 +144,10 @@ int main(int argc, char *argv[]){ const char* dest_friend=NULL; int i; const char* big_file_content="big file"; + LinphoneChatRoom* chat_room; + LinphoneContent content; + LinphoneChatMessage* chat_message; + /*seting dummy file content to something*/ for (i=0;i1){ @@ -105,7 +109,7 @@ int main(int argc, char *argv[]){ #ifdef DEBUG linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif - /* + /* Fill the LinphoneCoreVTable with application callbacks. All are optional. Here we only use the registration_state_changed callbacks in order to get notifications about the progress of the registration. @@ -118,30 +122,28 @@ int main(int argc, char *argv[]){ */ lc=linphone_core_new(&vtable,NULL,NULL,data); - LinphoneProxyConfig* proxy_cfg; /*create proxy config*/ proxy_cfg = linphone_proxy_config_new(); /*parse identity*/ - LinphoneAddress *from = linphone_address_new(identity); + from = linphone_address_new(identity); if (from==NULL){ printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity); goto end; } - LinphoneAuthInfo *info; - if (password!=NULL){ - info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ - linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ - } + if (password!=NULL){ + info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ + linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ + } - // configure proxy entries - linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/ - const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/ - linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/ - linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/ - linphone_address_destroy(from); /*release resource*/ + // configure proxy entries + linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/ + server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/ + linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/ + linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/ + linphone_address_destroy(from); /*release resource*/ - linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/ - linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/ + linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/ + linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/ i=0; /* main loop for receiving notifications and doing background linphonecore work: */ @@ -163,7 +165,7 @@ int main(int argc, char *argv[]){ linphone_proxy_config_edit(proxy_cfg); /*start editing proxy configuration*/ linphone_proxy_config_enable_register(proxy_cfg,FALSE); /*de-activate registration for this proxy config*/ linphone_proxy_config_done(proxy_cfg); /*initiate REGISTER with expire = 0*/ - + if (data->ev){ linphone_event_terminate(data->ev); } diff --git a/coreapi/help/registration.c b/coreapi/help/registration.c index 70ab4f4ca..8dbab6440 100644 --- a/coreapi/help/registration.c +++ b/coreapi/help/registration.c @@ -1,7 +1,7 @@ /* linphone -Copyright (C) 2010 Belledonne Communications SARL +Copyright (C) 2010 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -60,9 +60,13 @@ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyCo LinphoneCore *lc; int main(int argc, char *argv[]){ LinphoneCoreVTable vtable={0}; + LinphoneProxyConfig* proxy_cfg; + LinphoneAddress *from; + LinphoneAuthInfo *info; char* identity=NULL; char* password=NULL; + const char* server_addr; /* takes sip uri identity from the command line arguments */ if (argc>1){ @@ -79,7 +83,7 @@ int main(int argc, char *argv[]){ #ifdef DEBUG linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif - /* + /* Fill the LinphoneCoreVTable with application callbacks. All are optional. Here we only use the registration_state_changed callbacks in order to get notifications about the progress of the registration. @@ -91,30 +95,28 @@ int main(int argc, char *argv[]){ */ lc=linphone_core_new(&vtable,NULL,NULL,NULL); - LinphoneProxyConfig* proxy_cfg; /*create proxy config*/ proxy_cfg = linphone_proxy_config_new(); /*parse identity*/ - LinphoneAddress *from = linphone_address_new(identity); + from = linphone_address_new(identity); if (from==NULL){ printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity); goto end; } - LinphoneAuthInfo *info; - if (password!=NULL){ - info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ - linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ - } - - // configure proxy entries - linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/ - const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/ - linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/ - linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/ - linphone_address_destroy(from); /*release resource*/ - - linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/ - linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/ + if (password!=NULL){ + info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ + linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ + } + + // configure proxy entries + linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/ + server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/ + linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/ + linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/ + linphone_address_destroy(from); /*release resource*/ + + linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/ + linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/ /* main loop for receiving notifications and doing background linphonecore work: */ diff --git a/coreapi/info.c b/coreapi/info.c index 2bf2b85ad..ad8cd1f8e 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -192,8 +192,7 @@ void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1); info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); if (body) linphone_content_copy_from_sal_body(&info->content,body); - if (lc->vtable.info_received) - lc->vtable.info_received(lc,call,info); + linphone_core_notify_info_received(lc,call,info); linphone_info_message_destroy(info); } } diff --git a/coreapi/ldap/ldapprovider.c b/coreapi/ldap/ldapprovider.c index f9a4add67..75b6b19a1 100644 --- a/coreapi/ldap/ldapprovider.c +++ b/coreapi/ldap/ldapprovider.c @@ -567,10 +567,11 @@ LinphoneLDAPContactProvider*linphone_ldap_contact_provider_create(LinphoneCore* belle_sip_object_unref(obj); obj = NULL; } else { + int ret; linphone_dictionary_foreach( config, linphone_ldap_contact_provider_config_dump_cb, 0 ); linphone_ldap_contact_provider_loadconfig(obj, config); - int ret = ldap_initialize(&(obj->ld),obj->server); + ret = ldap_initialize(&(obj->ld),obj->server); if( ret != LDAP_SUCCESS ){ ms_error( "Problem initializing ldap on url '%s': %s", obj->server, ldap_err2string(ret)); @@ -617,9 +618,10 @@ static int linphone_ldap_request_entry_compare_strong(const void*a, const void* static inline LinphoneLDAPContactSearch* linphone_ldap_contact_provider_request_search( LinphoneLDAPContactProvider* obj, int msgid ) { LinphoneLDAPContactSearch dummy = {}; + MSList* list_entry; dummy.msgid = msgid; - MSList* list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy); + list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy); if( list_entry ) return list_entry->data; else return NULL; } @@ -680,13 +682,14 @@ static LinphoneLDAPContactSearch* linphone_ldap_contact_provider_begin_search ( void* cb_data ) { bool_t connected = obj->connected; + LinphoneLDAPContactSearch* request; // if we're not yet connected, bind if( !connected ) { if( !obj->bind_thread ) linphone_ldap_contact_provider_bind(obj); } - LinphoneLDAPContactSearch* request = linphone_ldap_contact_search_create( obj, predicate, cb, cb_data ); + request = linphone_ldap_contact_search_create( obj, predicate, cb, cb_data ); if( connected ){ int ret = linphone_ldap_contact_provider_perform_search(obj, request); @@ -711,6 +714,7 @@ static LinphoneLDAPContactSearch* linphone_ldap_contact_provider_begin_search ( static int linphone_ldap_contact_provider_marshal(LinphoneLDAPContactProvider* obj, char* buff, size_t buff_size, size_t *offset) { belle_sip_error_code error = BELLE_SIP_OK; + char **attr; error = belle_sip_snprintf(buff, buff_size, offset, "ld:%p,\n", obj->ld); if(error!= BELLE_SIP_OK) return error; @@ -741,7 +745,7 @@ static int linphone_ldap_contact_provider_marshal(LinphoneLDAPContactProvider* o obj->sip_attr, obj->name_attr); if(error!= BELLE_SIP_OK) return error; - char **attr = obj->attributes; + attr = obj->attributes; while( *attr ){ error = belle_sip_snprintf(buff, buff_size, offset, "- %s\n", *attr); if(error!= BELLE_SIP_OK) return error; diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc index 2e77bbd95..beabd43a8 100644 --- a/coreapi/linphone_tunnel.cc +++ b/coreapi/linphone_tunnel.cc @@ -29,14 +29,15 @@ #include "private.h" #include "lpconfig.h" -LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){ +static const char *_tunnel_mode_str[3] = { "disable", "enable", "auto" }; + +LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){ return lc->tunnel; } struct _LinphoneTunnel { belledonnecomm::TunnelManager *manager; MSList *config_list; - bool_t auto_detect_enabled; }; extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){ @@ -45,16 +46,19 @@ extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){ return tunnel; } -static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnel *tunnel){ +belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel){ return tunnel->manager; } -static inline _LpConfig *config(LinphoneTunnel *tunnel){ +static inline _LpConfig *config(const LinphoneTunnel *tunnel){ return tunnel->manager->getLinphoneCore()->config; } void linphone_tunnel_destroy(LinphoneTunnel *tunnel){ delete tunnel->manager; + + ms_list_free_with_data(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy); + ms_free(tunnel); } @@ -100,12 +104,12 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str) break; case 3: delay = atoi(pch); - break; + break; default: // Abort pos = 0; break; - + } ++pos; pch = strtok(NULL, ":"); @@ -121,12 +125,12 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str) if(pos == 4) { linphone_tunnel_config_set_delay(tunnel_config, delay); } - ms_free(dstr); + ms_free(dstr); return tunnel_config; } -static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) { +static void linphone_tunnel_save_config(const LinphoneTunnel *tunnel) { MSList *elem = NULL; char *tmp = NULL, *old_tmp = NULL, *tc_str = NULL; for(elem = tunnel->config_list; elem != NULL; elem = elem->next) { @@ -152,12 +156,12 @@ static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) { static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) { if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) == -1) { - bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), + bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), linphone_tunnel_config_get_port(tunnel_config)); } else { - bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), - linphone_tunnel_config_get_port(tunnel_config), - linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), + linphone_tunnel_config_get_port(tunnel_config), + linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), linphone_tunnel_config_get_delay(tunnel_config)); } tunnel->config_list = ms_list_append(tunnel->config_list, tunnel_config); @@ -209,38 +213,37 @@ void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig MSList *elem = ms_list_find(tunnel->config_list, tunnel_config); if(elem != NULL) { tunnel->config_list = ms_list_remove(tunnel->config_list, tunnel_config); - linphone_tunnel_config_destroy(tunnel_config); + linphone_tunnel_config_destroy(tunnel_config); linphone_tunnel_refresh_config(tunnel); linphone_tunnel_save_config(tunnel); - } + } } -const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ +const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel){ return tunnel->config_list; } void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){ bcTunnel(tunnel)->cleanServers(); - + /* Free the list */ - ms_list_for_each(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy); - tunnel->config_list = ms_list_free(tunnel->config_list); - + ms_list_free_with_data(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy); + tunnel->config_list = NULL; + linphone_tunnel_save_config(tunnel); } -void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){ - tunnel->auto_detect_enabled = FALSE; - lp_config_set_int(config(tunnel),"tunnel","enabled",(int)enabled); - bcTunnel(tunnel)->enable(enabled); +void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode){ + lp_config_set_string(config(tunnel),"tunnel","mode", tunnel_mode_to_string(mode)); + bcTunnel(tunnel)->setMode(mode); } -bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){ - return bcTunnel(tunnel)->isEnabled(); +LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel){ + return bcTunnel(tunnel)->getMode(); } -bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){ - return bcTunnel(tunnel)->isReady(); +bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){ + return bcTunnel(tunnel)->isConnected(); } static OrtpLogFunc tunnelOrtpLogHandler=NULL; @@ -316,27 +319,65 @@ void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){ bcTunnel(tunnel)->reconnect(); } -void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){ - tunnel->auto_detect_enabled = TRUE; - bcTunnel(tunnel)->autoDetect(); +void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable) { + bcTunnel(tunnel)->tunnelizeSipPackets(enable); + lp_config_set_int(config(tunnel), "tunnel", "sip", (enable ? TRUE : FALSE)); } -bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) { - return tunnel->auto_detect_enabled; +bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) { + return bcTunnel(tunnel)->tunnelizeSipPacketsEnabled() ? TRUE : FALSE; } static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){ ortp_logv(level,fmt,args); } +LinphoneTunnelMode string_to_tunnel_mode(const char *string) { + if(string != NULL) { + int i; + for(i=0; i<3 && strcmp(string, _tunnel_mode_str[i]) != 0; i++); + if(i<3) { + return (LinphoneTunnelMode)i; + } else { + ms_error("Invalid tunnel mode '%s'", string); + return LinphoneTunnelModeDisable; + } + } else { + return LinphoneTunnelModeDisable; + } +} + +const char *tunnel_mode_to_string(LinphoneTunnelMode mode) { + return _tunnel_mode_str[mode]; +} + /** * Startup tunnel using configuration. * Called internally from linphonecore at startup. */ void linphone_tunnel_configure(LinphoneTunnel *tunnel){ - bool_t enabled=(bool_t)lp_config_get_int(config(tunnel),"tunnel","enabled",FALSE); + LinphoneTunnelMode mode = string_to_tunnel_mode(lp_config_get_string(config(tunnel), "tunnel", "mode", NULL)); + bool_t tunnelizeSIPPackets = (bool_t)lp_config_get_int(config(tunnel), "tunnel", "sip", TRUE); linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv); linphone_tunnel_load_config(tunnel); - linphone_tunnel_enable(tunnel, enabled); + linphone_tunnel_enable_sip(tunnel, tunnelizeSIPPackets); + linphone_tunnel_set_mode(tunnel, mode); +} + +/* Deprecated functions */ +void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled) { + if(enabled) linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeEnable); + else linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeDisable); } +bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel) { + return linphone_tunnel_get_mode(tunnel) == LinphoneTunnelModeEnable; +} + +void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel) { + linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeAuto); +} + +bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) { + return linphone_tunnel_get_mode(tunnel) == LinphoneTunnelModeAuto; +} diff --git a/coreapi/linphone_tunnel.h b/coreapi/linphone_tunnel.h index 336351267..8bf94fcef 100644 --- a/coreapi/linphone_tunnel.h +++ b/coreapi/linphone_tunnel.h @@ -50,6 +50,30 @@ extern "C" typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig; +/** + * Enum describing the tunnel modes. +**/ +typedef enum _LinphoneTunnelMode { + LinphoneTunnelModeDisable, /**< The tunnel is disabled. */ + LinphoneTunnelModeEnable, /**< The tunnel is enabled. */ + LinphoneTunnelModeAuto /**< The tunnel is enabled automatically if it is required. */ +} LinphoneTunnelMode; + +/** + * @brief Convert a string into LinphoneTunnelMode enum + * @param string String to convert + * @return An LinphoneTunnelMode enum. If the passed string is NULL or + * does not match with any mode, the LinphoneTunnelModeDisable is returned. + */ +LINPHONE_PUBLIC LinphoneTunnelMode string_to_tunnel_mode(const char *string); + +/** + * @brief Convert a tunnel mode enum into string + * @param mode Enum to convert + * @return "disable", "enable" or "auto" + */ +LINPHONE_PUBLIC const char *tunnel_mode_to_string(LinphoneTunnelMode mode); + /** * Create a new tunnel configuration */ @@ -131,51 +155,49 @@ LINPHONE_PUBLIC void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel LINPHONE_PUBLIC void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config); /** - * Remove tunnel server configuration - * + * @brief Remove tunnel server configuration * @param tunnel object * @param tunnel_config object */ LINPHONE_PUBLIC void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config); /** - * @param tunnel object - * returns a string of space separated list of host:port of tunnel server addresses - * */ -LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel); + * @brief Get added servers + * @param tunnel A LinphoneTunnel object + * @return A list of LinphoneTunnelConfig objects + */ +LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel); /** - * @param tunnel object - * Removes all tunnel server address previously entered with addServer() + * @brief Removes all tunnel server address previously entered with addServer() + * @param tunnel A LinphoneTunnel object **/ LINPHONE_PUBLIC void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel); /** - * Sets whether tunneling of SIP and RTP is required. + * @brief Set tunnel mode + * The tunnel mode can be 'enable', 'disable' or 'auto' + * If the mode is set to 'auto', the tunnel manager will try to established an RTP session + * with the tunnel server on the UdpMirrorPort. If the connection fail, the tunnel is automatically + * activated whereas the tunnel is automatically disabled if the connection succeed. * @param tunnel object - * @param enabled If true enter in tunneled mode, if false exits from tunneled mode. - * The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode. - * + * @param mode See #LinphoneTunnelMode **/ -LINPHONE_PUBLIC void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled); +LINPHONE_PUBLIC void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode); /** - * @param tunnel object - * Returns a boolean indicating whether tunneled operation is enabled. + * @brief Get the tunnel mode + * @param tunnel A LinphoneTunnel object + * @return Return a #LinphoneTunnelMode enumeration **/ -LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel); +LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel); /** - * @param tunnel object - * Returns a boolean indicating whether tunnel is connected successfully. + * @brief Check whether the tunnel is connected + * @param tunnel LinphoneTunnel object + * @return True if the tunnel is connected **/ -bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel); - -/** - * @param tunnel object - * Returns a boolean indicating whether tunnel is connected successfully. -**/ -bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel); +LINPHONE_PUBLIC bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel); /** * @param tunnel object @@ -187,20 +209,18 @@ bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel); LINPHONE_PUBLIC void linphone_tunnel_reconnect(LinphoneTunnel *tunnel); /** - * Start tunnel need detection. - * @param tunnel object - * In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port. - *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on. - *
Call this method each time to run the auto detection algorithm + * @brief Set whether SIP packets must be directly sent to a UA or pass through the tunnel + * @param tunnel Tunnel to configure + * @param enable If true, SIP packets shall pass through the tunnel */ -LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel); +LINPHONE_PUBLIC void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable); /** - * Tells whether tunnel auto detection is enabled. - * @param[in] tunnel LinphoneTunnel object. - * @return TRUE if auto detection is enabled, FALSE otherwise. + * @brief Check whether tunnel is set to transport SIP packets + * @param tunnel Tunnel to check + * @return True, SIP packets shall pass through through tunnel */ -LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel); +LINPHONE_PUBLIC bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel); /** * Set an optional http proxy to go through when connecting to tunnel server. @@ -222,8 +242,49 @@ LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, cons **/ LINPHONE_PUBLIC void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd); +/** + * @brief Set authentication info for the http proxy + * @param tunnel LinphoneTunnel object + * @param username User name + * @param passwd Password + */ LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd); +/** + * @deprecated Replaced by linphone_tunnel_set_mode() + * @brief Sets whether tunneling of SIP and RTP is required. + * @param tunnel object + * @param enabled If true enter in tunneled mode, if false exits from tunneled mode. + * The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode. + * +**/ +LINPHONE_PUBLIC void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled); + +/** + * @deprecated Replaced by linphone_tunnel_get_mode() + * @brief Check whether tunnel is enabled + * @param tunnel Tunnel object + * @return Returns a boolean indicating whether tunneled operation is enabled. +**/ +LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel); + +/** + * @deprecated Replaced by linphone_tunnel_set_mode(LinphoneTunnelModeAuto) + * @brief Start tunnel need detection. + * @param tunnel object + * In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port. + *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on. + *
Call this method each time to run the auto detection algorithm + */ +LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel); + +/** + * @deprecated Replaced by linphone_tunnel_get_mode() + * @brief Tells whether tunnel auto detection is enabled. + * @param[in] tunnel LinphoneTunnel object. + * @return TRUE if auto detection is enabled, FALSE otherwise. + */ +LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel); /** * @} diff --git a/coreapi/linphone_tunnel_stubs.c b/coreapi/linphone_tunnel_stubs.c index c208dd249..72693463b 100644 --- a/coreapi/linphone_tunnel_stubs.c +++ b/coreapi/linphone_tunnel_stubs.c @@ -29,7 +29,7 @@ #include "lpconfig.h" -LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){ +LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){ return lc->tunnel; } @@ -45,21 +45,21 @@ void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tu void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){ } -const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ +const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel){ return NULL; } void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){ } -void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){ +void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode) { } -bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){ - return FALSE; +LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel){ + return LinphoneTunnelModeDisable; } -bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){ +bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){ return FALSE; } @@ -79,9 +79,14 @@ void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){ } -void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){ -} - void linphone_tunnel_configure(LinphoneTunnel *tunnel){ } +void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable) {} +bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) { return FALSE; } + +/* Deprecated functions */ +void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled) {} +bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel) { return FALSE; } +void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel) {} +bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) { return FALSE; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index c650894b3..7608c47ba 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -37,6 +37,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mediastreamer2/mseventqueue.h" #include "mediastreamer2/mssndcard.h" +static const char EC_STATE_STORE[] = ".linphone.ecstate"; + static void linphone_call_stats_uninit(LinphoneCallStats *stats); #ifdef VIDEO_ENABLED @@ -151,17 +153,14 @@ static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) { } static void propagate_encryption_changed(LinphoneCall *call){ - LinphoneCore *lc=call->core; if (!linphone_call_all_streams_encrypted(call)) { ms_message("Some streams are not encrypted"); - call->current_params.media_encryption=LinphoneMediaEncryptionNone; - if (lc->vtable.call_encryption_changed) - lc->vtable.call_encryption_changed(call->core, call, FALSE, call->auth_token); + call->current_params->media_encryption=LinphoneMediaEncryptionNone; + linphone_core_notify_call_encryption_changed(call->core, call, FALSE, call->auth_token); } else { ms_message("All streams are encrypted"); - call->current_params.media_encryption=LinphoneMediaEncryptionZRTP; - if (lc->vtable.call_encryption_changed) - lc->vtable.call_encryption_changed(call->core, call, TRUE, call->auth_token); + call->current_params->media_encryption=LinphoneMediaEncryptionZRTP; + linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token); } } @@ -171,9 +170,9 @@ static void linphone_call_audiostream_encryption_changed(void *data, bool_t encr call = (LinphoneCall *)data; - if (encrypted && call->core->vtable.display_status != NULL) { + if (encrypted) { snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token); - call->core->vtable.display_status(call->core, status); + linphone_core_notify_display_status(call->core, status); } propagate_encryption_changed(call); @@ -236,6 +235,14 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw for(it=codecs;it!=NULL;it=it->next){ PayloadType *pt=(PayloadType*)it->data; if (pt->flags & PAYLOAD_TYPE_ENABLED){ + int sample_rate = payload_type_get_rate(pt); + + if( strcasecmp("G722",pt->mime_type) == 0 ){ + /* G722 spec says 8000 but the codec actually requires 16000 */ + ms_debug("Correcting sample rate for G722"); + sample_rate = 16000; + } + if (bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,bandwidth_limit)){ ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s", pt->mime_type,pt->clock_rate,bandwidth_limit); @@ -244,7 +251,7 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw if (linphone_core_check_payload_type_usability(lc,pt)){ l=ms_list_append(l,payload_type_clone(pt)); nb++; - if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt); + if (max_sample_rate && sample_rate>*max_sample_rate) *max_sample_rate=sample_rate; } } if ((nb_codecs_limit > 0) && (nb >= nb_codecs_limit)) break; @@ -305,7 +312,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){ for(i=0; inb_streams; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) { - if (keep_srtp_keys && old_md && sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE){ + if (keep_srtp_keys && old_md && (sal_stream_description_active(&old_md->streams[i]) == TRUE) && (sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE)) { int j; ms_message("Keeping same crypto keys."); for(j=0;jstreams[i])) continue; for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) { pt = (PayloadType *)pt_it->data; - if (call->params.avpf_enabled == TRUE) { + if (call->params->avpf_enabled == TRUE) { payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); avpf_params = payload_type_get_avpf_params(pt); - avpf_params.trr_interval = call->params.avpf_rr_interval; + avpf_params.trr_interval = call->params->avpf_rr_interval; } else { payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); memset(&avpf_params, 0, sizeof(avpf_params)); @@ -348,20 +355,20 @@ static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) { LinphoneCore *lc = call->core; int i; - md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 0); + md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 1); if (md->rtcp_xr.enabled == TRUE) { - const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "none"); + const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "all"); if (strcasecmp(rcvr_rtt_mode, "all") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll; else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttSender; else md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttNone; if (md->rtcp_xr.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) { - md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 0); + md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000); } - md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 0); + md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 1); if (md->rtcp_xr.stat_summary_enabled == TRUE) { md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL; } - md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 0); + md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1); } for (i = 0; i < md->nb_streams; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; @@ -374,13 +381,6 @@ void linphone_call_increment_local_media_description(LinphoneCall *call){ md->session_ver++; } -static SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) { - if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf; - if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp; - if (params->avpf_enabled) return SalProtoRtpAvpf; - return SalProtoRtpAvp; -} - void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){ MSList *l; PayloadType *pt; @@ -391,9 +391,9 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * SalMediaDescription *md=sal_media_description_new(); LinphoneAddress *addr; char* local_ip=call->localip; - const char *subject=linphone_call_params_get_session_name(&call->params); + const char *subject=linphone_call_params_get_session_name(call->params); - linphone_core_adapt_to_network(lc,call->ping_time,&call->params); + linphone_core_adapt_to_network(lc,call->ping_time,call->params); if (call->dest_proxy) me=linphone_proxy_config_get_identity(call->dest_proxy); @@ -409,8 +409,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username)); if (subject) strncpy(md->name,subject,sizeof(md->name)); - if (call->params.down_bw) - md->bandwidth=call->params.down_bw; + if (call->params->down_bw) + md->bandwidth=call->params->down_bw; else md->bandwidth=linphone_core_get_download_bandwidth(lc); /*set audio capabilities */ @@ -419,19 +419,19 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * strncpy(md->streams[0].name,"Audio",sizeof(md->streams[0].name)-1); md->streams[0].rtp_port=call->media_ports[0].rtp_port; md->streams[0].rtcp_port=call->media_ports[0].rtcp_port; - md->streams[0].proto=get_proto_from_call_params(&call->params); + md->streams[0].proto=get_proto_from_call_params(call->params); md->streams[0].type=SalAudio; - if (call->params.down_ptime) - md->streams[0].ptime=call->params.down_ptime; + if (call->params->down_ptime) + md->streams[0].ptime=call->params->down_ptime; else md->streams[0].ptime=linphone_core_get_download_ptime(lc); - l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate,-1); + l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params->audio_bw,&md->streams[0].max_rate,-1); pt=payload_type_clone(rtp_profile_get_payload_from_mime(lc->default_profile,"telephone-event")); l=ms_list_append(l,pt); md->streams[0].payloads=l; nb_active_streams++; - if (call->params.has_video){ + if (call->params->has_video){ strncpy(md->streams[1].rtp_addr,local_ip,sizeof(md->streams[1].rtp_addr)); strncpy(md->streams[1].rtcp_addr,local_ip,sizeof(md->streams[1].rtcp_addr)); strncpy(md->streams[1].name,"Video",sizeof(md->streams[1].name)-1); @@ -562,15 +562,12 @@ static void port_config_set(LinphoneCall *call, int stream_index, int min_port, static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){ int min_port, max_port; ms_message("New LinphoneCall [%p] initialized (LinphoneCore version: %s)",call,linphone_core_get_version()); - call->magic=linphone_call_magic; - call->refcnt=1; call->state=LinphoneCallIdle; call->transfer_state = LinphoneCallIdle; - call->media_start_time=0; - call->log=linphone_call_log_new(call, from, to); - call->owns_call_log=TRUE; + call->log=linphone_call_log_new(call->dir, from, to); call->camera_enabled=TRUE; - call->current_params.media_encryption=LinphoneMediaEncryptionNone; + call->current_params = linphone_call_params_new(); + call->current_params->media_encryption=LinphoneMediaEncryptionNone; linphone_core_get_audio_port_range(call->core, &min_port, &max_port); port_config_set(call,0,min_port,max_port); @@ -612,11 +609,11 @@ void linphone_call_create_op(LinphoneCall *call){ if (call->op) sal_op_release(call->op); call->op=sal_op_new(call->core->sal); sal_op_set_user_pointer(call->op,call); - if (call->params.referer) - sal_call_set_referer(call->op,call->params.referer->op); - linphone_configure_op(call->core,call->op,call->log->to,call->params.custom_headers,FALSE); - if (call->params.privacy != LinphonePrivacyDefault) - sal_op_set_privacy(call->op,(SalPrivacyMask)call->params.privacy); + if (call->params->referer) + sal_call_set_referer(call->op,call->params->referer->op); + linphone_configure_op(call->core,call->op,call->log->to,call->params->custom_headers,FALSE); + if (call->params->privacy != LinphonePrivacyDefault) + sal_op_set_privacy(call->op,(SalPrivacyMask)call->params->privacy); /*else privacy might be set by proxy */ } @@ -639,21 +636,70 @@ static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, Linphon }else call->af=AF_INET; } +/** + * Fill the local ip that routes to the internet according to the destination, or guess it by other special means (upnp). + */ +static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr){ + const char *ip; + int af = call->af; + const char *dest = NULL; + if (call->dest_proxy == NULL) { + struct addrinfo hints; + struct addrinfo *res = NULL; + int err; + const char *domain = linphone_address_get_domain(remote_addr); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICHOST; + err = getaddrinfo(domain, NULL, &hints, &res); + if (err == 0) { + dest = domain; + } + if (res != NULL) freeaddrinfo(res); + } + if (_linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress + && (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){ + strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE); + return; + } +#ifdef BUILD_UPNP + else if (call->core->upnp != NULL && linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseUpnp && + linphone_upnp_context_get_state(call->core->upnp) == LinphoneUpnpStateOk) { + ip = linphone_upnp_context_get_external_ipaddress(call->core->upnp); + strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE); + return; + } +#endif //BUILD_UPNP + linphone_core_get_local_ip(call->core, af, dest, call->localip); +} + +static void linphone_call_destroy(LinphoneCall *obj); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCall); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCall, belle_sip_object_t, + (belle_sip_object_destroy_t)linphone_call_destroy, + NULL, // clone + NULL, // marshal + FALSE +); + LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){ - LinphoneCall *call=ms_new0(LinphoneCall,1); + LinphoneCall *call = belle_sip_object_new(LinphoneCall); call->dir=LinphoneCallOutgoing; call->core=lc; linphone_call_outgoing_select_ip_version(call,to,cfg); - linphone_core_get_local_ip(lc,call->af,call->localip); + linphone_call_get_local_ip(call, to); linphone_call_init_common(call,from,to); - _linphone_call_params_copy(&call->params,params); + call->params = linphone_call_params_copy(params); - if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { + if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { call->ice_session = ice_session_new(); ice_session_set_role(call->ice_session, IR_Controlling); } - if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) { + if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) { call->ping_time=linphone_core_run_stun_tests(call->core,call); } #ifdef BUILD_UPNP @@ -683,24 +729,24 @@ static void linphone_call_incoming_select_ip_version(LinphoneCall *call){ * Fix call parameters on incoming call to eg. enable AVPF if the incoming call propose it and it is not enabled locally. */ void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, const SalMediaDescription *md) { - call->params.has_video &= linphone_core_media_description_contains_video_stream(md); + call->params->has_video &= linphone_core_media_description_contains_video_stream(md); /* Handle AVPF and SRTP. */ - call->params.avpf_enabled = sal_media_description_has_avpf(md); - if (call->params.avpf_enabled == TRUE) { + call->params->avpf_enabled = sal_media_description_has_avpf(md); + if (call->params->avpf_enabled == TRUE) { if (call->dest_proxy != NULL) { - call->params.avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000; + call->params->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000; } else { - call->params.avpf_rr_interval = 5000; + call->params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(call->core)*1000; } } if ((sal_media_description_has_srtp(md) == TRUE) && (media_stream_srtp_supported() == TRUE)) { - call->params.media_encryption = LinphoneMediaEncryptionSRTP; + call->params->media_encryption = LinphoneMediaEncryptionSRTP; } } LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){ - LinphoneCall *call=ms_new0(LinphoneCall,1); + LinphoneCall *call = belle_sip_object_new(LinphoneCall); const SalMediaDescription *md; LinphoneFirewallPolicy fpol; @@ -731,27 +777,28 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro } linphone_address_clean(from); - linphone_core_get_local_ip(lc,call->af,call->localip); + linphone_call_get_local_ip(call, from); linphone_call_init_common(call, from, to); + call->params = linphone_call_params_new(); call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/ call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to); - linphone_core_init_default_params(lc, &call->params); + linphone_core_init_default_params(lc, call->params); /* * Initialize call parameters according to incoming call parameters. This is to avoid to ask later (during reINVITEs) for features that the remote * end apparently does not support. This features are: privacy, video */ /*set privacy*/ - call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); + call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); /*set video support */ md=sal_call_get_remote_media_description(op); - call->params.has_video = lc->video_policy.automatically_accept; + call->params->has_video = linphone_core_video_enabled(lc) && lc->video_policy.automatically_accept; if (md) { // It is licit to receive an INVITE without SDP // In this case WE chose the media parameters according to policy. linphone_call_set_compatible_incoming_call_parameters(call, md); } - fpol=linphone_core_get_firewall_policy(call->core); + fpol=_linphone_core_get_firewall_policy(call->core); /*create the ice session now if ICE is required*/ if (fpol==LinphonePolicyUseIce){ if (md){ @@ -810,7 +857,6 @@ static void linphone_call_set_terminated(LinphoneCall *call){ linphone_core_update_allocated_audio_bandwidth(lc); linphone_call_stats_uninit(&call->stats[0]); linphone_call_stats_uninit(&call->stats[1]); - call->owns_call_log=FALSE; linphone_call_log_completed(call); @@ -831,10 +877,10 @@ static void linphone_call_set_terminated(LinphoneCall *call){ } void linphone_call_fix_call_parameters(LinphoneCall *call){ - call->params.has_video=call->current_params.has_video; + call->params->has_video=call->current_params->has_video; - if (call->params.media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/ - call->params.media_encryption=call->current_params.media_encryption; + if (call->params->media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/ + call->params->media_encryption=call->current_params->media_encryption; } const char *linphone_call_state_to_string(LinphoneCallState cs){ @@ -877,11 +923,19 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){ return "LinphoneCallUpdating"; case LinphoneCallReleased: return "LinphoneCallReleased"; + case LinphoneCallEarlyUpdatedByRemote: + return "LinphoneCallEarlyUpdatedByRemote"; + case LinphoneCallEarlyUpdating: + return "LinphoneCallEarlyUpdating"; } return "undefined state"; } -void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){ +void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message) { + linphone_call_set_state_base(call, cstate, message,FALSE); +} + +void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate, const char *message,bool_t silently){ LinphoneCore *lc=call->core; if (call->state!=cstate){ @@ -917,11 +971,11 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const } if (cstate == LinphoneCallConnected) { call->log->status=LinphoneCallSuccess; - call->media_start_time=time(NULL); + call->log->connected_date_time=time(NULL); } - if (lc->vtable.call_state_changed) - lc->vtable.call_state_changed(lc,call,cstate,message); + if (!silently) + linphone_core_notify_call_state_changed(lc,call,cstate,message); linphone_reporting_call_state_updated(call); @@ -983,15 +1037,17 @@ static void linphone_call_destroy(LinphoneCall *obj) if (obj->transfer_target){ linphone_call_unref(obj->transfer_target); } - if (obj->owns_call_log) - linphone_call_log_destroy(obj->log); + if (obj->log) + linphone_call_log_unref(obj->log); if (obj->auth_token) { ms_free(obj->auth_token); } - linphone_call_params_uninit(&obj->params); - linphone_call_params_uninit(&obj->current_params); + linphone_call_params_unref(obj->params); + linphone_call_params_unref(obj->current_params); + if (obj->remote_params != NULL) { + linphone_call_params_unref(obj->remote_params); + } sal_error_info_reset(&obj->non_op_error); - ms_free(obj); } /** @@ -999,27 +1055,13 @@ static void linphone_call_destroy(LinphoneCall *obj) * @{ **/ -/** - * Increments the call 's reference count. - * An application that wishes to retain a pointer to call object - * must use this function to unsure the pointer remains - * valid. Once the application no more needs this pointer, - * it must call linphone_call_unref(). -**/ LinphoneCall * linphone_call_ref(LinphoneCall *obj){ - obj->refcnt++; + belle_sip_object_ref(obj); return obj; } -/** - * Decrements the call object reference count. - * See linphone_call_ref(). -**/ void linphone_call_unref(LinphoneCall *obj){ - obj->refcnt--; - if (obj->refcnt==0){ - linphone_call_destroy(obj); - } + belle_sip_object_unref(obj); } /** @@ -1029,35 +1071,35 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){ #ifdef VIDEO_ENABLED VideoStream *vstream; #endif - MS_VIDEO_SIZE_ASSIGN(call->current_params.sent_vsize, UNKNOWN); - MS_VIDEO_SIZE_ASSIGN(call->current_params.recv_vsize, UNKNOWN); + MS_VIDEO_SIZE_ASSIGN(call->current_params->sent_vsize, UNKNOWN); + MS_VIDEO_SIZE_ASSIGN(call->current_params->recv_vsize, UNKNOWN); #ifdef VIDEO_ENABLED vstream = call->videostream; if (vstream != NULL) { - call->current_params.sent_vsize = video_stream_get_sent_video_size(vstream); - call->current_params.recv_vsize = video_stream_get_received_video_size(vstream); - call->current_params.sent_fps = video_stream_get_sent_framerate(vstream); - call->current_params.received_fps = video_stream_get_received_framerate(vstream); + call->current_params->sent_vsize = video_stream_get_sent_video_size(vstream); + call->current_params->recv_vsize = video_stream_get_received_video_size(vstream); + call->current_params->sent_fps = video_stream_get_sent_framerate(vstream); + call->current_params->received_fps = video_stream_get_received_framerate(vstream); } #endif if (linphone_call_all_streams_encrypted(call)) { if (linphone_call_get_authentication_token(call)) { - call->current_params.media_encryption=LinphoneMediaEncryptionZRTP; + call->current_params->media_encryption=LinphoneMediaEncryptionZRTP; } else { - call->current_params.media_encryption=LinphoneMediaEncryptionSRTP; + call->current_params->media_encryption=LinphoneMediaEncryptionSRTP; } } else { - call->current_params.media_encryption=LinphoneMediaEncryptionNone; + call->current_params->media_encryption=LinphoneMediaEncryptionNone; } - call->current_params.avpf_enabled = linphone_call_all_streams_avpf_enabled(call); - if (call->current_params.avpf_enabled == TRUE) { - call->current_params.avpf_rr_interval = linphone_call_get_avpf_rr_interval(call); + call->current_params->avpf_enabled = linphone_call_all_streams_avpf_enabled(call); + if (call->current_params->avpf_enabled == TRUE) { + call->current_params->avpf_rr_interval = linphone_call_get_avpf_rr_interval(call); } else { - call->current_params.avpf_rr_interval = 0; + call->current_params->avpf_rr_interval = 0; } - return &call->current_params; + return call->current_params; } /** @@ -1067,10 +1109,12 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){ * supports video, encryption or whatever. **/ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){ - LinphoneCallParams *cp=&call->remote_params; - memset(cp,0,sizeof(*cp)); if (call->op){ - SalMediaDescription *md=sal_call_get_remote_media_description(call->op); + LinphoneCallParams *cp; + SalMediaDescription *md; + if (call->remote_params != NULL) linphone_call_params_unref(call->remote_params); + cp = call->remote_params = linphone_call_params_new(); + md=sal_call_get_remote_media_description(call->op); if (md) { SalStreamDescription *sd; unsigned int i; @@ -1093,7 +1137,7 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){ } if (md->name[0]!='\0') linphone_call_params_set_session_name(cp,md->name); } - cp->custom_headers=(SalCustomHeader*)sal_op_get_recv_custom_header(call->op); + cp->custom_headers=sal_custom_header_clone((SalCustomHeader*)sal_op_get_recv_custom_header(call->op)); return cp; } return NULL; @@ -1140,27 +1184,26 @@ const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call){ } /** - * Get the user_pointer in the LinphoneCall + * Get the user pointer associated with the LinphoneCall * * @ingroup call_control - * - * return user_pointer an opaque user pointer that can be retrieved at any time + * @return an opaque user pointer that can be retrieved at any time **/ -void *linphone_call_get_user_pointer(LinphoneCall *call) +void *linphone_call_get_user_data(const LinphoneCall *call) { - return call->user_pointer; + return call->user_data; } /** - * Set the user_pointer in the LinphoneCall + * Set the user pointer associated with the LinphoneCall * * @ingroup call_control * - * the user_pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall + * the user pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall **/ -void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer) +void linphone_call_set_user_data(LinphoneCall *call, void *user_pointer) { - call->user_pointer = user_pointer; + call->user_data = user_pointer; } /** @@ -1240,8 +1283,8 @@ bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){ * Returns call's duration in seconds. **/ int linphone_call_get_duration(const LinphoneCall *call){ - if (call->media_start_time==0) return 0; - return time(NULL)-call->media_start_time; + if (call->log->connected_date_time==0) return 0; + return time(NULL)-call->log->connected_date_time; } /** @@ -1304,7 +1347,6 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){ return ms_filter_call_method(call->videostream->jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file); } ms_warning("Cannot take snapshot: no currently running video stream on this call."); - return -1; #endif return -1; } @@ -1334,194 +1376,6 @@ bool_t linphone_call_camera_enabled (const LinphoneCall *call){ return call->camera_enabled; } -/** - * Enable video stream. -**/ -void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){ - cp->has_video=enabled; -} - -/** - * Returns the audio codec used in the call, described as a PayloadType structure. -**/ -const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) { - return cp->audio_codec; -} - - -/** - * Returns the video codec used in the call, described as a PayloadType structure. -**/ -const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) { - return cp->video_codec; -} - -MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp) { - return cp->sent_vsize; -} - -MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp) { - return cp->recv_vsize; -} - -/** - * Gets the framerate of the video that is sent. - * @param[in] cp The call parameters. - * @return the actual sent framerate in frames per seconds, 0 if not available. - */ -float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp){ - return cp->sent_fps; -} - -/** - * Gets the framerate of the video that is received. - * @param[in] cp The call paramaters for which to get the received framerate. - * @return the actual received framerate in frames per seconds, 0 if not available. - */ -float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp){ - return cp->received_fps; -} - -const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp) { - return sal_media_proto_to_string(get_proto_from_call_params(cp)); -} - -/** - * @ingroup call_control - * Use to know if this call has been configured in low bandwidth mode. - * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file. - * An application that would have reliable way to know network capacity may not use activate_edge_workarounds=1 but instead manually configure - * low bandwidth mode with linphone_call_params_enable_low_bandwidth(). - *
When enabled, this param may transform a call request with video in audio only mode. - * @return TRUE if low bandwidth has been configured/detected - */ -bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) { - return cp->low_bandwidth; -} - -/** - * @ingroup call_control - * Indicate low bandwith mode. - * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage - * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided - * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled. - * -**/ -void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){ - cp->low_bandwidth=enabled; -} - -/** - * Returns whether video is enabled. -**/ -bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){ - return cp->has_video; -} - -/** - * Returns kind of media encryption selected for the call. -**/ -LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) { - return cp->media_encryption; -} - -/** - * Set requested media encryption for a call. -**/ -void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e) { - cp->media_encryption = e; -} - - -/** - * Enable sending of real early media (during outgoing calls). -**/ -void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){ - cp->real_early_media=enabled; -} - -/** - * Indicates whether sending of early media was enabled. -**/ -bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){ - return cp->real_early_media; -} - -/** - * Returns true if the call is part of the locally managed conference. -**/ -bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){ - return cp->in_conference; -} - -/** - * Refine bandwidth settings for this call by setting a bandwidth limit for audio streams. - * As a consequence, codecs whose bitrates are not compatible with this limit won't be used. -**/ -void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){ - cp->audio_bw=bandwidth; -} - -void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value){ - params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value); -} - -const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){ - return sal_custom_header_find(params->custom_headers,header_name); -} - -/** - * Returns the session name of the media session (ie in SDP). Subject from the SIP message can be retrieved using linphone_call_params_get_custom_header() and is different. - * @param cp the call parameters. -**/ -const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){ - return cp->session_name; -} - -/** - * Set the session name of the media session (ie in SDP). Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header(). - * @param cp the call parameters. - * @param name the session name -**/ -void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){ - if (cp->session_name){ - ms_free(cp->session_name); - cp->session_name=NULL; - } - if (name) cp->session_name=ms_strdup(name); -} - -void _linphone_call_params_copy(LinphoneCallParams *ncp, const LinphoneCallParams *cp){ - if (ncp==cp) return; - memcpy(ncp,cp,sizeof(LinphoneCallParams)); - if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file); - if (cp->session_name) ncp->session_name=ms_strdup(cp->session_name); - /* - * The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient. - */ - if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers); -} - -/** - * @ingroup call_control - * Set requested level of privacy for the call. - * \xmlonly javascript \endxmlonly - * @param params the call parameters to be modified - * @param privacy LinphonePrivacy to configure privacy - * */ -void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) { - params->privacy=privacy; -} - -/** - * @ingroup call_control - * Get requested level of privacy for the call. - * @param params the call parameters - * @return Privacy mode - * */ -LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) { - return params->privacy; -} /** * @ingroup call_control @@ -1539,27 +1393,6 @@ const char* linphone_privacy_to_string(LinphonePrivacy privacy) { default: return "Unknown privacy mode"; } } -/** - * Copy existing LinphoneCallParams to a new LinphoneCallParams object. -**/ -LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){ - LinphoneCallParams *ncp=ms_new0(LinphoneCallParams,1); - _linphone_call_params_copy(ncp,cp); - return ncp; -} - -void linphone_call_params_uninit(LinphoneCallParams *p){ - if (p->record_file) ms_free(p->record_file); - if (p->custom_headers) sal_custom_header_free(p->custom_headers); -} - -/** - * Destroy LinphoneCallParams. -**/ -void linphone_call_params_destroy(LinphoneCallParams *p){ - linphone_call_params_uninit(p); - ms_free(p); -} /** @@ -1594,7 +1427,7 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED: ms_message("First video frame decoded successfully"); if (call->nextVideoFrameDecoded._func != NULL) - call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data); + call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data); break; case MS_VIDEO_DECODER_SEND_PLI: case MS_VIDEO_DECODER_SEND_SLI: @@ -1624,7 +1457,7 @@ static void port_config_set_random_choosed(LinphoneCall *call, int stream_index, static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){ MediaStream *ms=stream_index == 0 ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream; - if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ + if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ IceCheckList *cl; rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE); rtp_session_set_symmetric_rtp(ms->sessions.rtp_session, FALSE); @@ -1645,11 +1478,11 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){ SalMediaDescription *remote = NULL; bool_t has_video=FALSE; - if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ + if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ if (incoming_offer){ remote=sal_call_get_remote_media_description(call->op); - has_video=call->params.has_video && linphone_core_media_description_contains_video_stream(remote); - }else has_video=call->params.has_video; + has_video=call->params->has_video && linphone_core_media_description_contains_video_stream(remote); + }else has_video=call->params->has_video; _linphone_call_prepare_ice_for_stream(call,0,TRUE); if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE); @@ -1679,6 +1512,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; @@ -1702,16 +1536,24 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ else if (strcasecmp(type,"full")==0) audio_stream_enable_echo_limiter(audiostream,ELControlFull); } + + /* equalizer location in the graph: 'mic' = in input graph, otherwise in output graph. + Any other value than mic will default to output graph for compatibility */ + location = lp_config_get_string(lc->config,"sound","eq_location","hp"); + audiostream->eq_loc = (strcasecmp(location,"mic") == 0) ? MSEqualizerMic : MSEqualizerHP; + ms_message("Equalizer location: %s", location); + audio_stream_enable_gain_control(audiostream,TRUE); if (linphone_core_echo_cancellation_enabled(lc)){ int len,delay,framesize; - const char *statestr=lp_config_get_string(lc->config,"sound","ec_state",NULL); + char *statestr=lp_config_read_relative_file(lc->config, EC_STATE_STORE); len=lp_config_get_int(lc->config,"sound","ec_tail_len",0); delay=lp_config_get_int(lc->config,"sound","ec_delay",0); framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0); audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize); if (statestr && audiostream->ec){ ms_filter_call_method(audiostream->ec,MS_ECHO_CANCELLER_SET_STATE_STRING,(void*)statestr); + ms_free(statestr); } } audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc)); @@ -1725,7 +1567,11 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ if (lc->rtptf){ RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[0].rtp_port); RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port); - rtp_session_set_transports(audiostream->ms.sessions.rtp_session,artp,artcp); + RtpTransport *meta_rtp; + RtpTransport *meta_rtcp; + meta_rtp_transport_new(&meta_rtp,TRUE,artp, 0); + meta_rtp_transport_new(&meta_rtcp,FALSE,artcp, 0); + rtp_session_set_transports(audiostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp); } call->audiostream_app_evq = ortp_ev_queue_new(); @@ -1763,9 +1609,13 @@ void linphone_call_init_video_stream(LinphoneCall *call){ if (lc->rtptf){ RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[1].rtp_port); RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[1].rtcp_port); - rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,vrtp,vrtcp); + RtpTransport *meta_rtp; + RtpTransport *meta_rtcp; + meta_rtp_transport_new(&meta_rtp,TRUE,vrtp, 0); + meta_rtp_transport_new(&meta_rtcp,FALSE,vrtcp, 0); + rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp); } - call->videostream_app_evq = ortp_ev_queue_new(); + call->videostream_app_evq = ortp_ev_queue_new(); rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq); _linphone_call_prepare_ice_for_stream(call,1,FALSE); #ifdef TEST_EXT_RENDERER @@ -1790,8 +1640,7 @@ static void linphone_core_dtmf_received(LinphoneCore *lc, int dtmf){ ms_warning("Bad dtmf value %i",dtmf); return; } - if (lc->vtable.dtmf_received != NULL) - lc->vtable.dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]); + linphone_core_notify_dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]); } static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){ @@ -1816,6 +1665,19 @@ static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){ } } +void set_mic_gain_db(AudioStream *st, float gain){ + if (st->volsend){ + ms_filter_call_method(st->volsend,MS_VOLUME_SET_DB_GAIN,&gain); + }else ms_warning("Could not apply mic gain: gain control wasn't activated."); +} + +void set_playback_gain_db(AudioStream *st, float gain){ + if (st->volrecv){ + ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain); + }else ms_warning("Could not apply playback gain: gain control wasn't activated."); +} + +/*This function is not static because used internally in linphone-daemon project*/ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){ float mic_gain=lc->sound_conf.soft_mic_lev; float thres = 0; @@ -1832,13 +1694,13 @@ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t mute int spk_agc; if (!muted) - linphone_core_set_mic_gain_db (lc, mic_gain); + set_mic_gain_db(st,mic_gain); else audio_stream_set_mic_gain(st,0); recv_gain = lc->sound_conf.soft_play_lev; if (recv_gain != 0) { - linphone_core_set_playback_gain_db (lc,recv_gain); + set_playback_gain_db(st,recv_gain); } if (st->volsend){ @@ -1874,11 +1736,11 @@ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t mute parametrize_equalizer(lc,st); } -static void post_configure_audio_streams(LinphoneCall*call){ +static void post_configure_audio_streams(LinphoneCall *call, bool_t muted){ AudioStream *st=call->audiostream; LinphoneCore *lc=call->core; - _post_configure_audio_stream(st,lc,call->audio_muted); - if (lc->vtable.dtmf_received!=NULL){ + _post_configure_audio_stream(st,lc,muted); + if (linphone_core_dtmf_received_has_listener(lc)){ audio_stream_play_received_dtmfs(call->audiostream,FALSE); } if (call->record_active) @@ -1889,7 +1751,7 @@ static int get_ideal_audio_bw(LinphoneCall *call, const SalMediaDescription *md, int remote_bw=0; int upload_bw; int total_upload_bw=linphone_core_get_upload_bandwidth(call->core); - const LinphoneCallParams *params=&call->params; + const LinphoneCallParams *params=call->params; bool_t will_use_video=linphone_core_media_description_contains_video_stream(md); bool_t forced=FALSE; @@ -1936,7 +1798,7 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m bool_t first=TRUE; LinphoneCore *lc=call->core; int up_ptime=0; - const LinphoneCallParams *params=&call->params; + const LinphoneCallParams *params=call->params; *used_pt=-1; @@ -2044,6 +1906,7 @@ static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *ca static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cname, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){ LinphoneCore *lc=call->core; + LpConfig* conf; int used_pt=-1; char rtcp_tool[128]={0}; const SalStreamDescription *stream; @@ -2068,7 +1931,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt); if (used_pt!=-1){ - call->current_params.audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); + call->current_params->audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); if (playcard==NULL) { ms_warning("No card defined for playback !"); } @@ -2088,15 +1951,20 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna /*playfile=NULL;*/ } if (send_ringbacktone){ + conf = linphone_core_get_config(lc); captcard=NULL; playfile=NULL;/* it is setup later*/ + if( conf && lp_config_get_int(conf,"sound","send_ringback_without_playback", 0) == 1){ + playcard = NULL; + recfile = NULL; + } } /*if playfile are supplied don't use soundcards*/ if (lc->use_files) { captcard=NULL; playcard=NULL; } - if (call->params.in_conference){ + if (call->params->in_conference){ /* first create the graph without soundcard resources*/ captcard=playcard=NULL; } @@ -2108,10 +1976,12 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna if (playcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(playcard, stream->max_rate); if (captcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate); audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc); + media_stream_set_adaptive_bitrate_algorithm(&call->audiostream->ms, + ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc))); audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc)); - if (!call->params.in_conference && call->params.record_file){ - audio_stream_mixed_record_open(call->audiostream,call->params.record_file); - call->current_params.record_file=ms_strdup(call->params.record_file); + if (!call->params->in_conference && call->params->record_file){ + audio_stream_mixed_record_open(call->audiostream,call->params->record_file); + call->current_params->record_file=ms_strdup(call->params->record_file); } /* valid local tags are > 0 */ if (sal_stream_description_has_srtp(stream) == TRUE) { @@ -2142,10 +2012,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna captcard, use_ec ); - post_configure_audio_streams(call); - if (muted && !send_ringbacktone){ - audio_stream_set_mic_gain(call->audiostream,0); - } + post_configure_audio_streams(call, muted && !send_ringbacktone); if (stream->dir==SalStreamSendOnly && playfile!=NULL){ int pause_time=500; ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); @@ -2154,13 +2021,13 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna setup_ring_player(lc,call); } - if (call->params.in_conference){ + if (call->params->in_conference){ /*transform the graph to connect it to the conference filter */ mute=stream->dir==SalStreamRecvOnly; linphone_call_add_to_conf(call, mute); } - call->current_params.in_conference=call->params.in_conference; - call->current_params.low_bandwidth=call->params.low_bandwidth; + call->current_params->in_conference=call->params->in_conference; + call->current_params->low_bandwidth=call->params->low_bandwidth; }else ms_warning("No audio stream accepted ?"); } } @@ -2171,12 +2038,17 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna int used_pt=-1; char rtcp_tool[128]={0}; const SalStreamDescription *vstream; + MSFilter* source = NULL; + bool_t reused_preview = FALSE; snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version()); /* shutdown preview */ if (lc->previewstream!=NULL) { - video_preview_stop(lc->previewstream); + + if( lc->video_conf.reuse_preview_source == FALSE) video_preview_stop(lc->previewstream); + else source = video_preview_stop_reuse_source(lc->previewstream); + lc->previewstream=NULL; } @@ -2193,11 +2065,13 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna MSWebCam *cam=lc->video_conf.device; bool_t is_inactive=FALSE; - call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt); - call->current_params.has_video=TRUE; + call->current_params->video_codec = rtp_profile_get_payload(call->video_profile, used_pt); + call->current_params->has_video=TRUE; video_stream_enable_adaptive_bitrate_control(call->videostream, linphone_core_adaptive_rate_control_enabled(lc)); + media_stream_set_adaptive_bitrate_algorithm(&call->videostream->ms, + ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc))); video_stream_enable_adaptive_jittcomp(call->videostream, linphone_core_video_adaptive_jittcomp_enabled(lc)); if (lc->video_conf.preview_vsize.width!=0) video_stream_set_preview_size(call->videostream,lc->video_conf.preview_vsize); @@ -2249,15 +2123,30 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna video_stream_set_device_rotation(call->videostream, lc->device_rotation); video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool); video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 0)); - video_stream_start(call->videostream, - call->video_profile, rtp_addr, vstream->rtp_port, - rtcp_addr, - linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, - used_pt, linphone_core_get_video_jittcomp(lc), cam); + if( lc->video_conf.reuse_preview_source && source ){ + ms_message("video_stream_start_with_source kept: %p", source); + video_stream_start_with_source(call->videostream, + call->video_profile, rtp_addr, vstream->rtp_port, + rtcp_addr, + linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, + used_pt, linphone_core_get_video_jittcomp(lc), cam, source); + reused_preview = TRUE; + } else { + video_stream_start(call->videostream, + call->video_profile, rtp_addr, vstream->rtp_port, + rtcp_addr, + linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, + used_pt, linphone_core_get_video_jittcomp(lc), cam); + } } }else ms_warning("No video stream accepted."); }else{ - ms_warning("No valid video stream defined."); + ms_message("No valid video stream defined."); + } + if( reused_preview == FALSE && source != NULL ){ + /* destroy not-reused source filter */ + ms_warning("Video preview (%p) not reused: destroying it.", source); + ms_filter_destroy(source); } #endif } @@ -2271,8 +2160,8 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo); #endif - call->current_params.audio_codec = NULL; - call->current_params.video_codec = NULL; + call->current_params->audio_codec = NULL; + call->current_params->video_codec = NULL; if ((call->audiostream == NULL) && (call->videostream == NULL)) { ms_fatal("start_media_stream() called without prior init !"); @@ -2290,9 +2179,9 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut call, linphone_core_get_upload_bandwidth(lc),linphone_core_get_download_bandwidth(lc)); if (call->audiostream!=NULL) { - linphone_call_start_audio_stream(call,cname,all_inputs_muted,send_ringbacktone,use_arc); + linphone_call_start_audio_stream(call,cname,all_inputs_muted||call->audio_muted,send_ringbacktone,use_arc); } - call->current_params.has_video=FALSE; + call->current_params->has_video=FALSE; if (call->videostream!=NULL) { if (call->audiostream) audio_stream_link_video(call->audiostream,call->videostream); linphone_call_start_video_stream(call,cname,all_inputs_muted); @@ -2302,7 +2191,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut call->playing_ringbacktone=send_ringbacktone; call->up_bw=linphone_core_get_upload_bandwidth(lc); - if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) { + if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { OrtpZrtpParams params; memset(¶ms,0,sizeof(OrtpZrtpParams)); /*call->current_params.media_encryption will be set later when zrtp is activated*/ @@ -2316,7 +2205,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut } #endif }else{ - call->current_params.media_encryption=linphone_call_all_streams_encrypted(call) ? + call->current_params->media_encryption=linphone_call_all_streams_encrypted(call) ? LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone; } @@ -2342,7 +2231,7 @@ void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){ static bool_t update_stream_crypto_params(LinphoneCall *call, const SalStreamDescription *local_st_desc, SalStreamDescription *old_stream, SalStreamDescription *new_stream, MediaStream *ms){ int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag); if (crypto_idx >= 0) { - if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) + if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) media_stream_set_srtp_send_key(ms,new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key); if (strcmp(old_stream->crypto[0].master_key,new_stream->crypto[0].master_key)!=0){ media_stream_set_srtp_recv_key(ms,new_stream->crypto[0].algo,new_stream->crypto[0].master_key); @@ -2429,7 +2318,7 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) { ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_STATE_STRING,&state_str); if (state_str){ ms_message("Writing echo canceler state, %i bytes",(int)strlen(state_str)); - lp_config_set_string(call->core->config,"sound","ec_state",state_str); + lp_config_write_relative_file(call->core->config, EC_STATE_STORE, state_str); } } audio_stream_get_local_rtp_stats(call->audiostream,&call->log->local_stats); @@ -2439,7 +2328,7 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) { } audio_stream_stop(call->audiostream); call->audiostream=NULL; - call->current_params.audio_codec = NULL; + call->current_params->audio_codec = NULL; } } @@ -2455,7 +2344,7 @@ static void linphone_call_stop_video_stream(LinphoneCall *call) { linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream); video_stream_stop(call->videostream); call->videostream=NULL; - call->current_params.video_codec = NULL; + call->current_params->video_codec = NULL; } #endif } @@ -2756,38 +2645,49 @@ uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCa if (!stats || !call) return 0; memset(&rtp_stats, 0, sizeof(rtp_stats)); - if (stats->type == LINPHONE_CALL_STATS_AUDIO) + if (stats->type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) audio_stream_get_local_rtp_stats(call->audiostream, &rtp_stats); #ifdef VIDEO_ENABLED - else + else if (call->videostream != NULL) video_stream_get_local_rtp_stats(call->videostream, &rtp_stats); #endif return rtp_stats.outoftime; } /** - * Enable recording of the call (voice-only). - * This function must be used before the call parameters are assigned to the call. - * The call recording can be started and paused after the call is established with - * linphone_call_start_recording() and linphone_call_pause_recording(). - * @param cp the call parameters - * @param path path and filename of the file where audio/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){ - ms_free(cp->record_file); - cp->record_file=NULL; - } - if (path) cp->record_file=ms_strdup(path); + * Get the bandwidth measurement of the received stream, expressed in kbit/s, including IP/UDP/RTP headers. + * @param[in] stats LinphoneCallStats object + * @return The bandwidth measurement of the received stream in kbit/s. + */ +float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats) { + return stats->download_bandwidth; } /** - * Retrieves the path for the audio recoding of the call. -**/ -const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){ - return cp->record_file; + * Get the bandwidth measurement of the sent stream, expressed in kbit/s, including IP/UDP/RTP headers. + * @param[in] stats LinphoneCallStats object + * @return The bandwidth measurement of the sent stream in kbit/s. + */ +float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats) { + return stats->upload_bandwidth; +} + +/** + * Get the state of ICE processing. + * @param[in] stats LinphoneCallStats object + * @return The state of ICE processing. + */ +LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats) { + return stats->ice_state; +} + +/** + * Get the state of uPnP processing. + * @param[in] stats LinphoneCallStats object + * @return The state of uPnP processing. + */ +LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats) { + return stats->upnp_state; } /** @@ -2795,11 +2695,11 @@ const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){ * The output file where audio is recorded must be previously specified with linphone_call_params_set_record_file(). **/ void linphone_call_start_recording(LinphoneCall *call){ - if (!call->params.record_file){ + if (!call->params->record_file){ ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file()."); return; } - if (call->audiostream && !call->params.in_conference){ + if (call->audiostream && !call->params->in_conference){ audio_stream_mixed_record_start(call->audiostream); } call->record_active=TRUE; @@ -2809,7 +2709,7 @@ void linphone_call_start_recording(LinphoneCall *call){ * Stop call recording. **/ void linphone_call_stop_recording(LinphoneCall *call){ - if (call->audiostream && !call->params.in_conference){ + if (call->audiostream && !call->params->in_conference){ audio_stream_mixed_record_stop(call->audiostream); } call->record_active=FALSE; @@ -2842,8 +2742,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){ if (from) ms_free(from); ms_message("On call [%p]: %s",call,temp); - if (lc->vtable.display_warning!=NULL) - lc->vtable.display_warning(lc,temp); + linphone_core_notify_display_warning(lc,temp); linphone_core_terminate_call(lc,call); linphone_core_play_named_tone(lc,LinphoneToneCallLost); } @@ -2854,17 +2753,16 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ int ping_time; if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) { - LinphoneCallParams params; - _linphone_call_params_copy(¶ms,&call->current_params); - if (call->params.media_encryption == LinphoneMediaEncryptionZRTP) { + LinphoneCallParams *params = linphone_call_params_copy(call->current_params); + if (call->params->media_encryption == LinphoneMediaEncryptionZRTP) { /* preserve media encryption param because at that time ZRTP negociation may still be ongoing*/ - params.media_encryption=call->params.media_encryption; + params->media_encryption=call->params->media_encryption; } switch (ice_session_state(call->ice_session)) { case IS_Completed: ice_session_select_candidates(call->ice_session); if (ice_session_role(call->ice_session) == IR_Controlling) { - linphone_core_update_call(call->core, call, ¶ms); + linphone_core_update_call(call->core, call, params); } break; case IS_Failed: @@ -2872,7 +2770,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ ice_session_select_candidates(call->ice_session); if (ice_session_role(call->ice_session) == IR_Controlling) { /* At least one ICE session has succeeded, so perform a call update. */ - linphone_core_update_call(call->core, call, ¶ms); + linphone_core_update_call(call->core, call, params); } } break; @@ -2880,6 +2778,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ break; } linphone_core_update_ice_state_in_call_stats(call); + linphone_call_params_unref(params); } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) { if (evd->info.ice_processing_successful==TRUE) { @@ -2899,7 +2798,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ linphone_core_start_update_call(call->core, call); break; case LinphoneCallUpdatedByRemote: - linphone_core_start_accept_call_update(call->core, call); + linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate)); break; case LinphoneCallOutgoingInit: linphone_call_stop_media_streams_for_ice_gathering(call); @@ -2914,13 +2813,13 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ } } else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) { if (call->state==LinphoneCallUpdatedByRemote){ - linphone_core_start_accept_call_update(call->core, call); + linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate)); linphone_core_update_ice_state_in_call_stats(call); } } else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) { ice_session_restart(call->ice_session); ice_session_set_role(call->ice_session, IR_Controlling); - linphone_core_update_call(call->core, call, &call->current_params); + linphone_core_update_call(call->core, call, call->current_params); } } @@ -2965,8 +2864,7 @@ void linphone_call_notify_stats_updated(LinphoneCall *call, int stream_index){ LinphoneCore *lc=call->core; if (stats->updated){ linphone_reporting_on_rtcp_update(call, stream_index); - if (lc->vtable.call_stats_updated) - lc->vtable.call_stats_updated(lc, call, stats); + linphone_core_notify_call_stats_updated(lc, call, stats); stats->updated = 0; } } @@ -3053,7 +2951,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse void linphone_call_log_completed(LinphoneCall *call){ LinphoneCore *lc=call->core; - call->log->duration=time(NULL)-call->log->start_date_time; + call->log->duration=linphone_call_get_duration(call); /*store duration since connected*/ if (call->log->status==LinphoneCallMissed){ char *info; @@ -3061,11 +2959,10 @@ void linphone_call_log_completed(LinphoneCall *call){ info=ortp_strdup_printf(ngettext("You have missed %i call.", "You have missed %i calls.", lc->missed_calls), lc->missed_calls); - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,info); + linphone_core_notify_display_status(lc,info); ms_free(info); } - lc->call_logs=ms_list_prepend(lc->call_logs,(void *)call->log); + lc->call_logs=ms_list_prepend(lc->call_logs,linphone_call_log_ref(call->log)); if (ms_list_size(lc->call_logs)>lc->max_call_logs){ MSList *elem,*prevelem=NULL; /*find the last element*/ @@ -3073,12 +2970,10 @@ void linphone_call_log_completed(LinphoneCall *call){ prevelem=elem; } elem=prevelem; - linphone_call_log_destroy((LinphoneCallLog*)elem->data); + linphone_call_log_unref((LinphoneCallLog*)elem->data); lc->call_logs=ms_list_remove_link(lc->call_logs,elem); } - if (lc->vtable.call_log_updated!=NULL){ - lc->vtable.call_log_updated(lc,call->log); - } + linphone_core_notify_call_log_updated(lc,call->log); call_logs_write_to_config_file(lc); } @@ -3097,13 +2992,12 @@ void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState stat ,linphone_call_state_to_string(call->transfer_state) ,linphone_call_state_to_string(state)); call->transfer_state = state; - if (lc->vtable.transfer_state_changed) - lc->vtable.transfer_state_changed(lc, call, state); + linphone_core_notify_transfer_state_changed(lc, call, state); } } bool_t linphone_call_is_in_conference(const LinphoneCall *call) { - return call->params.in_conference; + return call->params->in_conference; } /** @@ -3137,7 +3031,7 @@ void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, zoom[0] = zoom_factor; zoom[1] = *cx; zoom[2] = *cy; - ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom); + ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom); }else ms_warning("Could not apply zoom: video output wasn't activated."); } @@ -3147,7 +3041,7 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , const char *localip=call->localip; /* first use user's supplied ip address if asked*/ - if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){ + if (_linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){ ctt=linphone_core_get_primary_contact_parsed(lc); linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc)); ret=ctt; @@ -3193,3 +3087,16 @@ void linphone_call_set_contact_op(LinphoneCall* call) { linphone_address_destroy(contact); } } + +LinphonePlayer *linphone_call_get_player(LinphoneCall *call){ + if (call->player==NULL) + call->player=linphone_call_build_player(call); + return call->player; +} + +void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){ + LinphoneCallParams *cp=NULL; + if (params) cp=linphone_call_params_copy(params); + if (call->params) linphone_call_params_unref(call->params); + call->params=cp; +} diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 4a5a11554..ef81ef8c1 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -17,8 +17,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define _GNU_SOURCE - #include "linphonecore.h" #include "sipsetup.h" #include "lpconfig.h" @@ -26,6 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quality_reporting.h" #include +#include +#include #include #include #include "mediastreamer2/mediastream.h" @@ -42,7 +42,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef HAVE_CONFIG_H #include "config.h" -#include "liblinphone_gitversion.h" +#ifndef ANDROID /*on Android LIBLINPHONE version is passed from root Makefile*/ + #include "liblinphone_gitversion.h" +#endif #else #ifndef LIBLINPHONE_GIT_VERSION #define LIBLINPHONE_GIT_VERSION "unknown" @@ -53,6 +55,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "TargetConditionals.h" #endif +#ifdef HAVE_ZLIB +#define COMPRESSED_LOG_COLLECTION_EXTENSION "gz" +#ifdef WIN32 +#include +#include +#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +#define SET_BINARY_MODE(file) +#endif +#include +#else +#define COMPRESSED_LOG_COLLECTION_EXTENSION "txt" +#endif +#define LOG_COLLECTION_DEFAULT_PATH "." +#define LOG_COLLECTION_DEFAULT_PREFIX "linphone" +#define LOG_COLLECTION_DEFAULT_MAX_FILE_SIZE (10 * 1024 * 1024) + + /*#define UNSTANDART_GSM_11K 1*/ #define ROOT_CA_FILE PACKAGE_DATA_DIR "/linphone/rootca.pem" @@ -64,6 +84,12 @@ static const char *liblinphone_version= LIBLINPHONE_VERSION #endif ; +static OrtpLogFunc liblinphone_log_func = NULL; +static LinphoneLogCollectionState liblinphone_log_collection_state = LinphoneLogCollectionDisabled; +static char * liblinphone_log_collection_path = NULL; +static char * liblinphone_log_collection_prefix = NULL; +static int liblinphone_log_collection_max_file_size = LOG_COLLECTION_DEFAULT_MAX_FILE_SIZE; +static ortp_mutex_t liblinphone_log_collection_mutex; 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); @@ -102,345 +128,486 @@ int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){ } -/*prevent a gcc bug with %c*/ -static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){ - return strftime(s, max, fmt, tm); +/** + * Returns TRUE if the LinphoneCall asked to autoanswer + * +**/ +bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){ + //return TRUE if the unique(for the moment) incoming call asked to be autoanswered + if(call) + return sal_call_autoanswer_asked(call->op); + else + return FALSE; } -static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){ - struct tm loctime; -#ifdef WIN32 -#if !defined(_WIN32_WCE) - loctime=*localtime(&start_time); - /*FIXME*/ -#endif /*_WIN32_WCE*/ -#else - localtime_r(&start_time,&loctime); -#endif - my_strftime(cl->start_date,sizeof(cl->start_date),"%c",&loctime); +int linphone_core_get_current_call_duration(const LinphoneCore *lc){ + LinphoneCall *call=linphone_core_get_current_call((LinphoneCore *)lc); + if (call) return linphone_call_get_duration(call); + return -1; } -LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){ - LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1); - cl->dir=call->dir; - cl->start_date_time=time(NULL); - set_call_log_date(cl,cl->start_date_time); - cl->from=from; - cl->to=to; - cl->status=LinphoneCallAborted; /*default status*/ - cl->quality=-1; +const LinphoneAddress *linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc){ + LinphoneCall *call=linphone_core_get_current_call(lc); + if (call==NULL) return NULL; + return linphone_call_get_remote_address(call); +} - cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new(); - cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new(); - return cl; +void linphone_core_set_log_handler(OrtpLogFunc logfunc) { + ortp_set_log_handler(logfunc); } -void call_logs_write_to_config_file(LinphoneCore *lc){ - MSList *elem; - char logsection[32]; - int i; - char *tmp; - LpConfig *cfg=lc->config; - - if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return; - - for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){ - LinphoneCallLog *cl=(LinphoneCallLog*)elem->data; - snprintf(logsection,sizeof(logsection),"call_log_%i",i); - lp_config_clean_section(cfg,logsection); - lp_config_set_int(cfg,logsection,"dir",cl->dir); - lp_config_set_int(cfg,logsection,"status",cl->status); - tmp=linphone_address_as_string(cl->from); - lp_config_set_string(cfg,logsection,"from",tmp); - ms_free(tmp); - tmp=linphone_address_as_string(cl->to); - lp_config_set_string(cfg,logsection,"to",tmp); - ms_free(tmp); - if (cl->start_date_time) - lp_config_set_int64(cfg,logsection,"start_date_time",(int64_t)cl->start_date_time); - else lp_config_set_string(cfg,logsection,"start_date",cl->start_date); - lp_config_set_int(cfg,logsection,"duration",cl->duration); - if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey); - lp_config_set_float(cfg,logsection,"quality",cl->quality); - lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled); - lp_config_set_string(cfg,logsection,"call_id",cl->call_id); - } - for(;imax_call_logs;++i){ - snprintf(logsection,sizeof(logsection),"call_log_%i",i); - lp_config_clean_section(cfg,logsection); - } -} - -static time_t string_to_time(const char *date){ -#ifndef WIN32 - struct tm tmtime={0}; - strptime(date,"%c",&tmtime); - return mktime(&tmtime); -#else - return 0; -#endif +void linphone_core_set_log_file(FILE *file) { + if (file == NULL) file = stdout; + ortp_set_log_file(file); } -static void call_logs_read_from_config_file(LinphoneCore *lc){ - char logsection[32]; - int i; - const char *tmp; - uint64_t sec; - LpConfig *cfg=lc->config; - for(i=0;;++i){ - snprintf(logsection,sizeof(logsection),"call_log_%i",i); - if (lp_config_has_section(cfg,logsection)){ - LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1); - cl->dir=lp_config_get_int(cfg,logsection,"dir",0); - cl->status=lp_config_get_int(cfg,logsection,"status",0); - tmp=lp_config_get_string(cfg,logsection,"from",NULL); - if (tmp) cl->from=linphone_address_new(tmp); - tmp=lp_config_get_string(cfg,logsection,"to",NULL); - if (tmp) cl->to=linphone_address_new(tmp); - sec=lp_config_get_int64(cfg,logsection,"start_date_time",0); - if (sec) { - /*new call log format with date expressed in seconds */ - cl->start_date_time=(time_t)sec; - set_call_log_date(cl,cl->start_date_time); - }else{ - tmp=lp_config_get_string(cfg,logsection,"start_date",NULL); - if (tmp) { - strncpy(cl->start_date,tmp,sizeof(cl->start_date)); - cl->start_date_time=string_to_time(cl->start_date); - } - } - cl->duration=lp_config_get_int(cfg,logsection,"duration",0); - tmp=lp_config_get_string(cfg,logsection,"refkey",NULL); - if (tmp) cl->refkey=ms_strdup(tmp); - cl->quality=lp_config_get_float(cfg,logsection,"quality",-1); - cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0); - tmp=lp_config_get_string(cfg,logsection,"call_id",NULL); - if (tmp) cl->call_id=ms_strdup(tmp); - lc->call_logs=ms_list_append(lc->call_logs,cl); - }else break; +void linphone_core_set_log_level(OrtpLogLevel loglevel) { + ortp_set_log_level_mask(loglevel); + if (loglevel == 0) { + sal_disable_logs(); + } else { + sal_enable_logs(); } } +static void linphone_core_log_collection_handler(OrtpLogLevel level, const char *fmt, va_list args) { + const char *lname="undef"; + char *msg; + char *log_filename1; + char *log_filename2; + FILE *log_file; + struct timeval tp; + struct tm *lt; + time_t tt; + struct stat statbuf; + if (liblinphone_log_func != NULL) { + liblinphone_log_func(level, fmt, args); + } -/** - * @addtogroup call_logs - * @{ -**/ - -/** - * Returns a human readable string describing the call. - * - * @note: the returned char* must be freed by the application (use ms_free()). -**/ -char * linphone_call_log_to_str(LinphoneCallLog *cl){ - char *status; - char *tmp; - char *from=linphone_address_as_string (cl->from); - char *to=linphone_address_as_string (cl->to); - switch(cl->status){ - case LinphoneCallAborted: - status=_("aborted"); + ortp_gettimeofday(&tp, NULL); + tt = (time_t)tp.tv_sec; + lt = localtime((const time_t*)&tt); + switch(level){ + case ORTP_DEBUG: + lname = "DEBUG"; break; - case LinphoneCallSuccess: - status=_("completed"); + case ORTP_MESSAGE: + lname = "MESSAGE"; break; - case LinphoneCallMissed: - status=_("missed"); + case ORTP_WARNING: + lname = "WARNING"; + break; + case ORTP_ERROR: + lname = "ERROR"; + break; + case ORTP_FATAL: + lname = "FATAL"; break; default: - status="unknown"; - } - tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"), - (cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"), - cl->start_date, - from, - to, - status, - cl->duration/60, - cl->duration%60); - ms_free(from); - ms_free(to); - return tmp; -} - -/** - * Returns RTP statistics computed locally regarding the call. - * -**/ -const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){ - return &cl->local_stats; -} + ortp_fatal("Bad level !"); + } + msg = ortp_strdup_vprintf(fmt, args); + + log_filename1 = ortp_strdup_printf("%s/%s1.log", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX); + log_filename2 = ortp_strdup_printf("%s/%s2.log", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX); + ortp_mutex_lock(&liblinphone_log_collection_mutex); + log_file = fopen(log_filename1, "a"); + fstat(fileno(log_file), &statbuf); + if (statbuf.st_size > liblinphone_log_collection_max_file_size) { + fclose(log_file); + log_file = fopen(log_filename2, "a"); + fstat(fileno(log_file), &statbuf); + if (statbuf.st_size > liblinphone_log_collection_max_file_size) { + fclose(log_file); + unlink(log_filename1); + rename(log_filename2, log_filename1); + log_file = fopen(log_filename2, "a"); + } + } + fprintf(log_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i %s %s\n", + 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec, (int)(tp.tv_usec / 1000), lname, msg); + fflush(log_file); + fclose(log_file); + ortp_mutex_unlock(&liblinphone_log_collection_mutex); -/** - * Returns RTP statistics computed by remote end and sent back via RTCP. - * - * @note Not implemented yet. -**/ -const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){ - return &cl->remote_stats; + ortp_free(log_filename1); + ortp_free(log_filename2); + ortp_free(msg); } -const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){ - return cl->call_id; +const char * linphone_core_get_log_collection_path(void) { + if (liblinphone_log_collection_path != NULL) { + return liblinphone_log_collection_path; + } + return LOG_COLLECTION_DEFAULT_PATH; } -/** - * Assign a user pointer to the call log. -**/ -void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up){ - cl->user_pointer=up; +void linphone_core_set_log_collection_path(const char *path) { + if (liblinphone_log_collection_path != NULL) { + ms_free(liblinphone_log_collection_path); + liblinphone_log_collection_path = NULL; + } + if (path != NULL) { + liblinphone_log_collection_path = ms_strdup(path); + } } -/** - * Returns the user pointer associated with the call log. -**/ -void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl){ - return cl->user_pointer; +const char * linphone_core_get_log_collection_prefix(void) { + if (liblinphone_log_collection_prefix != NULL) { + return liblinphone_log_collection_prefix; + } + return LOG_COLLECTION_DEFAULT_PREFIX; } - - -/** - * Associate a persistent reference key to the call log. - * - * The reference key can be for example an id to an external database. - * It is stored in the config file, thus can survive to process exits/restarts. - * -**/ -void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){ - if (cl->refkey!=NULL){ - ms_free(cl->refkey); - cl->refkey=NULL; +void linphone_core_set_log_collection_prefix(const char *prefix) { + if (liblinphone_log_collection_prefix != NULL) { + ms_free(liblinphone_log_collection_prefix); + liblinphone_log_collection_prefix = NULL; + } + if (prefix != NULL) { + liblinphone_log_collection_prefix = ms_strdup(prefix); } - if (refkey) cl->refkey=ms_strdup(refkey); } -/** - * Get the persistent reference key associated to the call log. - * - * The reference key can be for example an id to an external database. - * It is stored in the config file, thus can survive to process exits/restarts. - * -**/ -const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){ - return cl->refkey; +int linphone_core_get_log_collection_max_file_size(void) { + return liblinphone_log_collection_max_file_size; } -/** - * Returns origin (ie from) address of the call. -**/ -LinphoneAddress *linphone_call_log_get_from(LinphoneCallLog *cl){ - return cl->from; +void linphone_core_set_log_collection_max_file_size(int size) { + liblinphone_log_collection_max_file_size = size; } -/** - * Returns destination address (ie to) of the call. -**/ -LinphoneAddress *linphone_call_log_get_to(LinphoneCallLog *cl){ - return cl->to; +const char *linphone_core_get_log_collection_upload_server_url(LinphoneCore *core) { + return lp_config_get_string(core->config, "misc", "log_collection_upload_server_url", NULL); } -/** - * Returns remote address (that is from or to depending on call direction). -**/ -LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){ - return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to; +void linphone_core_set_log_collection_upload_server_url(LinphoneCore *core, const char *server_url) { + lp_config_set_string(core->config, "misc", "log_collection_upload_server_url", server_url); } -/** - * Returns the direction of the call. -**/ -LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){ - return cl->dir; +LinphoneLogCollectionState linphone_core_log_collection_enabled(void) { + return liblinphone_log_collection_state; } -/** - * Returns the status of the call. -**/ -LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){ - return cl->status; +void linphone_core_enable_log_collection(LinphoneLogCollectionState state) { + /* at first call of this function, set liblinphone_log_func to the current + * ortp log function */ + if( liblinphone_log_func == NULL ){ + liblinphone_log_func = ortp_logv_out; + } + liblinphone_log_collection_state = state; + if (state != LinphoneLogCollectionDisabled) { + ortp_mutex_init(&liblinphone_log_collection_mutex, NULL); + if (state == LinphoneLogCollectionEnabledWithoutPreviousLogHandler) { + liblinphone_log_func = NULL; + } else { + liblinphone_log_func = ortp_logv_out; + } + ortp_set_log_handler(linphone_core_log_collection_handler); + } else { + ortp_set_log_handler(liblinphone_log_func); + } } -/** - * Returns the start date of the call, expressed as a POSIX time_t. -**/ -time_t linphone_call_log_get_start_date(LinphoneCallLog *cl){ - return cl->start_date_time; +static void delete_log_collection_upload_file(void) { + char *filename = ms_strdup_printf("%s/%s_log.%s", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX, + COMPRESSED_LOG_COLLECTION_EXTENSION); + unlink(filename); + ms_free(filename); } -/** - * Returns duration of the call. -**/ -int linphone_call_log_get_duration(LinphoneCallLog *cl){ - return cl->duration; +static void process_io_error_upload_log_collection(void *data, const belle_sip_io_error_event_t *event) { + LinphoneCore *core = (LinphoneCore *)data; + ms_error("I/O Error during log collection upload to %s", linphone_core_get_log_collection_upload_server_url(core)); + linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateNotDelivered, "I/O Error"); + delete_log_collection_upload_file(); } -/** - * Returns overall quality indication of the call. -**/ -float linphone_call_log_get_quality(LinphoneCallLog *cl){ - return cl->quality; +static void process_auth_requested_upload_log_collection(void *data, belle_sip_auth_event_t *event) { + LinphoneCore *core = (LinphoneCore *)data; + ms_error("Error during log collection upload: auth requested to connect %s", linphone_core_get_log_collection_upload_server_url(core)); + linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateNotDelivered, "Auth requested"); + delete_log_collection_upload_file(); } + /** - * return true if video was enabled at the end of the call + * Callback called when posting a log collection file to server (following rcs5.1 recommendation) + * + * @param[in] bh The body handler + * @param[in] msg The belle sip message + * @param[in] data The user data associated with the handler, contains the LinphoneCore object + * @param[in] offset The current position in the input buffer + * @param[in] buffer The ouput buffer where to copy the data to be uploaded + * @param[in,out] size The size in byte of the data requested, as output it will contain the effective copied size + * */ -bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) { - return cl->video_enabled; -} -/** @} */ +static int log_collection_upload_on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *msg, void *data, size_t offset, uint8_t *buffer, size_t *size) { + LinphoneCore *core = (LinphoneCore *)data; + + /* If we've not reach the end of file yet, fill the buffer with more data */ + if (offset < core->log_collection_upload_information->size) { + char *log_filename = ms_strdup_printf("%s/%s_log.%s", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX, + COMPRESSED_LOG_COLLECTION_EXTENSION); +#ifdef HAVE_ZLIB + FILE *log_file = fopen(log_filename, "rb"); +#else + FILE *log_file = fopen(log_filename, "r"); +#endif + fseek(log_file, offset, SEEK_SET); + *size = fread(buffer, 1, *size, log_file); + fclose(log_file); + ms_free(log_filename); + } -void linphone_call_log_destroy(LinphoneCallLog *cl){ - if (cl->from!=NULL) linphone_address_destroy(cl->from); - if (cl->to!=NULL) linphone_address_destroy(cl->to); - if (cl->refkey!=NULL) ms_free(cl->refkey); - if (cl->call_id) ms_free(cl->call_id); - if (cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]); - if (cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]); + return BELLE_SIP_CONTINUE; +} - ms_free(cl); +/** + * Callback called during upload of a log collection to server. + * It is just forwarding the call and some parameters to the vtable defined callback. + */ +static void log_collection_upload_on_progress(belle_sip_body_handler_t *bh, belle_sip_message_t *msg, void *data, size_t offset, size_t total) { + LinphoneCore *core = (LinphoneCore *)data; + linphone_core_notify_log_collection_upload_progress_indication(core, offset, total); } /** - * Returns TRUE if the LinphoneCall asked to autoanswer + * Callback function called when we have a response from server during the upload of the log collection to the server (rcs5.1 recommandation) + * Note: The first post is empty and the server shall reply a 204 (No content) message, this will trigger a new post request to the server + * to upload the file. The server response to this second post is processed by this same function * -**/ -bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){ - //return TRUE if the unique(for the moment) incoming call asked to be autoanswered - if(call) - return sal_call_autoanswer_asked(call->op); - else - return FALSE; + * @param[in] data The user-defined pointer associated with the request, it contains the LinphoneCore object + * @param[in] event The response from server + */ +static void process_response_from_post_file_log_collection(void *data, const belle_http_response_event_t *event) { + LinphoneCore *core = (LinphoneCore *)data; + + /* Check the answer code */ + if (event->response) { + int code = belle_http_response_get_status_code(event->response); + if (code == 204) { /* This is the reply to the first post to the server - an empty file */ + /* Start uploading the file */ + belle_http_request_listener_callbacks_t cbs = { 0 }; + belle_http_request_listener_t *l; + belle_generic_uri_t *uri; + belle_http_request_t *req; + belle_sip_multipart_body_handler_t *bh; + char* ua; + char *first_part_header; + belle_sip_user_body_handler_t *first_part_bh; + + linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateInProgress, NULL); + + /* Temporary storage for the Content-disposition header value */ + first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"", core->log_collection_upload_information->name); + + /* Create a user body handler to take care of the file and add the content disposition and content-type headers */ + first_part_bh = belle_sip_user_body_handler_new(core->log_collection_upload_information->size, NULL, NULL, log_collection_upload_on_send_body, core); + belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, belle_sip_header_create("Content-disposition", first_part_header)); + belle_sip_free(first_part_header); + belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, (belle_sip_header_t *)belle_sip_header_content_type_create(core->log_collection_upload_information->type, core->log_collection_upload_information->subtype)); + + /* Insert it in a multipart body handler which will manage the boundaries of multipart message */ + bh = belle_sip_multipart_body_handler_new(log_collection_upload_on_progress, core, (belle_sip_body_handler_t *)first_part_bh); + ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version()); + uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core)); + req = belle_http_request_create("POST", uri, belle_sip_header_create("User-Agent", ua), NULL); + ms_free(ua); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(bh)); + cbs.process_response = process_response_from_post_file_log_collection; + cbs.process_io_error = process_io_error_upload_log_collection; + cbs.process_auth_requested = process_auth_requested_upload_log_collection; + l = belle_http_request_listener_create_from_callbacks(&cbs, core); + belle_http_provider_send_request(core->http_provider, req, l); + } + if (code == 200) { /* The file has been uploaded correctly, get the server reply */ + xmlDocPtr xmlMessageBody; + xmlNodePtr cur; + xmlChar *file_url = NULL; + const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response); + xmlMessageBody = xmlParseDoc((const xmlChar *)body); + cur = xmlDocGetRootElement(xmlMessageBody); + if (cur != NULL) { + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { /* we found a file info node, check it has a type="file" attribute */ + xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); + if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */ + cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */ + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) { + file_url = xmlGetProp(cur, (const xmlChar *)"url"); + } + cur=cur->next; + } + xmlFree(typeAttribute); + break; + } + xmlFree(typeAttribute); + } + cur = cur->next; + } + } + if (file_url != NULL) { + linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateDelivered, (const char *)file_url); + } + delete_log_collection_upload_file(); + } + } } -int linphone_core_get_current_call_duration(const LinphoneCore *lc){ - LinphoneCall *call=linphone_core_get_current_call((LinphoneCore *)lc); - if (call) return linphone_call_get_duration(call); - return -1; -} +#ifdef HAVE_ZLIB +#define COMPRESS_FILE_PTR gzFile +#define COMPRESS_OPEN gzopen +#define COMPRESS_CLOSE gzclose +#else +#define COMPRESS_FILE_PTR FILE* +#define COMPRESS_OPEN fopen +#define COMPRESS_CLOSE fclose +#endif -const LinphoneAddress *linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc){ - LinphoneCall *call=linphone_core_get_current_call(lc); - if (call==NULL) return NULL; - return linphone_call_get_remote_address(call); +/** + * If zlib is not available the two log files are simply concatenated. + */ +static int compress_file(FILE *input_file, COMPRESS_FILE_PTR output_file) { + char buffer[131072]; /* 128kB */ + int bytes; + + while ((bytes = fread(buffer, 1, sizeof(buffer), input_file)) > 0) { + if (bytes < 0) return bytes; +#ifdef HAVE_ZLIB + bytes = gzwrite(output_file, buffer, bytes); +#else + bytes = fwrite(buffer, 1, bytes, output_file); +#endif + if (bytes < 0) return bytes; + } + return 0; } -void linphone_core_set_log_handler(OrtpLogFunc logfunc) { - ortp_set_log_handler(logfunc); +static int prepare_log_collection_file_to_upload(const char *filename) { + char *input_filename = NULL; + char *output_filename = NULL; + FILE *input_file = NULL; + COMPRESS_FILE_PTR output_file = NULL; + int ret = 0; + + ortp_mutex_lock(&liblinphone_log_collection_mutex); + output_filename = ms_strdup_printf("%s/%s", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, filename); + output_file = COMPRESS_OPEN(output_filename, "w"); + if (output_file == NULL) goto error; + input_filename = ms_strdup_printf("%s/%s1.log", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX); + input_file = fopen(input_filename, "r"); + if (input_file == NULL) goto error; + ret = compress_file(input_file, output_file); + if (ret < 0) goto error; + fclose(input_file); + ms_free(input_filename); + input_filename = ms_strdup_printf("%s/%s2.log", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX); + input_file = fopen(input_filename, "r"); + if (input_file != NULL) { + ret = compress_file(input_file, output_file); + if (ret < 0) goto error; + } + +error: + if (input_file != NULL) fclose(input_file); + if (output_file != NULL) COMPRESS_CLOSE(output_file); + if (input_filename != NULL) ms_free(input_filename); + if (output_filename != NULL) ms_free(output_filename); + ortp_mutex_unlock(&liblinphone_log_collection_mutex); + return ret; } -void linphone_core_set_log_file(FILE *file) { - if (file == NULL) file = stdout; - ortp_set_log_file(file); +static size_t get_size_of_file_to_upload(const char *filename) { + struct stat statbuf; + char *output_filename = ms_strdup_printf("%s/%s", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, filename); + FILE *output_file = fopen(output_filename, "rb"); + fstat(fileno(output_file), &statbuf); + fclose(output_file); + ms_free(output_filename); + return statbuf.st_size; +} + +void linphone_core_upload_log_collection(LinphoneCore *core) { + if ((core->log_collection_upload_information == NULL) && (linphone_core_get_log_collection_upload_server_url(core) != NULL) && (liblinphone_log_collection_state != LinphoneLogCollectionDisabled)) { + /* open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */ + belle_http_request_listener_callbacks_t cbs = { 0 }; + belle_http_request_listener_t *l; + belle_generic_uri_t *uri; + belle_http_request_t *req; + + core->log_collection_upload_information = (LinphoneContent *)malloc(sizeof(LinphoneContent)); + memset(core->log_collection_upload_information, 0, sizeof(LinphoneContent)); +#ifdef HAVE_ZLIB + core->log_collection_upload_information->type = "application"; + core->log_collection_upload_information->subtype = "gzip"; +#else + core->log_collection_upload_information->type = "text"; + core->log_collection_upload_information->subtype = "plain"; +#endif + core->log_collection_upload_information->name = ms_strdup_printf("%s_log.%s", + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX, + COMPRESSED_LOG_COLLECTION_EXTENSION); + if (prepare_log_collection_file_to_upload(core->log_collection_upload_information->name) < 0) return; + core->log_collection_upload_information->size = get_size_of_file_to_upload(core->log_collection_upload_information->name); + uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core)); + req = belle_http_request_create("POST", uri, NULL, NULL, NULL); + cbs.process_response = process_response_from_post_file_log_collection; + cbs.process_io_error = process_io_error_upload_log_collection; + cbs.process_auth_requested = process_auth_requested_upload_log_collection; + l = belle_http_request_listener_create_from_callbacks(&cbs, core); + belle_http_provider_send_request(core->http_provider, req, l); + } +} + +char * linphone_core_compress_log_collection(LinphoneCore *core) { + char *filename = NULL; + if (liblinphone_log_collection_state == LinphoneLogCollectionDisabled) return NULL; + filename = ms_strdup_printf("%s_log.%s", + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX, + COMPRESSED_LOG_COLLECTION_EXTENSION); + if (prepare_log_collection_file_to_upload(filename) < 0) { + ms_free(filename); + return NULL; + } + ms_free(filename); + return ms_strdup_printf("%s/%s_log.%s", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX, + COMPRESSED_LOG_COLLECTION_EXTENSION); } -void linphone_core_set_log_level(OrtpLogLevel loglevel) { - ortp_set_log_level_mask(loglevel); - if (loglevel == 0) { - sal_disable_logs(); - } else { - sal_enable_logs(); - } +void linphone_core_reset_log_collection(LinphoneCore *core) { + char *filename; + ortp_mutex_lock(&liblinphone_log_collection_mutex); + delete_log_collection_upload_file(); + filename = ms_strdup_printf("%s/%s1.log", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX); + unlink(filename); + ms_free(filename); + filename = ms_strdup_printf("%s/%s2.log", + liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, + liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX); + unlink(filename); + ms_free(filename); + ortp_mutex_unlock(&liblinphone_log_collection_mutex); } /** @@ -725,6 +892,7 @@ static void sip_config_read(LinphoneCore *lc) LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc,i); if (cfg!=NULL){ linphone_core_add_proxy_config(lc,cfg); + linphone_proxy_config_unref(cfg); }else{ break; } @@ -762,6 +930,7 @@ static void sip_config_read(LinphoneCore *lc) sal_enable_sip_update_method(lc->sal,lp_config_get_int(lc->config,"sip","sip_update",1)); lc->sip_conf.vfu_with_info=lp_config_get_int(lc->config,"sip","vfu_with_info",1); linphone_core_set_sip_transport_timeout(lc, lp_config_get_int(lc->config, "sip", "transport_timeout", 63000)); + sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound")); } static void rtp_config_read(LinphoneCore *lc) @@ -804,6 +973,7 @@ static void rtp_config_read(LinphoneCore *lc) adaptive_jitt_comp_enabled = lp_config_get_int(lc->config, "rtp", "video_adaptive_jitt_comp_enabled", TRUE); linphone_core_enable_video_adaptive_jittcomp(lc, adaptive_jitt_comp_enabled); lc->rtp_conf.disable_upnp = lp_config_get_int(lc->config, "rtp", "disable_upnp", FALSE); + linphone_core_set_avpf_mode(lc,lp_config_get_int(lc->config,"rtp","avpf",0)); } static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, int channels, const char *recv_fmtp){ @@ -955,6 +1125,7 @@ static void codecs_config_read(LinphoneCore *lc) } } audio_codecs=add_missing_codecs(lc,SalAudio,audio_codecs); + for (i=0;get_codec(lc,"video_codec",i,&pt);i++){ if (pt){ if (!ms_filter_codec_supported(pt->mime_type)){ @@ -988,7 +1159,7 @@ static void build_video_devices_table(LinphoneCore *lc){ static void video_config_read(LinphoneCore *lc){ #ifdef VIDEO_ENABLED - int capture, display, self_view; + int capture, display, self_view, reuse_source; int automatic_video=1; #endif const char *str; @@ -1017,12 +1188,14 @@ static void video_config_read(LinphoneCore *lc){ capture=lp_config_get_int(lc->config,"video","capture",1); display=lp_config_get_int(lc->config,"video","display",1); self_view=lp_config_get_int(lc->config,"video","self_view",1); + reuse_source=lp_config_get_int(lc->config,"video","reuse_source",0); vpol.automatically_initiate=lp_config_get_int(lc->config,"video","automatically_initiate",automatic_video); vpol.automatically_accept=lp_config_get_int(lc->config,"video","automatically_accept",automatic_video); linphone_core_enable_video_capture(lc, capture); linphone_core_enable_video_display(lc, display); linphone_core_enable_video_preview(lc,lp_config_get_int(lc->config,"video","show_local",0)); linphone_core_enable_self_view(lc,self_view); + linphone_core_enable_video_source_reuse(lc, reuse_source); linphone_core_set_video_policy(lc,&vpol); #endif } @@ -1083,6 +1256,28 @@ bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"net","adaptive_rate_control",TRUE); } +/** + * Sets adaptive rate algorithm. It will be used for each new calls starting from + * now. Calls already started will not be updated. + * + * @ingroup media_parameters + * +**/ +void linphone_core_set_adaptive_rate_algorithm(LinphoneCore *lc, const char* algorithm){ + lp_config_set_string(lc->config,"net","adaptive_rate_algorithm",algorithm); +} + +/** + * Returns which adaptive rate algorithm is currently configured for future calls. + * + * @ingroup media_parameters + * + * See linphone_core_set_adaptive_rate_algorithm(). +**/ +const char * linphone_core_get_adaptive_rate_algorithm(const LinphoneCore *lc){ + return lp_config_get_string(lc->config, "net", "adaptive_rate_algorithm", "Simple"); +} + bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE); } @@ -1267,9 +1462,7 @@ static void linphone_core_free_payload_types(LinphoneCore *lc){ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message){ lc->state=gstate; - if (lc->vtable.global_state_changed){ - lc->vtable.global_state_changed(lc,gstate,message); - } + linphone_core_notify_global_state_changed(lc,gstate,message); } static void misc_config_read(LinphoneCore *lc) { @@ -1302,18 +1495,18 @@ static void linphone_core_start(LinphoneCore * lc) { ui_config_read(lc); #ifdef TUNNEL_ENABLED lc->tunnel=linphone_core_tunnel_new(lc); - if (lc->tunnel) linphone_tunnel_configure(lc->tunnel); + if (lc->tunnel) { + linphone_tunnel_configure(lc->tunnel); + } #endif - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Ready")); + linphone_core_notify_display_status(lc,_("Ready")); lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon; linphone_core_set_state(lc,LinphoneGlobalOn,"Ready"); } void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message) { - if (lc->vtable.configuring_status) - lc->vtable.configuring_status(lc, state, message); + linphone_core_notify_configuring_status(lc, state, message); if (state == LinphoneConfiguringSuccessful) { if (linphone_core_is_provisioning_transient(lc) == TRUE) @@ -1326,13 +1519,16 @@ void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata) { const char *remote_provisioning_uri = NULL; + const char *aac_fmtp162248, *aac_fmtp3244; + LinphoneCoreVTable* local_vtable= linphone_core_v_table_new(); ms_message("Initializing LinphoneCore %s", linphone_core_get_version()); memset (lc, 0, sizeof (LinphoneCore)); lc->config=lp_config_ref(config); lc->data=userdata; lc->ringstream_autorelease=TRUE; - memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable)); + memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable)); + lc->vtables=ms_list_append(lc->vtables,local_vtable); linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up"); ortp_init(); @@ -1370,17 +1566,29 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_core_assign_payload_type(lc,&payload_type_h264,102,"profile-level-id=42801F"); linphone_core_assign_payload_type(lc,&payload_type_vp8,103,NULL); - linphone_core_assign_payload_type(lc,&payload_type_theora,97,NULL); - linphone_core_assign_payload_type(lc,&payload_type_x_snow,-1,NULL); + /* linphone_core_assign_payload_type(lc,&payload_type_theora,97,NULL); commented out to free 1 slot */ + /* linphone_core_assign_payload_type(lc,&payload_type_x_snow,-1,NULL); commented out to free 1 slot */ /* due to limited space in SDP, we have to disable this h264 line which is normally no more necessary */ /* linphone_core_assign_payload_type(&payload_type_h264,-1,"packetization-mode=1;profile-level-id=428014");*/ #endif + /* For AAC, we use a config value to determine if we ought to support SBR. Since it is not offically supported + * for the mpeg4-generic mime type, setting this flag to 1 will break compatibility with other clients. */ + if( lp_config_get_int(lc->config, "misc", "aac_use_sbr", FALSE) ) { + ms_message("Using SBR for AAC"); + aac_fmtp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5; SBR-enabled=1"; + aac_fmtp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5; SBR-enabled=1"; + } else { + aac_fmtp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5"; + aac_fmtp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5"; + } + + /*add all payload type for which we don't care about the number */ linphone_core_assign_payload_type(lc,&payload_type_ilbc,-1,"mode=30"); linphone_core_assign_payload_type(lc,&payload_type_amr,-1,"octet-align=1"); linphone_core_assign_payload_type(lc,&payload_type_amrwb,-1,"octet-align=1"); - linphone_core_assign_payload_type(lc,&payload_type_lpc1015,-1,NULL); + /* linphone_core_assign_payload_type(lc,&payload_type_lpc1015,-1,NULL); commented out to free 1 slot */ linphone_core_assign_payload_type(lc,&payload_type_g726_16,-1,NULL); linphone_core_assign_payload_type(lc,&payload_type_g726_24,-1,NULL); linphone_core_assign_payload_type(lc,&payload_type_g726_32,-1,NULL); @@ -1394,8 +1602,11 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_core_assign_payload_type(lc,&payload_type_silk_wb,-1,NULL); linphone_core_assign_payload_type(lc,&payload_type_silk_swb,-1,NULL); linphone_core_assign_payload_type(lc,&payload_type_g729,18,"annexb=no"); - linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,"config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5"); - linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,"config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5"); + linphone_core_assign_payload_type(lc,&payload_type_aaceld_16k,-1,aac_fmtp162248); + linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,aac_fmtp162248); + linphone_core_assign_payload_type(lc,&payload_type_aaceld_32k,-1,aac_fmtp3244); + linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,aac_fmtp3244); + linphone_core_assign_payload_type(lc,&payload_type_aaceld_48k,-1,aac_fmtp162248); linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; stereo=0; sprop-stereo=0"); linphone_core_assign_payload_type(lc,&payload_type_isac,-1,NULL); linphone_core_handle_static_payloads(lc); @@ -1418,8 +1629,6 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab lc->http_verify_policy = belle_tls_verify_policy_new(); belle_http_provider_set_tls_verify_policy(lc->http_provider,lc->http_verify_policy); - lc->file_transfer_server = NULL; - certificates_config_read(lc); remote_provisioning_uri = linphone_core_get_provisioning_uri(lc); @@ -1466,6 +1675,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. @@ -1480,6 +1691,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. @@ -1518,44 +1731,6 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact) } -/*Returns the local ip that routes to the internet, or guessed by other special means (upnp)*/ -/*result must be an array of chars at least LINPHONE_IPADDR_SIZE */ -void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){ - const char *ip; - if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress - && (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){ - strncpy(result,ip,LINPHONE_IPADDR_SIZE); - return; - } -#ifdef BUILD_UPNP - else if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp && - linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) { - ip = linphone_upnp_context_get_external_ipaddress(lc->upnp); - strncpy(result,ip,LINPHONE_IPADDR_SIZE); - return; - } -#endif //BUILD_UPNP - if (af==AF_UNSPEC){ - if (linphone_core_ipv6_enabled(lc)){ - bool_t has_ipv6; - has_ipv6=linphone_core_get_local_ip_for(AF_INET6,NULL,result)==0; - if (strcmp(result,"::1")!=0) - return; /*this machine has real ipv6 connectivity*/ - if (linphone_core_get_local_ip_for(AF_INET,NULL,result)==0 && strcmp(result,"127.0.0.1")!=0) - return; /*this machine has only ipv4 connectivity*/ - if (has_ipv6){ - /*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/ - strncpy(result,"::1",LINPHONE_IPADDR_SIZE); - return; - } - } - /*in all other cases use IPv4*/ - af=AF_INET; - } - if (linphone_core_get_local_ip_for(af,NULL,result)==0) - return; -} - static void update_primary_contact(LinphoneCore *lc){ char *guessed=NULL; char tmp[LINPHONE_IPADDR_SIZE]; @@ -1570,7 +1745,7 @@ static void update_primary_contact(LinphoneCore *lc){ ms_error("Could not parse identity contact !"); url=linphone_address_new("sip:unknown@unkwownhost"); } - linphone_core_get_local_ip(lc, AF_UNSPEC, tmp); + linphone_core_get_local_ip(lc, AF_UNSPEC, NULL, tmp); if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){ ms_warning("Local loopback network only !"); lc->sip_conf.loopback_only=TRUE; @@ -1631,6 +1806,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. @@ -1646,6 +1824,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. @@ -1763,24 +1944,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){ @@ -1890,35 +2100,14 @@ void linphone_core_set_use_rfc2833_for_dtmf(LinphoneCore *lc,bool_t use_rfc2833) * Deprecated: use linphone_core_get_sip_transports() instead. * @ingroup network_parameters **/ -int linphone_core_get_sip_port(LinphoneCore *lc) -{ +int linphone_core_get_sip_port(LinphoneCore *lc){ LCSipTransports tr; linphone_core_get_sip_transports_used(lc,&tr); return tr.udp_port>0 ? tr.udp_port : (tr.tcp_port > 0 ? tr.tcp_port : tr.tls_port); } -#if !USE_BELLE_SIP static char _ua_name[64]="Linphone"; -static char _ua_version[64]=LINPHONE_VERSION; -#endif - -#if HAVE_EXOSIP_GET_VERSION && !USE_BELLESIP -extern const char *eXosip_get_version(); -#endif - -static void apply_user_agent(LinphoneCore *lc){ -#if !USE_BELLESIP /*default user agent is handled at sal level*/ - char ua_string[256]; - snprintf(ua_string,sizeof(ua_string)-1,"%s/%s (eXosip2/%s)",_ua_name,_ua_version, -#if HAVE_EXOSIP_GET_VERSION - eXosip_get_version() -#else - "unknown" -#endif - ); - if (lc->sal) sal_set_user_agent(lc->sal,ua_string); -#endif -} +static char _ua_version[64]=LIBLINPHONE_VERSION; /** * Sets the user agent string used in SIP messages. @@ -1926,27 +2115,15 @@ static void apply_user_agent(LinphoneCore *lc){ * @ingroup misc **/ void linphone_core_set_user_agent(LinphoneCore *lc, const char *name, const char *ver){ -#if USE_BELLESIP char ua_string[256]; snprintf(ua_string, sizeof(ua_string) - 1, "%s/%s", name?name:"", ver?ver:""); if (lc->sal) { sal_set_user_agent(lc->sal, ua_string); sal_append_stack_string_to_user_agent(lc->sal); } -#else - strncpy(_ua_name,name,sizeof(_ua_name)-1); - strncpy(_ua_version,ver,sizeof(_ua_version)); - apply_user_agent(lc); -#endif } const char *linphone_core_get_user_agent(LinphoneCore *lc){ -#if USE_BELLESIP return sal_get_user_agent(lc->sal); -#else - static char ua_buffer[255] = {0}; - snprintf(ua_buffer, "%s/%s", _ua_name, _ua_version, 254); - return ua_buffer; -#endif } const char *linphone_core_get_user_agent_name(void){ @@ -1960,8 +2137,7 @@ const char *linphone_core_get_user_agent_version(void){ static void transport_error(LinphoneCore *lc, const char* transport, int port){ char *msg=ortp_strdup_printf("Could not start %s transport on port %i, maybe this port is already used.",transport,port); ms_warning("%s",msg); - if (lc->vtable.display_warning) - lc->vtable.display_warning(lc,msg); + linphone_core_notify_display_warning(lc,msg); ms_free(msg); } @@ -2004,7 +2180,6 @@ static int apply_transports(LinphoneCore *lc){ } } } - apply_user_agent(lc); return 0; } @@ -2131,7 +2306,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){ /* only do the network up checking every five seconds */ if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){ - linphone_core_get_local_ip(lc,AF_UNSPEC,newip); + linphone_core_get_local_ip(lc,AF_UNSPEC,NULL,newip); if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){ new_status=TRUE; }else new_status=FALSE; /*no network*/ @@ -2161,10 +2336,11 @@ static void proxy_update(LinphoneCore *lc){ for(elem=lc->sip_conf.deleted_proxies;elem!=NULL;elem=next){ LinphoneProxyConfig* cfg = (LinphoneProxyConfig*)elem->data; next=elem->next; - if (ms_time(NULL) - cfg->deletion_date > 5) { + if (ms_time(NULL) - cfg->deletion_date > 32) { lc->sip_conf.deleted_proxies =ms_list_remove_link(lc->sip_conf.deleted_proxies,elem); - ms_message("clearing proxy config for [%s]",linphone_proxy_config_get_addr(cfg)); - linphone_proxy_config_destroy(cfg); + ms_message("Proxy config for [%s] is definitely removed from core.",linphone_proxy_config_get_addr(cfg)); + _linphone_proxy_config_release_ops(cfg); + linphone_proxy_config_unref(cfg); } } } @@ -2174,8 +2350,7 @@ static void assign_buddy_info(LinphoneCore *lc, BuddyInfo *info){ if (lf!=NULL){ lf->info=info; ms_message("%s has a BuddyInfo assigned with image %p",info->sip_uri, info->image_data); - if (lc->vtable.buddy_info_updated) - lc->vtable.buddy_info_updated(lc,lf); + linphone_core_notify_buddy_info_updated(lc,lf); }else{ ms_warning("Could not any friend with uri %s",info->sip_uri); } @@ -2261,7 +2436,10 @@ void linphone_core_iterate(LinphoneCore *lc){ int elapsed; bool_t one_second_elapsed=FALSE; const char *remote_provisioning_uri = NULL; - + if (lc->network_reachable_to_be_notified) { + lc->network_reachable_to_be_notified=FALSE; + linphone_core_notify_network_reachable(lc,lc->network_reachable); + } if (linphone_core_get_global_state(lc) == LinphoneGlobalStartup) { if (sal_get_root_ca(lc->sal)) { belle_tls_verify_policy_t *tls_policy = belle_tls_verify_policy_new(); @@ -2269,8 +2447,7 @@ void linphone_core_iterate(LinphoneCore *lc){ belle_http_provider_set_tls_verify_policy(lc->http_provider, tls_policy); } - if (lc->vtable.display_status) - lc->vtable.display_status(lc, _("Configuring")); + linphone_core_notify_display_status(lc, _("Configuring")); linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring"); remote_provisioning_uri = linphone_core_get_provisioning_uri(lc); @@ -2371,8 +2548,8 @@ void linphone_core_iterate(LinphoneCore *lc){ } } if ( (lc->sip_conf.in_call_timeout > 0) - && (call->media_start_time != 0) - && ((curtime - call->media_start_time) > lc->sip_conf.in_call_timeout)) + && (call->log->connected_date_time != 0) + && ((curtime - call->log->connected_date_time) > lc->sip_conf.in_call_timeout)) { ms_message("in call timeout (%i)",lc->sip_conf.in_call_timeout); linphone_core_terminate_call(lc,call); @@ -2435,11 +2612,9 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url) if (*url=='\0') return NULL; if (is_enum(url,&enum_domain)){ - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Looking for telephone number destination...")); + linphone_core_notify_display_status(lc,_("Looking for telephone number destination...")); if (enum_lookup(enum_domain,&enumres)<0){ - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Could not resolve this number.")); + linphone_core_notify_display_status(lc,_("Could not resolve this number.")); ms_free(enum_domain); return NULL; } @@ -2536,7 +2711,7 @@ LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall * } if (!params){ - cp->has_video = call->current_params.has_video; /*start the call to refer-target with video enabled if original call had video*/ + cp->has_video = call->current_params->has_video; /*start the call to refer-target with video enabled if original call had video*/ } cp->referer=call; ms_message("Starting new call to refered address %s",call->refer_to); @@ -2722,13 +2897,11 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const Linph call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/ barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url); - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,barmsg); + linphone_core_notify_display_status(lc,barmsg); ms_free(barmsg); if (err<0){ - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Could not call")); + linphone_core_notify_display_status(lc,_("Could not call")); linphone_call_stop_media_streams(call); linphone_call_set_state(call,LinphoneCallError,"Call failed"); }else { @@ -2878,8 +3051,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const linphone_core_preempt_sound_resources(lc); if(!linphone_core_can_we_add_call(lc)){ - if (lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls")); + linphone_core_notify_display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls")); return NULL; } @@ -2890,6 +3062,9 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const from=linphone_proxy_config_get_identity(proxy); cp->avpf_enabled = linphone_proxy_config_avpf_enabled(proxy); cp->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(proxy) * 1000; + }else{ + cp->avpf_enabled=linphone_core_get_avpf_mode(lc)==LinphoneAVPFEnabled; + if (cp->avpf_enabled) cp->avpf_rr_interval=linphone_core_get_avpf_rr_interval(lc) * 1000; } /* if no proxy or no identity defined for this proxy, default to primary contact*/ @@ -2910,15 +3085,15 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const /* this call becomes now the current one*/ lc->current_call=call; linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); - call->log->start_date_time=time(NULL); + call->log->start_date_time=ms_time(NULL); linphone_call_init_media_streams(call); - if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { + if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { /* Defer the start of the call after the ICE gathering process. */ if (linphone_call_prepare_ice(call,FALSE)==1) defer=TRUE; } - else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) { + else if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) { #ifdef BUILD_UPNP if (linphone_core_update_upnp(lc,call)<0) { /* uPnP port mappings failed, proceed with the call anyway. */ @@ -3009,7 +3184,7 @@ int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, return result; } -bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){ +bool_t linphone_core_is_incoming_invite_pending(LinphoneCore*lc){ LinphoneCall *call = linphone_core_get_current_call(lc); if(call != NULL) { @@ -3038,8 +3213,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ if (md){ if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){ sal_call_decline(call->op,SalReasonNotAcceptable,NULL); - linphone_call_stop_media_streams(call); - linphone_core_del_call(lc,call); + linphone_call_set_state_base(call, LinphoneCallError, NULL,TRUE); linphone_call_unref(call); return; } @@ -3051,9 +3225,8 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ linphone_address_destroy(from_parsed); barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"), (sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_(".")); - if (lc->vtable.show) lc->vtable.show(lc); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,barmesg); + linphone_core_notify_show_interface(lc); + linphone_core_notify_display_status(lc,barmesg); /* play the ring if this is the only call*/ if (ms_list_size(lc->calls)==1){ @@ -3119,7 +3292,7 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* // if parameters are passed, update the media description if ( params ) { - _linphone_call_params_copy ( &call->params,params ); + linphone_call_set_new_params(call,params); linphone_call_make_local_media_description ( lc,call ); sal_call_set_local_media_description ( call->op,call->localdesc ); sal_op_set_sent_custom_header ( call->op,params->custom_headers ); @@ -3153,26 +3326,39 @@ int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call){ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){ const char *subject; + int err; + bool_t no_user_consent=call->params->no_user_consent; - linphone_call_make_local_media_description(lc,call); + if (!no_user_consent) linphone_call_make_local_media_description(lc,call); #ifdef BUILD_UPNP if(call->upnp_session != NULL) { linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); } #endif //BUILD_UPNP - if (call->params.in_conference){ + if (call->params->in_conference){ subject="Conference"; - }else{ + }else if (!no_user_consent){ subject="Media change"; + }else{ + subject="Refreshing"; + } + linphone_core_notify_display_status(lc,_("Modifying call parameters...")); + if (!lc->sip_conf.sdp_200_ack){ + sal_call_set_local_media_description (call->op,call->localdesc); + } else { + sal_call_set_local_media_description (call->op,NULL); } - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Modifying call parameters...")); - sal_call_set_local_media_description (call->op,call->localdesc); if (call->dest_proxy && call->dest_proxy->op){ /*give a chance to update the contact address if connectivity has changed*/ sal_op_set_contact_address(call->op,sal_op_get_contact_address(call->dest_proxy->op)); }else sal_op_set_contact_address(call->op,NULL); - return sal_call_update(call->op,subject); + err= sal_call_update(call->op,subject,no_user_consent); + if (lc->sip_conf.sdp_200_ack){ + /*we are NOT offering, set local media description after sending the call so that we are ready to + process the remote offer when it will arrive*/ + sal_call_set_local_media_description(call->op,call->localdesc); + } + return err; } /** @@ -3191,15 +3377,20 @@ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){ **/ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ int err=0; + LinphoneCallState nextstate; #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) bool_t has_video = FALSE; #endif switch(call->state){ - case LinphoneCallIncomingEarlyMedia: case LinphoneCallIncomingReceived: + case LinphoneCallIncomingEarlyMedia: + case LinphoneCallOutgoingRinging: + case LinphoneCallOutgoingEarlyMedia: + nextstate=LinphoneCallEarlyUpdating; + break; case LinphoneCallStreamsRunning: - /*these states are allowed for linphone_core_update_call()*/ + nextstate=LinphoneCallUpdating; break; default: ms_error("linphone_core_update_call() is not allowed in [%s] state",linphone_call_state_to_string(call->state)); @@ -3207,9 +3398,9 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho } if (params!=NULL){ - linphone_call_set_state(call,LinphoneCallUpdating,"Updating call"); + linphone_call_set_state(call,nextstate,"Updating call"); #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) - has_video = call->params.has_video; + has_video = call->params->has_video; // Video removing if((call->videostream != NULL) && !params->has_video) { @@ -3222,8 +3413,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho } #endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */ - - _linphone_call_params_copy(&call->params,params); + linphone_call_set_new_params(call,params); err=linphone_call_prepare_ice(call,FALSE); if (err==1) { ms_message("Defer call update to gather ICE candidates"); @@ -3232,7 +3422,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) // Video adding - if (!has_video && call->params.has_video) { + if (!has_video && call->params->has_video) { if(call->upnp_session != NULL) { ms_message("Defer call update to add uPnP port mappings"); video_stream_prepare_video(call->videostream); @@ -3250,6 +3440,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); @@ -3283,7 +3474,7 @@ int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){ return -1; } -int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call){ +int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState next_state, const char *state_info){ SalMediaDescription *md; if (call->ice_session != NULL) { if (ice_session_nb_losing_pairs(call->ice_session) > 0) { @@ -3301,8 +3492,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call) linphone_core_update_streams (lc,call,md); linphone_call_fix_call_parameters(call); } - if (call->state != LinphoneCallOutgoingEarlyMedia) /*don't change the state in case of outgoing early (SIP UPDATE)*/ - linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); + linphone_call_set_state(call,next_state,state_info); return 0; } @@ -3331,14 +3521,14 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const linphone_call_state_to_string(call->state)); return -1; } - return _linphone_core_accept_call_update(lc, call, params); + return _linphone_core_accept_call_update(lc, call, params, call->prevstate, linphone_call_state_to_string(call->prevstate)); } -int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ +int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info){ SalMediaDescription *remote_desc; bool_t keep_sdp_version; #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) - bool_t old_has_video = call->params.has_video; + bool_t old_has_video = call->params->has_video; #endif remote_desc = sal_call_get_remote_media_description(call->op); @@ -3347,23 +3537,23 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons /* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */ ms_warning("SDP version has not changed, send same SDP as before."); sal_call_accept(call->op); - linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); + linphone_call_set_state(call,next_state,state_info); return 0; } if (params==NULL){ - call->params.has_video=lc->video_policy.automatically_accept || call->current_params.has_video; + call->params->has_video=lc->video_policy.automatically_accept || call->current_params->has_video; }else - _linphone_call_params_copy(&call->params,params); + linphone_call_set_new_params(call,params); - if (call->params.has_video && !linphone_core_video_enabled(lc)){ + if (call->params->has_video && !linphone_core_video_enabled(lc)){ ms_warning("linphone_core_accept_call_update(): requested video but video support is globally disabled. Refusing video."); - call->params.has_video=FALSE; + call->params->has_video=FALSE; } - if (call->current_params.in_conference) { + if (call->current_params->in_conference) { ms_warning("Video isn't supported in conference"); - call->params.has_video = FALSE; + call->params->has_video = FALSE; } - call->params.has_video &= linphone_core_media_description_contains_video_stream(remote_desc); + call->params->has_video &= linphone_core_media_description_contains_video_stream(remote_desc); linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/ if (call->ice_session != NULL) { if (linphone_call_prepare_ice(call,TRUE)==1) @@ -3374,7 +3564,7 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons if(call->upnp_session != NULL) { linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op)); #ifdef VIDEO_ENABLED - if ((call->params.has_video) && (call->params.has_video != old_has_video)) { + if ((call->params->has_video) && (call->params->has_video != old_has_video)) { video_stream_prepare_video(call->videostream); if (linphone_core_update_upnp(lc, call)<0) { /* uPnP update failed, proceed with the call anyway. */ @@ -3385,7 +3575,7 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons } #endif //BUILD_UPNP - linphone_core_start_accept_call_update(lc, call); + linphone_core_start_accept_call_update(lc, call, next_state, state_info); return 0; } @@ -3419,8 +3609,7 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call){ * @param params the specific parameters for this call, for example whether video is accepted or not. Use NULL to use default parameters. * **/ -int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) -{ +int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ SalOp *replaced; SalMediaDescription *new_md; bool_t was_ringing=FALSE; @@ -3433,9 +3622,15 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, call = (LinphoneCall*)linphone_core_get_calls(lc)->data; } - if (call->state==LinphoneCallConnected){ - /*call already accepted*/ - return -1; + switch(call->state){ + case LinphoneCallIncomingReceived: + case LinphoneCallIncomingEarlyMedia: + break; + default: + ms_error("linphone_core_accept_call_with_params() call [%p] is in state [%s], operation not permitted.", + call, linphone_call_state_to_string(call->state)); + return -1; + break; } /* check if this call is supposed to replace an already running one*/ @@ -3468,7 +3663,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, linphone_call_set_contact_op(call); if (params){ const SalMediaDescription *md = sal_call_get_remote_media_description(call->op); - _linphone_call_params_copy(&call->params,params); + linphone_call_set_new_params(call,params); // There might not be a md if the INVITE was lacking an SDP // In this case we use the parameters as is. if (md) { @@ -3495,8 +3690,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, linphone_call_update_remote_session_id_and_ver(call); sal_call_accept(call->op); - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Connected.")); + linphone_core_notify_display_status(lc,_("Connected.")); lc->current_call=call; linphone_call_set_state(call,LinphoneCallConnected,"Connected"); new_md=sal_call_get_final_media_description(call->op); @@ -3521,8 +3715,7 @@ int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *e linphone_call_delete_upnp_session(call); #endif //BUILD_UPNP - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Call aborted") ); + linphone_core_notify_display_status(lc,_("Call aborted") ); linphone_call_set_state(call,LinphoneCallError,error); return 0; } @@ -3541,8 +3734,7 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ linphone_call_delete_upnp_session(call); #endif //BUILD_UPNP - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Call ended") ); + linphone_core_notify_display_status(lc,_("Call ended") ); linphone_call_set_state(call,LinphoneCallEnd,"Call terminated"); } @@ -3642,6 +3834,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. @@ -3710,14 +3904,12 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) return -1; } sal_call_set_local_media_description(call->op,call->localdesc); - if (sal_call_update(call->op,subject) != 0){ - if (lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("Could not pause the call")); + if (sal_call_update(call->op,subject,FALSE) != 0){ + linphone_core_notify_display_warning(lc,_("Could not pause the call")); } lc->current_call=NULL; linphone_call_set_state(call,LinphoneCallPausing,"Pausing call"); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Pausing the current call...")); + linphone_core_notify_display_status(lc,_("Pausing the current call...")); if (call->audiostream || call->videostream) linphone_call_stop_media_streams (call); call->paused_by_app=FALSE; @@ -3771,7 +3963,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){ ms_warning("we cannot resume a call that has not been established and paused before"); return -1; } - if (call->params.in_conference==FALSE){ + if (call->params->in_conference==FALSE){ if (linphone_core_sound_resources_locked(lc)){ ms_warning("Cannot resume call %p because another call is locking the sound resources.",call); return -1; @@ -3794,16 +3986,15 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){ #endif //BUILD_UPNP sal_call_set_local_media_description(call->op,call->localdesc); sal_media_description_set_dir(call->localdesc,SalStreamSendRecv); - if (call->params.in_conference && !call->current_params.in_conference) subject="Conference"; - if(sal_call_update(call->op,subject) != 0){ + if (call->params->in_conference && !call->current_params->in_conference) subject="Conference"; + if ( sal_call_update(call->op,subject,FALSE) != 0){ return -1; } linphone_call_set_state(call,LinphoneCallResuming,"Resuming"); - if (call->params.in_conference==FALSE) + if (call->params->in_conference==FALSE) lc->current_call=call; snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call)); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,temp); + linphone_core_notify_display_status(lc,temp); return 0; } @@ -3823,6 +4014,7 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){ LinphoneAddress *raddr=linphone_address_new(remote_address); MSList *elem=ms_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr); + linphone_address_unref(raddr); if (elem) return (LinphoneCall*) elem->data; return NULL; } @@ -4087,9 +4279,7 @@ void linphone_core_set_mic_gain_db (LinphoneCore *lc, float gaindb){ ms_message("linphone_core_set_mic_gain_db(): no active call."); return; } - if (st->volsend){ - ms_filter_call_method(st->volsend,MS_VOLUME_SET_DB_GAIN,&gain); - }else ms_warning("Could not apply gain: gain control wasn't activated."); + set_mic_gain_db(st,gain); } /** @@ -4120,9 +4310,7 @@ void linphone_core_set_playback_gain_db (LinphoneCore *lc, float gaindb){ ms_message("linphone_core_set_playback_gain_db(): no active call."); return; } - if (st->volrecv){ - ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain); - }else ms_warning("Could not apply gain: gain control wasn't activated."); + set_playback_gain_db(st,gain); } /** @@ -4477,7 +4665,7 @@ void linphone_core_set_ringback(LinphoneCore *lc, const char *path){ if (lc->sound_conf.remote_ring!=0){ ms_free(lc->sound_conf.remote_ring); } - lc->sound_conf.remote_ring=ms_strdup(path); + lc->sound_conf.remote_ring=path?ms_strdup(path):NULL; } /** @@ -4490,7 +4678,10 @@ const char * linphone_core_get_ringback(const LinphoneCore *lc){ } /** - * Enables or disable echo cancellation. Value is saved an used for subsequent calls + * Enables or disable echo cancellation. Value is saved and used for subsequent calls. + * This actually controls software echo cancellation. If hardware echo cancellation is available, it will be always used and activated for calls, regardless + * of the value passed to this function. + * When hardware echo cancellation is available, the software one is of course not activated. * * @ingroup media_parameters **/ @@ -4518,26 +4709,28 @@ bool_t linphone_core_echo_limiter_enabled(const LinphoneCore *lc){ return lc->sound_conf.ea; } +static void linphone_core_mute_audio_stream(LinphoneCore *lc, AudioStream *st, bool_t val) { + audio_stream_set_mic_gain(st, + (val==TRUE) ? 0 : pow(10,lc->sound_conf.soft_mic_lev/10)); + if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){ + audio_stream_mute_rtp(st,val); + } +} + void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){ - LinphoneCall *call=linphone_core_get_current_call(lc); - AudioStream *st=NULL; + LinphoneCall *call; + const MSList *list; + const MSList *elem; + if (linphone_core_is_in_conference(lc)){ lc->conf_ctx.local_muted=val; - st=lc->conf_ctx.local_participant; - }else if (call==NULL){ - ms_warning("linphone_core_mute_mic(): No current call !"); - return; - }else{ - st=call->audiostream; - call->audio_muted=val; - } - if (st!=NULL){ - audio_stream_set_mic_gain(st, - (val==TRUE) ? 0 : pow(10,lc->sound_conf.soft_mic_lev/10)); - if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){ - audio_stream_mute_rtp(st,val); - } - + linphone_core_mute_audio_stream(lc, lc->conf_ctx.local_participant, val); + } + list = linphone_core_get_calls(lc); + for (elem = list; elem != NULL; elem = elem->next) { + call = (LinphoneCall *)elem->data; + call->audio_muted = val; + linphone_core_mute_audio_stream(lc, call->audiostream, val); } } @@ -4765,9 +4958,23 @@ void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy lp_config_set_string(lc->config,"net","firewall_policy",policy); } -LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc){ - const char *policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL); +ORTP_INLINE LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) { + return _linphone_core_get_firewall_policy_with_lie(lc, FALSE); +} +ORTP_INLINE LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc) { + return _linphone_core_get_firewall_policy_with_lie(lc, TRUE); +} + +LinphoneFirewallPolicy _linphone_core_get_firewall_policy_with_lie(const LinphoneCore *lc, bool_t lie){ + const char *policy; + if(lie) { + LinphoneTunnel *tunnel = linphone_core_get_tunnel(lc); + if(tunnel != NULL && linphone_tunnel_get_mode(tunnel)) { + return LinphonePolicyNoFirewall; + } + } + policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL); if ((policy == NULL) || (strcmp(policy, "0") == 0)) return LinphonePolicyNoFirewall; else if ((strcmp(policy, "nat_address") == 0) || (strcmp(policy, "1") == 0)) @@ -4782,23 +4989,19 @@ LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) return LinphonePolicyNoFirewall; } -/** - * Get the list of call logs (past calls). - * - * @ingroup call_logs -**/ + + +/******************************************************************************* + * Call log related functions * + ******************************************************************************/ + const MSList * linphone_core_get_call_logs(LinphoneCore *lc){ return lc->call_logs; } -/** - * Erase the call log. - * - * @ingroup call_logs -**/ void linphone_core_clear_call_logs(LinphoneCore *lc){ lc->missed_calls=0; - ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy); + ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref); lc->call_logs=ms_list_free(lc->call_logs); call_logs_write_to_config_file(lc); } @@ -4814,9 +5017,12 @@ void linphone_core_reset_missed_calls_count(LinphoneCore *lc) { void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl){ lc->call_logs = ms_list_remove(lc->call_logs, cl); call_logs_write_to_config_file(lc); - linphone_call_log_destroy(cl); + linphone_call_log_unref(cl); } + + + static void toggle_video_preview(LinphoneCore *lc, bool_t val){ #ifdef VIDEO_ENABLED if (val){ @@ -4891,6 +5097,18 @@ void linphone_core_enable_video_display(LinphoneCore *lc, bool_t enable) { reapply_network_bandwidth_settings(lc); } +void linphone_core_enable_video_source_reuse(LinphoneCore* lc, bool_t enable){ +#ifndef VIDEO_ENABLED + if (enable == TRUE) { + ms_warning("Cannot enable video display, this version of linphone was built without video support."); + } +#endif + lc->video_conf.reuse_preview_source = enable; + if( linphone_core_ready(lc) ){ + lp_config_set_int(lc->config, "video", "reuse_source", lc->video_conf.reuse_preview_source); + } +} + bool_t linphone_core_video_capture_enabled(LinphoneCore *lc) { return lc->video_conf.capture; } @@ -5276,15 +5494,15 @@ int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc) { } static MSVideoSizeDef supported_resolutions[]={ -#if !ANDROID & !TARGET_OS_IPHONE +#if !ANDROID && !TARGET_OS_IPHONE { { MS_VIDEO_SIZE_1080P_W, MS_VIDEO_SIZE_1080P_H } , "1080p" }, #endif -#if !ANDROID & !TARGET_OS_MAC /*limite to most common size because mac card cannot list supported resolutions*/ +#if !ANDROID && !TARGET_OS_MAC /*limit to most common sizes because mac video API cannot list supported resolutions*/ { { MS_VIDEO_SIZE_UXGA_W, MS_VIDEO_SIZE_UXGA_H } , "uxga" }, { { MS_VIDEO_SIZE_SXGA_MINUS_W, MS_VIDEO_SIZE_SXGA_MINUS_H } , "sxga-" }, #endif { { MS_VIDEO_SIZE_720P_W, MS_VIDEO_SIZE_720P_H } , "720p" }, -#if !ANDROID & !TARGET_OS_MAC +#if !ANDROID && !TARGET_OS_MAC { { MS_VIDEO_SIZE_XGA_W, MS_VIDEO_SIZE_XGA_H } , "xga" }, #endif #if !ANDROID && !TARGET_OS_IPHONE @@ -5316,23 +5534,33 @@ const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc){ static MSVideoSize video_size_get_by_name(const char *name){ MSVideoSizeDef *pdef=supported_resolutions; MSVideoSize null_vsize={0,0}; + MSVideoSize parsed; if (!name) return null_vsize; for(;pdef->name!=NULL;pdef++){ if (strcasecmp(name,pdef->name)==0){ return pdef->vsize; } } + if (sscanf(name,"%ix%i",&parsed.width,&parsed.height)==2){ + return parsed; + } ms_warning("Video resolution %s is not supported in linphone.",name); return null_vsize; } +/* warning: function not reentrant*/ static const char *video_size_get_name(MSVideoSize vsize){ MSVideoSizeDef *pdef=supported_resolutions; + static char customsize[64]={0}; for(;pdef->name!=NULL;pdef++){ if (pdef->vsize.width==vsize.width && pdef->vsize.height==vsize.height){ return pdef->name; } } + if (vsize.width && vsize.height){ + snprintf(customsize,sizeof(customsize)-1,"%ix%i",vsize.width,vsize.height); + return customsize; + } return NULL; } @@ -5359,13 +5587,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; } 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)); } @@ -5381,6 +5609,7 @@ void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize) * @param vsize the video resolution choosed for capuring and previewing. It can be (0,0) to not request any specific preview size and let the core optimize the processing. **/ void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize){ + MSVideoSize oldvsize; if (vsize.width==0 && vsize.height==0){ /*special case to reset the forced preview size mode*/ lc->video_conf.preview_vsize=vsize; @@ -5388,16 +5617,25 @@ void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize){ lp_config_set_string(lc->config,"video","preview_size",NULL); return; } - if (video_size_supported(vsize)){ - MSVideoSize oldvsize=lc->video_conf.preview_vsize; - lc->video_conf.preview_vsize=vsize; - if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){ - toggle_video_preview(lc,FALSE); - toggle_video_preview(lc,TRUE); - } - if (linphone_core_ready(lc)) - lp_config_set_string(lc->config,"video","preview_size",video_size_get_name(vsize)); + oldvsize=lc->video_conf.preview_vsize; + lc->video_conf.preview_vsize=vsize; + if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){ + toggle_video_preview(lc,FALSE); + toggle_video_preview(lc,TRUE); } + if (linphone_core_ready(lc)) + lp_config_set_string(lc->config,"video","preview_size",video_size_get_name(vsize)); +} + +/** + * Returns video size for the captured video if it was previously set by linphone_core_set_preview_video_size(), otherwise returns a 0,0 size. + * @see linphone_core_set_preview_video_size() + * @ingroup media_parameters + * @param lc the core + * @return a MSVideoSize +**/ +MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc){ + return lc->video_conf.preview_vsize; } /** @@ -5431,10 +5669,14 @@ void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char * * @ingroup media_parameters **/ -MSVideoSize linphone_core_get_preferred_video_size(LinphoneCore *lc){ +MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc){ return lc->video_conf.vsize; } +char * linphone_core_get_preferred_video_size_name(const LinphoneCore *lc) { + return ms_strdup(video_size_get_name(lc->video_conf.vsize)); +} + /** * Set the preferred frame rate for video. * Based on the available bandwidth constraints and network conditions, the video encoder @@ -5462,16 +5704,22 @@ float linphone_core_get_preferred_framerate(LinphoneCore *lc){ /** * Ask the core to stream audio from and to files, instead of using the soundcard. + * @ingroup media_parameters + * @param[in] lc LinphoneCore object + * @param[in] yesno A boolean value asking to stream audio from and to files or not. **/ -void linphone_core_use_files(LinphoneCore *lc, bool_t yesno){ +void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno){ lc->use_files=yesno; } /** * Sets a wav file to be played when putting somebody on hold, - * or when files are used instead of soundcards (see linphone_core_use_files()). + * or when files are used instead of soundcards (see linphone_core_set_use_files()). * * The file must be a 16 bit linear wav file. + * @ingroup media_parameters + * @param[in] lc LinphoneCore object + * @param[in] file The path to the file to be played when putting somebody on hold. **/ void linphone_core_set_play_file(LinphoneCore *lc, const char *file){ LinphoneCall *call=linphone_core_get_current_call(lc); @@ -5489,10 +5737,13 @@ void linphone_core_set_play_file(LinphoneCore *lc, const char *file){ /** * Sets a wav file where incoming stream is to be recorded, - * when files are used instead of soundcards (see linphone_core_use_files()). + * when files are used instead of soundcards (see linphone_core_set_use_files()). * * This feature is different from call recording (linphone_call_params_set_record_file()) * The file will be a 16 bit linear wav file. + * @ingroup media_parameters + * @param[in] lc LinphoneCore object + * @param[in] file The path to the file where incoming stream is to be recorded. **/ void linphone_core_set_record_file(LinphoneCore *lc, const char *file){ LinphoneCall *call=linphone_core_get_current_call(lc); @@ -5664,7 +5915,7 @@ void linphone_core_stop_dtmf(LinphoneCore *lc){ * * @ingroup initializing **/ -void *linphone_core_get_user_data(LinphoneCore *lc){ +void *linphone_core_get_user_data(const LinphoneCore *lc){ return lc->data; } @@ -5810,15 +6061,11 @@ void sip_config_uninit(LinphoneCore *lc) } if (i>=20) ms_warning("Cannot complete unregistration, giving up"); } - ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy); - ms_list_free(config->proxies); - config->proxies=NULL; + config->proxies=ms_list_free_with_data(config->proxies,(void (*)(void*)) _linphone_proxy_config_release); /*no longuer need to write proxy config if not changedlinphone_proxy_config_write_to_config_file(lc->config,NULL,i);*/ /*mark the end */ - ms_list_for_each(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy); - ms_list_free(lc->auth_info); - lc->auth_info=NULL; + lc->auth_info=ms_list_free_with_data(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy); /*now that we are unregisted, we no longer need the tunnel.*/ #ifdef TUNNEL_ENABLED @@ -6011,28 +6258,19 @@ static void linphone_core_uninit(LinphoneCore *lc) } #endif //BUILD_UPNP - if (lc->chatrooms){ - MSList *cr=ms_list_copy(lc->chatrooms); - MSList *elem; - for(elem=cr;elem!=NULL;elem=elem->next){ - linphone_chat_room_destroy((LinphoneChatRoom*)elem->data); - } - ms_list_free(cr); - } + ms_list_for_each(lc->chatrooms, (MSIterateFunc)linphone_chat_room_release); + lc->chatrooms = ms_list_free(lc->chatrooms); if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config); lp_config_destroy(lc->config); lc->config = NULL; /* Mark the config as NULL to block further calls */ - ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy); + ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref); lc->call_logs=ms_list_free(lc->call_logs); ms_list_for_each(lc->last_recv_msg_ids,ms_free); lc->last_recv_msg_ids=ms_list_free(lc->last_recv_msg_ids); - // Free struct variable - ms_free(lc->file_transfer_server); - if(lc->zrtp_secrets_cache != NULL) { ms_free(lc->zrtp_secrets_cache); } @@ -6053,6 +6291,7 @@ static void linphone_core_uninit(LinphoneCore *lc) if (liblinphone_serialize_logs == TRUE) { ortp_set_log_thread_id(0); } + ms_list_free_with_data(lc->vtables,(void (*)(void *))linphone_core_v_table_destroy); } static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){ @@ -6060,7 +6299,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu const MSList *elem=linphone_core_get_proxy_config_list(lc); if (lc->network_reachable==isReachable) return; // no change, ignore. - + lc->network_reachable_to_be_notified=TRUE; ms_message("Network state is now [%s]",isReachable?"UP":"DOWN"); for(;elem!=NULL;elem=elem->next){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data; @@ -6231,8 +6470,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 { @@ -6270,11 +6509,25 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){ } LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc){ - LinphoneCallParams *p=ms_new0(LinphoneCallParams,1); + LinphoneCallParams *p=linphone_call_params_new(); linphone_core_init_default_params(lc, p); return p; } +/** + * Create a LinphoneCallParams suitable for linphone_core_invite_with_params(), linphone_core_accept_call_with_params(), linphone_core_accept_early_media_with_params(), + * linphone_core_accept_call_update(). + * The parameters are initialized according to the current LinphoneCore configuration and the current state of the LinphoneCall. + * @param lc the LinphoneCore + * @param call the call for which the parameters are to be build, or NULL in the case where the parameters are to be used for a new outgoing call. + * @return a new LinphoneCallParams + * @ingroup call_control + */ +LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call){ + if (!call) return linphone_core_create_default_call_parameters(lc); + return linphone_call_params_copy(call->params); +} + const char *linphone_reason_to_string(LinphoneReason err){ switch(err){ case LinphoneReasonNone: @@ -6683,5 +6936,220 @@ 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); + lp_config_set_string(core->config, "misc", "file_transfer_server_url", server_url); +} + +const char * linphone_core_get_file_transfer_server(LinphoneCore *core) { + return lp_config_get_string(core->config, "misc", "file_transfer_server_url", NULL); +} + +/** + * This function controls signaling features supported by the core. + * They are typically included in a SIP Supported header. + * @param lc the LinphoneCore + * @param tag the feature tag name + * @ingroup initializing +**/ +void linphone_core_add_supported_tag(LinphoneCore *lc, const char *tag){ + sal_add_supported_tag(lc->sal,tag); + lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal)); +} + +/** + * Remove a supported tag. @see linphone_core_add_supported_tag() + * @param lc the LinphoneCore + * @param tag the tag to remove + * @ingroup initializing +**/ +void linphone_core_remove_supported_tag(LinphoneCore *lc, const char *tag){ + sal_remove_supported_tag(lc->sal,tag); + lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal)); +} + +/** + * Enable RTCP feedback (also known as RTP/AVPF profile). + * Setting LinphoneAVPFDefault is equivalent to LinphoneAVPFDisabled. + * This setting can be overriden per LinphoneProxyConfig with linphone_proxy_config_set_avpf_mode(). + * The value set here is used for calls placed or received out of any proxy configured, or if the proxy config is configured with LinphoneAVPFDefault. + * @param lc the LinphoneCore + * @param mode the mode. + * @ingroup media_parameters +**/ +void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode){ + if (mode==LinphoneAVPFDefault) mode=LinphoneAVPFDisabled; + lc->rtp_conf.avpf_mode=mode; + if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"rtp","avpf",mode); +} + +/** + * Return AVPF enablement. See linphone_core_set_avpf_mode() . + * @param lc the core + * @return the avpf enablement mode. + * @ingroup media_parameters +**/ +LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc){ + return lc->rtp_conf.avpf_mode; +} + +/** + * Return the avpf report interval in seconds. + * @param lc the LinphoneCore + * @return the avpf report interval in seconds. + * @ingroup media_parameters +**/ +int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc){ + return lp_config_get_int(lc->config,"rtp","avpf_rr_interval",5); +} + +/** + * Set the avpf report interval in seconds. + * This value can be overriden by the proxy config using linphone_proxy_config_set_avpf_rr_interval(). + * @param lc the core + * @param interval interval in seconds. + * @ingroup media_parameters +**/ +void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int interval){ + lp_config_set_int(lc->config,"rtp","avpf_rr_interval",interval); +} + +int linphone_payload_type_get_type(const LinphonePayloadType *pt) { + return pt->type; +} + +int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt) { + return pt->normal_bitrate; +} + +char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt) { + return pt->mime_type; +} + +int linphone_payload_type_get_channels(const LinphonePayloadType *pt) { + return pt->channels; +} + +LinphoneCoreVTable *linphone_core_v_table_new() { + return ms_new0(LinphoneCoreVTable,1); +} + +void linphone_core_v_table_destroy(LinphoneCoreVTable* table) { + ms_free(table); +} +#define NOTIFY_IF_EXIST(function_name) \ + MSList* iterator; \ + ms_message ("Linphone core [%p] notifying [%s]",lc,#function_name);\ + for (iterator=lc->vtables; iterator!=NULL; iterator=iterator->next) \ + if (((LinphoneCoreVTable*)(iterator->data))->function_name)\ + ((LinphoneCoreVTable*)(iterator->data))->function_name + +void linphone_core_notify_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message) { + NOTIFY_IF_EXIST(global_state_changed)(lc,gstate,message); +} +void linphone_core_notify_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message){ + NOTIFY_IF_EXIST(call_state_changed)(lc,call,cstate,message); +} +void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) { + NOTIFY_IF_EXIST(call_encryption_changed)(lc,call,on,authentication_token); +} +void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){ + NOTIFY_IF_EXIST(registration_state_changed)(lc,cfg,cstate,message); +} +void linphone_core_notify_show_interface(LinphoneCore *lc){ + NOTIFY_IF_EXIST(show)(lc); +} +void linphone_core_notify_display_status(LinphoneCore *lc, const char *message) { + NOTIFY_IF_EXIST(display_status)(lc,message); +} +void linphone_core_notify_display_message(LinphoneCore *lc, const char *message){ + NOTIFY_IF_EXIST(display_message)(lc,message); +} +void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message){ + NOTIFY_IF_EXIST(display_warning)(lc,message); +} +void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url){ + NOTIFY_IF_EXIST(display_url)(lc,message,url); +} +void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf){ + NOTIFY_IF_EXIST(notify_presence_received)(lc,lf); +} +void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url){ + NOTIFY_IF_EXIST(new_subscription_requested)(lc,lf,url); +} +void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain){ + NOTIFY_IF_EXIST(auth_info_requested)(lc,realm,username,domain); +} +void linphone_core_notify_call_log_updated(LinphoneCore *lc, LinphoneCallLog *newcl){ + NOTIFY_IF_EXIST(call_log_updated)(lc,newcl); +} +void linphone_core_notify_text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message){ + NOTIFY_IF_EXIST(text_received)(lc,room,from,message); +} +void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message){ + NOTIFY_IF_EXIST(message_received)(lc,room,message); +} +void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) { + NOTIFY_IF_EXIST(file_transfer_recv)(lc,message,content,buff,size); +} +void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) { + NOTIFY_IF_EXIST(file_transfer_send)(lc,message,content,buff,size); +} +void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) { + NOTIFY_IF_EXIST(file_transfer_progress_indication)(lc,message,content,offset,total); +} +void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { + NOTIFY_IF_EXIST(is_composing_received)(lc,room); +} +void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf) { + NOTIFY_IF_EXIST(dtmf_received)(lc,call,dtmf); +} +bool_t linphone_core_dtmf_received_has_listener(const LinphoneCore* lc) { + MSList* iterator; + for (iterator=lc->vtables; iterator!=NULL; iterator=iterator->next) + if (((LinphoneCoreVTable*)(iterator->data))->dtmf_received) + return TRUE; + return FALSE; +} +void linphone_core_notify_refer_received(LinphoneCore *lc, const char *refer_to) { + NOTIFY_IF_EXIST(refer_received)(lc,refer_to); +} +void linphone_core_notify_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf) { + NOTIFY_IF_EXIST(buddy_info_updated)(lc,lf); +} +void linphone_core_notify_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { + NOTIFY_IF_EXIST(transfer_state_changed)(lc,transfered,new_call_state); +} +void linphone_core_notify_call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats) { + NOTIFY_IF_EXIST(call_stats_updated)(lc,call,stats); +} +void linphone_core_notify_info_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg) { + NOTIFY_IF_EXIST(info_received)(lc,call,msg); +} +void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) { + NOTIFY_IF_EXIST(configuring_status)(lc,status,message); +} +void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable) { + NOTIFY_IF_EXIST(network_reachable)(lc,reachable); +} +void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) { + NOTIFY_IF_EXIST(notify_received)(lc,lev,notified_event,body); +} +void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { + NOTIFY_IF_EXIST(subscription_state_changed)(lc,lev,state); +} +void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state) { + NOTIFY_IF_EXIST(publish_state_changed)(lc,lev,state); +} +void linphone_core_notify_log_collection_upload_state_changed(LinphoneCore *lc, LinphoneCoreLogCollectionUploadState state, const char *info) { + NOTIFY_IF_EXIST(log_collection_upload_state_changed)(lc, state, info); +} +void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t offset, size_t total) { + NOTIFY_IF_EXIST(log_collection_upload_progress_indication)(lc, offset, total); +} +void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable) { + ms_message("Vtable [%p] registered on core [%p]",lc,vtable); + lc->vtables=ms_list_append(lc->vtables,vtable); +} +void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable) { + ms_message("Vtable [%p] unregistered on core [%p]",lc,vtable); + lc->vtables=ms_list_remove(lc->vtables,(void*)vtable); } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 9fdb864df..edb390570 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mediastreamer2/mscommon.h" #include "mediastreamer2/msvideo.h" #include "mediastreamer2/mediastream.h" +#include "mediastreamer2/bitratecontrol.h" #ifdef IN_LINPHONE #include "sipsetup.h" @@ -247,86 +248,61 @@ LinphoneDictionary* lp_config_section_to_dict( const LpConfig* lpconfig, const c void lp_config_load_dict_to_section( LpConfig* lpconfig, const char* section, const LinphoneDictionary* dict); -#ifdef IN_LINPHONE -#include "linphonefriend.h" -#include "event.h" -#else -#include "linphone/linphonefriend.h" -#include "linphone/event.h" -#endif - -LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr); -LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr); -LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr); -LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr); -LINPHONE_PUBLIC const char *linphone_address_get_scheme(const LinphoneAddress *u); -LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u); -LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u); -LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u); -LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u); -LINPHONE_PUBLIC void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name); -LINPHONE_PUBLIC void linphone_address_set_username(LinphoneAddress *uri, const char *username); -LINPHONE_PUBLIC void linphone_address_set_domain(LinphoneAddress *uri, const char *host); -LINPHONE_PUBLIC void linphone_address_set_port(LinphoneAddress *uri, int port); -/*remove tags, params etc... so that it is displayable to the user*/ -LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri); -LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *uri); -LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri); -LINPHONE_PUBLIC void linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type); -LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u); -LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u); -LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2); -LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u); +/** + * @addtogroup media_parameters + * @{ +**/ /** - * Create a #LinphoneAddress object by parsing the user supplied address, given as a string. - * @param[in] lc #LinphoneCore object - * @param[in] address String containing the user supplied address - * @return The create #LinphoneAddress object - * @ingroup linphone_address + * Object representing an RTP payload type. */ -LINPHONE_PUBLIC LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address); +typedef PayloadType LinphonePayloadType; -struct _SipSetupContext; +/** + * 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); /** - * Enum representing the direction of a call. - * @ingroup call_logs -**/ -enum _LinphoneCallDir { - LinphoneCallOutgoing, /**< outgoing calls*/ - LinphoneCallIncoming /**< incoming calls*/ -}; + * 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); /** - * Typedef for enum - * @ingroup call_logs -**/ -typedef enum _LinphoneCallDir LinphoneCallDir; + * Get the number of channels. + * @param[in] pt LinphonePayloadType object + * @return The number of channels. + */ +LINPHONE_PUBLIC int linphone_payload_type_get_channels(const LinphonePayloadType *pt); + /** - * Enum representing the status of a call - * @ingroup call_logs + * Enum describing RTP AVPF activation modes. **/ -typedef enum _LinphoneCallStatus { - LinphoneCallSuccess, /**< The call was sucessful*/ - LinphoneCallAborted, /**< The call was aborted */ - LinphoneCallMissed, /**< The call was missed (unanswered)*/ - LinphoneCallDeclined /**< The call was declined, either locally or by remote end*/ -} LinphoneCallStatus; +enum _LinphoneAVPFMode{ + LinphoneAVPFDefault=-1, /** A text message has been received */ - 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*/ + LinphoneCoreTextMessageReceivedCb text_received; /**< @deprecated, use #message_received instead
A text message has been received */ + LinphoneCoreFileTransferRecvCb file_transfer_recv; /**< Callback to store file received attached to a #LinphoneChatMessage */ + LinphoneCoreFileTransferSendCb file_transfer_send; /**< Callback to collect file chunk to be sent for a #LinphoneChatMessage */ + LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**< Callback to indicate file transfer progress */ + LinphoneCoreNetworkReachableCb network_reachable; /**< Callback to report IP network status (I.E up/down )*/ + LinphoneCoreLogCollectionUploadStateChangedCb log_collection_upload_state_changed; /**< Callback to upload collected logs */ + LinphoneCoreLogCollectionUploadProgressIndicationCb log_collection_upload_progress_indication; /**< Callback to indicate log collection upload progress */ } LinphoneCoreVTable; +/** + * Instantiate a vtable with all arguments set to NULL + * @returns newly allocated vtable + */ +LINPHONE_PUBLIC LinphoneCoreVTable *linphone_core_v_table_new(); + +/** + * Destroy a vtable. + * @param vtable to be destroyed + */ +LINPHONE_PUBLIC void linphone_core_v_table_destroy(LinphoneCoreVTable* table); + /** * @} **/ typedef struct _LCCallbackObj { - LinphoneCoreCbFunc _func; - void * _user_data; + LinphoneCoreCbFunc _func; + void * _user_data; }LCCallbackObj; @@ -1642,6 +1780,98 @@ typedef void * (*LinphoneCoreWaitingCallback)(LinphoneCore *lc, void *context, L /* THE main API */ +typedef enum _LinphoneLogCollectionState { + LinphoneLogCollectionDisabled, + LinphoneLogCollectionEnabled, + LinphoneLogCollectionEnabledWithoutPreviousLogHandler +} LinphoneLogCollectionState; + +/** + * Tells whether the linphone core log collection is enabled. + * @ingroup misc + * @returns The state of the linphone core log collection. + */ +LINPHONE_PUBLIC LinphoneLogCollectionState linphone_core_log_collection_enabled(void); + +/** + * Enable the linphone core log collection to upload logs on a server. + * @ingroup misc + * @param[in] state LinphoneLogCollectionState value telling whether to enable log collection or not. + */ +LINPHONE_PUBLIC void linphone_core_enable_log_collection(LinphoneLogCollectionState state); + +/** + * Get the path where the log files will be written for log collection. + * @ingroup misc + * @returns The path where the log files will be written. + */ +LINPHONE_PUBLIC const char * linphone_core_get_log_collection_path(void); + +/** + * Set the path where the log files will be written for log collection. + * @ingroup misc + * @param[in] path The path where the log files will be written. + */ +LINPHONE_PUBLIC void linphone_core_set_log_collection_path(const char *path); + +/** + * Get the prefix of the filenames that will be used for log collection. + * @ingroup misc + * @returns The prefix of the filenames used for log collection. + */ +LINPHONE_PUBLIC const char * linphone_core_get_log_collection_prefix(void); + +/** + * Set the prefix of the filenames that will be used for log collection. + * @ingroup misc + * @param[in] prefix The prefix to use for the filenames for log collection. + */ +LINPHONE_PUBLIC void linphone_core_set_log_collection_prefix(const char *prefix); + +/** + * Get the max file size in bytes of the files used for log collection. + * @ingroup misc + * @returns The max file size in bytes of the files used for log collection. + */ +LINPHONE_PUBLIC int linphone_core_get_log_collection_max_file_size(void); + +/** + * Set the max file size in bytes of the files used for log collection. + * @ingroup misc + * @param[in] size The max file size in bytes of the files used for log collection. + */ +LINPHONE_PUBLIC void linphone_core_set_log_collection_max_file_size(int size); + +/** + * Set the url of the server where to upload the collected log files. + * @ingroup misc + * @param[in] core LinphoneCore object + * @param[in] server_url The url of the server where to upload the collected log files. + */ +LINPHONE_PUBLIC void linphone_core_set_log_collection_upload_server_url(LinphoneCore *core, const char *server_url); + +/** + * Upload the log collection to the configured server url. + * @ingroup misc + * @param[in] core LinphoneCore object + */ +LINPHONE_PUBLIC void linphone_core_upload_log_collection(LinphoneCore *core); + +/** + * Compress the log collection in a single file. + * @ingroup misc + * @param[in] core LinphoneCore object + * @return The path of the compressed log collection file (to be freed calling ms_free()). + */ +LINPHONE_PUBLIC char * linphone_core_compress_log_collection(LinphoneCore *core); + +/** + * Reset the log collection by removing the log files. + * @ingroup misc + * @param[in] core LinphoneCore object + */ +LINPHONE_PUBLIC void linphone_core_reset_log_collection(LinphoneCore *core); + /** * Define a log handler. * @@ -1713,24 +1943,26 @@ LINPHONE_PUBLIC LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVT /* function to be periodically called in a main loop */ /* For ICE to work properly it should be called every 20ms */ LINPHONE_PUBLIC void linphone_core_iterate(LinphoneCore *lc); -#if 0 /*not implemented yet*/ + /** * @ingroup initializing - * Provide Linphone Core with an unique identifier. This be later used to identified contact address coming from this device. - * Value is not saved. + * add a listener to be notified of linphone core events. Once events are received, registered vtable are invoked in order. + * @param vtable a LinphoneCoreVTable structure holding your application callbacks. Object is owned by linphone core until linphone_core_remove_listener. * @param lc object * @param string identifying the device, can be EMEI or UDID * */ -void linphone_core_set_device_identifier(LinphoneCore *lc,const char* device_id); +LINPHONE_PUBLIC void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable); /** * @ingroup initializing - * get Linphone unique identifier + * remove a listener registred by linphone_core_add_listener. + * @param vtable a LinphoneCoreVTable structure holding your application callbacks + * @param lc object + * @param string identifying the device, can be EMEI or UDID * */ -const char* linphone_core_get_device_identifier(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable); -#endif /*sets the user-agent string in sip messages, ideally called just after linphone_core_new() or linphone_core_init() */ LINPHONE_PUBLIC void linphone_core_set_user_agent(LinphoneCore *lc, const char *ua_name, const char *version); @@ -1751,7 +1983,16 @@ LINPHONE_PUBLIC int linphone_core_transfer_call_to_another(LinphoneCore *lc, Lin LINPHONE_PUBLIC LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params); -LINPHONE_PUBLIC bool_t linphone_core_inc_invite_pending(LinphoneCore*lc); +/** @deprecated Use linphone_core_is_incoming_invite_pending() instead. */ +#define linphone_core_inc_invite_pending(lc) linphone_core_is_incoming_invite_pending(lc) + +/** + * Tells whether there is an incoming invite pending. + * @ingroup call_control + * @param[in] lc LinphoneCore object + * @return A boolean telling whether an incoming invite is pending or not. + */ +LINPHONE_PUBLIC bool_t linphone_core_is_incoming_invite_pending(LinphoneCore*lc); LINPHONE_PUBLIC bool_t linphone_core_in_call(const LinphoneCore *lc); @@ -1797,9 +2038,12 @@ LINPHONE_PUBLIC int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneC * Get default call parameters reflecting current linphone core configuration * @param lc LinphoneCore object * @return LinphoneCallParams + * @deprecated use linphone_core_create_call_params() */ LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call); + LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address); LINPHONE_PUBLIC void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf); @@ -1828,6 +2072,9 @@ LINPHONE_PUBLIC int linphone_core_get_upload_bandwidth(const LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled); LINPHONE_PUBLIC bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_set_adaptive_rate_algorithm(LinphoneCore *lc, const char *algorithm); +LINPHONE_PUBLIC const char* linphone_core_get_adaptive_rate_algorithm(const LinphoneCore *lc); + LINPHONE_PUBLIC void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime); LINPHONE_PUBLIC int linphone_core_get_download_ptime(LinphoneCore *lc); @@ -1879,48 +2126,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 @@ -1942,7 +2189,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); @@ -1966,12 +2213,17 @@ LINPHONE_PUBLIC void linphone_core_remove_proxy_config(LinphoneCore *lc, Linphon LINPHONE_PUBLIC const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc); -LINPHONE_PUBLIC void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config); +/** @deprecated Use linphone_core_set_default_proxy_config() instead. */ +#define linphone_core_set_default_proxy(lc, config) linphone_core_set_default_proxy_config(lc, config) void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index); LINPHONE_PUBLIC int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config); +LINPHONE_PUBLIC LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc); + +LINPHONE_PUBLIC void linphone_core_set_default_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config); + /** * Create an authentication information with default values from Linphone core. * @param[in] lc #LinphoneCore object @@ -2280,34 +2532,54 @@ bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc); void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, bool_t val); -/* returns a list of LinphoneCallLog */ -LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc); -LINPHONE_PUBLIC void linphone_core_clear_call_logs(LinphoneCore *lc); +/******************************************************************************* + * Call log related functions * + ******************************************************************************/ + +/** + * @addtogroup call_logs + * @{ +**/ + +/** + * Get the list of call logs (past calls). + * @param[in] lc LinphoneCore object + * @return \mslist{LinphoneCallLog} +**/ +LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc); + +/** + * Erase the call log. + * @param[in] lc LinphoneCore object +**/ +LINPHONE_PUBLIC void linphone_core_clear_call_logs(LinphoneCore *lc); /** * Get the number of missed calls. * Once checked, this counter can be reset with linphone_core_reset_missed_calls_count(). * @param[in] lc #LinphoneCore object. * @returns The number of missed calls. - * @ingroup call_logs **/ -LINPHONE_PUBLIC int linphone_core_get_missed_calls_count(LinphoneCore *lc); +LINPHONE_PUBLIC int linphone_core_get_missed_calls_count(LinphoneCore *lc); /** * Reset the counter of missed calls. * @param[in] lc #LinphoneCore object. - * @ingroup call_logs **/ -LINPHONE_PUBLIC void linphone_core_reset_missed_calls_count(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_reset_missed_calls_count(LinphoneCore *lc); /** * Remove a specific call log from call history list. * This function destroys the call log object. It must not be accessed anymore by the application after calling this function. * @param[in] lc #LinphoneCore object * @param[in] call_log #LinphoneCallLog object to remove. - * @ingroup call_logs **/ -LINPHONE_PUBLIC void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *call_log); +LINPHONE_PUBLIC void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *call_log); + +/** + * @} +**/ + /* video support */ LINPHONE_PUBLIC bool_t linphone_core_video_supported(LinphoneCore *lc); @@ -2356,6 +2628,24 @@ LINPHONE_PUBLIC void linphone_core_enable_video_capture(LinphoneCore *lc, bool_t **/ LINPHONE_PUBLIC void linphone_core_enable_video_display(LinphoneCore *lc, bool_t enable); + +/** + * Enable or disable video source reuse when switching from preview to actual video call. + * + * This source reuse is useful when you always display the preview, even before calls are initiated. + * By keeping the video source for the transition to a real video call, you will smooth out the + * source close/reopen cycle. + * + * This function does not have any effect durfing calls. It just indicates the #LinphoneCore to + * initiate future calls with video source reuse or not. + * Also, at the end of a video call, the source will be closed whatsoever for now. + * @param[in] lc #LinphoneCore object + * @param[in] enable TRUE to enable video source reuse. FALSE to disable it for subsequent calls. + * @ingroup media_parameters + * + */ +LINPHONE_PUBLIC void linphone_core_enable_video_source_reuse(LinphoneCore* lc, bool_t enable); + /** * Tells whether video capture is enabled. * @param[in] lc #LinphoneCore object. @@ -2384,7 +2674,15 @@ LINPHONE_PUBLIC const MSVideoSizeDef *linphone_core_get_supported_video_sizes(Li LINPHONE_PUBLIC void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize); LINPHONE_PUBLIC void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize); LINPHONE_PUBLIC void linphone_core_set_preview_video_size_by_name(LinphoneCore *lc, const char *name); -LINPHONE_PUBLIC MSVideoSize linphone_core_get_preferred_video_size(LinphoneCore *lc); +LINPHONE_PUBLIC MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc); +LINPHONE_PUBLIC MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc); + +/** + * Get the name of the current preferred video size for sending. + * @param[in] lc #LinphoneCore object. + * @returns A string containing the name of the current preferred video size (to be freed with ms_free()). + */ +LINPHONE_PUBLIC char * linphone_core_get_preferred_video_size_name(const LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char *name); LINPHONE_PUBLIC void linphone_core_set_preferred_framerate(LinphoneCore *lc, float fps); LINPHONE_PUBLIC float linphone_core_get_preferred_framerate(LinphoneCore *lc); @@ -2460,7 +2758,7 @@ LINPHONE_PUBLIC void linphone_core_set_native_preview_window_id(LinphoneCore *lc LINPHONE_PUBLIC void linphone_core_use_preview_window(LinphoneCore *lc, bool_t yesno); int linphone_core_get_device_rotation(LinphoneCore *lc ); -void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation); +LINPHONE_PUBLIC void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation); /** * Get the camera sensor rotation. @@ -2476,8 +2774,10 @@ LINPHONE_PUBLIC int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc); /* start or stop streaming video in case of embedded window */ void linphone_core_show_video(LinphoneCore *lc, bool_t show); +/** @deprecated Use linphone_core_set_use_files() instead. */ +#define linphone_core_use_files(lc, yesno) linphone_core_set_use_files(lc, yesno) /*play/record support: use files instead of soundcard*/ -LINPHONE_PUBLIC void linphone_core_use_files(LinphoneCore *lc, bool_t yesno); +LINPHONE_PUBLIC void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno); LINPHONE_PUBLIC void linphone_core_set_play_file(LinphoneCore *lc, const char *file); LINPHONE_PUBLIC void linphone_core_set_record_file(LinphoneCore *lc, const char *file); @@ -2514,7 +2814,7 @@ LINPHONE_PUBLIC void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t ena */ LINPHONE_PUBLIC bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc); -LINPHONE_PUBLIC void *linphone_core_get_user_data(LinphoneCore *lc); +LINPHONE_PUBLIC void *linphone_core_get_user_data(const LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_set_user_data(LinphoneCore *lc, void *userdata); /* returns LpConfig object to read/write to the config file: usefull if you wish to extend @@ -2674,7 +2974,7 @@ typedef struct _LinphoneTunnel LinphoneTunnel; /** * get tunnel instance if available */ -LINPHONE_PUBLIC LinphoneTunnel *linphone_core_get_tunnel(LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneTunnel *linphone_core_get_tunnel(const LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp); LINPHONE_PUBLIC int linphone_core_get_sip_dscp(const LinphoneCore *lc); @@ -2774,6 +3074,13 @@ LINPHONE_PUBLIC void linphone_core_set_tone(LinphoneCore *lc, LinphoneToneID id, * */ LINPHONE_PUBLIC void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url); +/** + * Get the globaly set http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml. + * @param[in] core #LinphoneCore from which to get the server_url + * @return URL of the file server like https://file.linphone.org/upload.php + * */ +LINPHONE_PUBLIC const char * linphone_core_get_file_transfer_server(LinphoneCore *core); + /** * Returns a null terminated table of strings containing the file format extension supported for call recording. * @param core the core @@ -2782,6 +3089,18 @@ LINPHONE_PUBLIC void linphone_core_set_file_transfer_server(LinphoneCore *core, **/ LINPHONE_PUBLIC const char ** linphone_core_get_supported_file_formats(LinphoneCore *core); +LINPHONE_PUBLIC void linphone_core_add_supported_tag(LinphoneCore *core, const char *tag); + +LINPHONE_PUBLIC void linphone_core_remove_supported_tag(LinphoneCore *core, const char *tag); + +LINPHONE_PUBLIC void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode); + +LINPHONE_PUBLIC LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc); + +LINPHONE_PUBLIC void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int interval); + +LINPHONE_PUBLIC int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc); + #ifdef __cplusplus } #endif diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index fc6b76f1f..241f130cc 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -27,6 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern "C" { #include "mediastreamer2/mediastream.h" #include "mediastreamer2/mscommon.h" +#include "mediastreamer2/dsptools.h" +#include "mediastreamer2/msmediaplayer.h" } #include "mediastreamer2/msjava.h" #include "private.h" @@ -55,9 +57,11 @@ extern "C" void libmsbcg729_init(); #ifdef HAVE_WEBRTC extern "C" void libmswebrtc_init(); #endif +#include #endif /*ANDROID*/ - +/*force linking of ms_audio_diff symbol because the tester requires it.*/ +static void *audiodiff=(void*)&ms_audio_diff; #define RETURN_USER_DATA_OBJECT(javaclass, funcprefix, cobj) \ { \ @@ -76,25 +80,6 @@ extern "C" void libmswebrtc_init(); return jUserDataObj; \ } - -#define RETURN_PROXY_CONFIG_USER_DATA_OBJECT(javaclass, funcprefix, cobj) \ - { \ - jclass jUserDataObjectClass; \ - jmethodID jUserDataObjectCtor; \ - jobject jUserDataObj; \ - jUserDataObj = (jobject)funcprefix ## _get_user_data(cobj); \ - if (jUserDataObj == NULL) { \ - jUserDataObjectClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/" javaclass)); \ - jUserDataObjectCtor = env->GetMethodID(jUserDataObjectClass,"", "(J)V"); \ - jUserDataObj = env->NewObject(jUserDataObjectClass, jUserDataObjectCtor,(jlong) cobj); \ - jUserDataObj = env->NewGlobalRef(jUserDataObj); \ - funcprefix ## _set_user_data(cobj, jUserDataObj); \ - env->DeleteGlobalRef(jUserDataObjectClass); \ - } \ - return jUserDataObj; \ - } - - static JavaVM *jvm=0; static const char* LogDomain = "Linphone"; static jclass handler_class; @@ -208,6 +193,9 @@ class LinphoneCoreData { vTable.notify_received=notifyReceived; vTable.publish_state_changed=publishStateChanged; vTable.configuring_status=configuringStatus; + vTable.file_transfer_progress_indication=fileTransferProgressIndication; + vTable.file_transfer_send=fileTransferSend; + vTable.file_transfer_recv=fileTransferRecv; listenerClass = (jclass)env->NewGlobalRef(env->GetObjectClass( alistener)); @@ -310,6 +298,10 @@ class LinphoneCoreData { configuringStateId = env->GetMethodID(listenerClass,"configuringStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;Ljava/lang/String;)V"); configuringStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RemoteProvisioningState")); configuringStateFromIntId = env->GetStaticMethodID(configuringStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;"); + + fileTransferProgressIndicationId = env->GetMethodID(listenerClass, "fileTransferProgressIndication", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;I)V"); + fileTransferSendId = env->GetMethodID(listenerClass, "fileTransferSend", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Ljava/nio/ByteBuffer;I)I"); + fileTransferRecvId = env->GetMethodID(listenerClass, "fileTransferRecv", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;[BI)V"); } ~LinphoneCoreData() { @@ -417,6 +409,10 @@ class LinphoneCoreData { jclass subscriptionDirClass; jmethodID subscriptionDirFromIntId; + jmethodID fileTransferProgressIndicationId; + jmethodID fileTransferSendId; + jmethodID fileTransferRecvId; + LinphoneCoreVTable vTable; static void showInterfaceCb(LinphoneCore *lc) { @@ -467,9 +463,35 @@ class LinphoneCoreData { ,env->CallStaticObjectMethod(lcData->globalStateClass,lcData->globalStateFromIntId,(jint)gstate), message ? env->NewStringUTF(message) : NULL); } + /* + * returns the java LinphoneProxyConfig associated with a C LinphoneProxyConfig. + **/ + jobject getProxy(JNIEnv *env , LinphoneProxyConfig *proxy, jobject core){ + jobject jobj=0; + + if (proxy!=NULL){ + void *up=linphone_proxy_config_get_user_data(proxy); + + if (up==NULL){ + jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); + linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); + linphone_proxy_config_ref(proxy); + }else{ + //promote the weak ref to local ref + jobj=env->NewLocalRef((jobject)up); + if (jobj == NULL){ + //the weak ref was dead + jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); + linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); + } + } + } + return jobj; + } static void registrationStateChange(LinphoneCore *lc, LinphoneProxyConfig* proxy,LinphoneRegistrationState state,const char* message) { JNIEnv *env = 0; jint result = jvm->AttachCurrentThread(&env,NULL); + jobject jproxy; if (result != 0) { ms_error("cannot attach VM"); return; @@ -478,7 +500,7 @@ class LinphoneCoreData { env->CallVoidMethod(lcData->listener ,lcData->registrationStateId ,lcData->core - ,env->NewObject(lcData->proxyClass,lcData->proxyCtrId,lcData->core,(jlong)proxy) + ,(jproxy=lcData->getProxy(env,proxy,lcData->core)) ,env->CallStaticObjectMethod(lcData->registrationStateClass,lcData->registrationStateFromIntId,(jint)state), message ? env->NewStringUTF(message) : NULL); } @@ -591,19 +613,37 @@ class LinphoneCoreData { ,env->NewObject(lcData->addressClass,lcData->addressCtrId,(jlong)from) ,message ? env->NewStringUTF(message) : NULL); } + jobject getChatMessage(JNIEnv *env , LinphoneChatMessage *msg){ + jobject jobj = 0; + + if (msg != NULL){ + void *up = linphone_chat_message_get_user_data(msg); + + if (up == NULL) { + jobj = env->NewObject(chatMessageClass,chatMessageCtrId,(jlong)linphone_chat_message_ref(msg)); + jobj = env->NewGlobalRef(jobj); + linphone_chat_message_set_user_data(msg,(void*)jobj); + } else { + jobj = (jobject)up; + } + } + return jobj; + } static void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) { JNIEnv *env = 0; + jobject jmsg; jint result = jvm->AttachCurrentThread(&env,NULL); if (result != 0) { ms_error("cannot attach VM"); return; } LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); + /*note: we call linphone_chat_message_ref() because the application does not acquire the object when invoked from a callback*/ env->CallVoidMethod(lcData->listener ,lcData->messageReceivedId ,lcData->core ,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room) - ,env->NewObject(lcData->chatMessageClass,lcData->chatMessageCtrId,(jlong)msg)); + ,(jmsg = lcData->getChatMessage(env, msg))); } static void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { JNIEnv *env = 0; @@ -675,7 +715,6 @@ class LinphoneCoreData { static void infoReceived(LinphoneCore *lc, LinphoneCall*call, const LinphoneInfoMessage *info){ JNIEnv *env = 0; jint result = jvm->AttachCurrentThread(&env,NULL); - jobject jcall; if (result != 0) { ms_error("cannot attach VM"); return; @@ -771,6 +810,65 @@ class LinphoneCoreData { LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); env->CallVoidMethod(lcData->listener, lcData->configuringStateId, lcData->core, env->CallStaticObjectMethod(lcData->configuringStateClass,lcData->configuringStateFromIntId,(jint)status), message ? env->NewStringUTF(message) : NULL); } + + static void fileTransferProgressIndication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) { + JNIEnv *env = 0; + jobject jmsg; + size_t progress = (offset * 100) / total; + jint result = jvm->AttachCurrentThread(&env,NULL); + if (result != 0) { + ms_error("cannot attach VM"); + return; + } + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); + env->CallVoidMethod(lcData->listener, + lcData->fileTransferProgressIndicationId, + lcData->core, + (jmsg = lcData->getChatMessage(env, message)), + content ? create_java_linphone_content(env, content) : NULL, + progress); + } + + static void fileTransferSend(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) { + JNIEnv *env = 0; + jobject jmsg; + size_t asking = *size; + jint result = jvm->AttachCurrentThread(&env,NULL); + if (result != 0) { + ms_error("cannot attach VM"); + return; + } + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); + *size = env->CallIntMethod(lcData->listener, + lcData->fileTransferSendId, + lcData->core, + (jmsg = lcData->getChatMessage(env, message)), + content ? create_java_linphone_content(env, content) : NULL, + buff ? env->NewDirectByteBuffer(buff, asking) : NULL, + asking); + } + + static void fileTransferRecv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) { + JNIEnv *env = 0; + jobject jmsg; + jint result = jvm->AttachCurrentThread(&env,NULL); + if (result != 0) { + ms_error("cannot attach VM"); + return; + } + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); + + jbyteArray jbytes = env->NewByteArray(size); + env->SetByteArrayRegion(jbytes, 0, size, (jbyte*)buff); + + env->CallVoidMethod(lcData->listener, + lcData->fileTransferRecvId, + lcData->core, + (jmsg = lcData->getChatMessage(env, message)), + content ? create_java_linphone_content(env, content) : NULL, + jbytes, + size); + } }; extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* env @@ -894,35 +992,37 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDefaultProxyConfig( J ,jlong pc) { linphone_core_set_default_proxy((LinphoneCore*)lc,(LinphoneProxyConfig*)pc); } -extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig( JNIEnv* env + +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig(JNIEnv* env ,jobject thiz ,jlong lc) { - LinphoneProxyConfig *config=0; + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc); linphone_core_get_default_proxy((LinphoneCore*)lc,&config); - return (jlong)config; -} - -static jobject getOrCreateProxy(JNIEnv* env,LinphoneProxyConfig* proxy){ - RETURN_PROXY_CONFIG_USER_DATA_OBJECT("LinphoneProxyConfigImpl", linphone_proxy_config, proxy); + if(config != 0) { + jobject jproxy = lcData->getProxy(env,config,lcData->core); + return jproxy; + } else { + return NULL; + } } extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigList(JNIEnv* env, jobject thiz, jlong lc) { const MSList* proxies = linphone_core_get_proxy_config_list((LinphoneCore*)lc); int proxyCount = ms_list_size(proxies); - jclass cls = env->FindClass("java/lang/Object"); + jclass cls = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl")); jobjectArray jProxies = env->NewObjectArray(proxyCount,cls,NULL); + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc); for (int i = 0; i < proxyCount; i++ ) { LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; - jobject jproxy = getOrCreateProxy(env,proxy); + jobject jproxy = lcData->getProxy(env,proxy,lcData->core); if(jproxy != NULL){ env->SetObjectArrayElement(jProxies, i, jproxy); - } else { - return NULL; } proxies = proxies->next; } + env->DeleteGlobalRef(cls); return jProxies; } @@ -932,9 +1032,7 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_addProxyConfig( JNIEnv* ,jlong lc ,jlong pc) { LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)pc; - linphone_proxy_config_set_user_data(proxy, env->NewGlobalRef(jproxyCfg)); - - return (jint)linphone_core_add_proxy_config((LinphoneCore*)lc,(LinphoneProxyConfig*)pc); + return (jint)linphone_core_add_proxy_config((LinphoneCore*)lc,proxy); } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_removeProxyConfig(JNIEnv* env, jobject thiz, jlong lc, jlong proxy) { @@ -1272,6 +1370,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 @@ -1300,6 +1405,28 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isAdaptiveRateContro ) { return (jboolean)linphone_core_adaptive_rate_control_enabled((LinphoneCore*)lc); } +extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getAdaptiveRateAlgorithm(JNIEnv* env + ,jobject thiz + ,jlong lc + ) { + const char* alg = linphone_core_get_adaptive_rate_algorithm((LinphoneCore*)lc); + if (alg) { + return env->NewStringUTF(alg); + } else { + return NULL; + } +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAdaptiveRateAlgorithm(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jstring jalg) { + const char* alg = jalg?env->GetStringUTFChars(jalg, NULL):NULL; + linphone_core_set_adaptive_rate_algorithm((LinphoneCore*)lc,alg); + if (alg) env->ReleaseStringUTFChars(jalg, alg); + +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableEchoCancellation(JNIEnv* env ,jobject thiz @@ -1539,11 +1666,6 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMediaEncryptionMandat linphone_core_set_media_encryption_mandatory((LinphoneCore*)lc, yesno); } -extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createProxyConfig(JNIEnv* env, jobject thiz, jlong lc) { - LinphoneProxyConfig* proxy = linphone_core_create_proxy_config((LinphoneCore *)lc); - return (jlong) proxy; -} - /* * Class: org_linphone_core_LinphoneCoreImpl * Method: disableChat @@ -1574,14 +1696,20 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_ch //ProxyConfig -extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_newLinphoneProxyConfig(JNIEnv* env,jobject thiz) { - LinphoneProxyConfig* proxy = linphone_proxy_config_new(); - return (jlong) proxy; +extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_createProxyConfig(JNIEnv* env, jobject thiz, jlong lc) { + LinphoneProxyConfig* proxy = linphone_core_create_proxy_config((LinphoneCore *)lc); + linphone_proxy_config_set_user_data(proxy,env->NewWeakGlobalRef(thiz)); + return (jlong) proxy; } -extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_delete(JNIEnv* env,jobject thiz,jlong ptr) { - linphone_proxy_config_destroy((LinphoneProxyConfig*)ptr); +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_finalize(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + LinphoneProxyConfig *proxy=(LinphoneProxyConfig*)ptr; + linphone_proxy_config_set_user_data(proxy,NULL); + linphone_proxy_config_unref(proxy); } + extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setIdentity(JNIEnv* env,jobject thiz,jlong proxyCfg,jstring jidentity) { const char* identity = env->GetStringUTFChars(jidentity, NULL); linphone_proxy_config_set_identity((LinphoneProxyConfig*)proxyCfg,identity); @@ -2317,6 +2445,10 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallImpl_getAverageQuality( JNI return (jfloat)linphone_call_get_average_quality((LinphoneCall*)ptr); } +extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getPlayer(JNIEnv *env, jobject thiz, jlong callPtr) { + return (jlong)linphone_call_get_player((LinphoneCall *)callPtr); +} + //LinphoneFriend extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env ,jobject thiz @@ -2418,12 +2550,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); @@ -2439,6 +2570,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) { @@ -2477,6 +2623,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) { @@ -2518,6 +2669,57 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_destroy(JNIEnv* env linphone_chat_room_destroy((LinphoneChatRoom*)ptr); } +extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) { + LinphoneContent content = {0}; + LinphoneChatMessage *message = NULL; + + content.type = (char*)env->GetStringUTFChars(jtype, NULL); + content.subtype = (char*)env->GetStringUTFChars(jsubtype, NULL); + content.name = (char*)env->GetStringUTFChars(jname, NULL); + content.size = data_size; + message = linphone_chat_room_create_file_transfer_message((LinphoneChatRoom *)ptr, &content); + env->ReleaseStringUTFChars(jtype, content.type); + env->ReleaseStringUTFChars(jsubtype, content.subtype); + env->ReleaseStringUTFChars(jname, content.name); + + return (jlong) message; +} + +extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_cancelFileTransfer(JNIEnv* env, jobject thiz, jlong ptr, jlong message) { + linphone_chat_room_cancel_file_transfer((LinphoneChatMessage *)message); +} + +extern "C" jobject Java_org_linphone_core_LinphoneChatMessageImpl_getFileTransferInformation(JNIEnv* env, jobject thiz, jlong ptr) { + const LinphoneContent *content = linphone_chat_message_get_file_transfer_information((LinphoneChatMessage *)ptr); + if (content) + return create_java_linphone_content(env, content); + return NULL; +} + +extern "C" jstring Java_org_linphone_core_LinphoneChatMessageImpl_getAppData(JNIEnv* env, jobject thiz, jlong ptr) { + const char * app_data = linphone_chat_message_get_appdata((LinphoneChatMessage *)ptr); + return app_data ? env->NewStringUTF(app_data) : NULL; +} + +extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setAppData(JNIEnv* env, jobject thiz, jlong ptr, jstring appdata) { + const char * data = appdata ? env->GetStringUTFChars(appdata, NULL) : NULL; + linphone_chat_message_set_appdata((LinphoneChatMessage *)ptr, data); + if (appdata) + env->ReleaseStringUTFChars(appdata, data); +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setFileTransferServer(JNIEnv* env, jobject thiz, jlong ptr, jstring server_url) { + const char * url = server_url ? env->GetStringUTFChars(server_url, NULL) : NULL; + linphone_core_set_file_transfer_server((LinphoneCore *)ptr, url); + if (server_url) + env->ReleaseStringUTFChars(server_url, url); +} + +extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getFileTransferServer(JNIEnv* env, jobject thiz, jlong ptr) { + const char * server_url = linphone_core_get_file_transfer_server((LinphoneCore *)ptr); + return server_url ? env->NewStringUTF(server_url) : NULL; +} + extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_store(JNIEnv* env ,jobject thiz ,jlong ptr) { @@ -2582,6 +2784,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) { @@ -2699,6 +2907,13 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage2(JNIEnv* linphone_chat_room_send_message2((LinphoneChatRoom*)chatroom_ptr, (LinphoneChatMessage*)messagePtr, chat_room_impl_callback, (void*)listener); } +extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_startFileDownload(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) { + jobject listener = env->NewGlobalRef(jlistener); + LinphoneChatMessage * message = (LinphoneChatMessage *)ptr; + message->cb_ud = listener; + linphone_chat_message_start_file_download(message, chat_room_impl_callback, NULL); +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoWindowId(JNIEnv* env ,jobject thiz ,jlong lc @@ -3329,6 +3544,60 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAddServerAndMirror env->ReleaseStringUTFChars(jHost, cHost); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAddServer(JNIEnv *env, jobject thiz, jlong pCore, jobject config) { + LinphoneTunnel *tunnel = linphone_core_get_tunnel((LinphoneCore *)pCore); + if(tunnel != NULL) { + jclass TunnelConfigClass = env->FindClass("org/linphone/core/TunnelConfig"); + jmethodID getHostMethod = env->GetMethodID(TunnelConfigClass, "getHost", "()Ljava/lang/String;"); + jmethodID getPortMethod = env->GetMethodID(TunnelConfigClass, "getPort", "()I"); + jmethodID getRemoteUdpMirrorPortMethod = env->GetMethodID(TunnelConfigClass, "getRemoteUdpMirrorPort", "()I"); + jmethodID getDelayMethod = env->GetMethodID(TunnelConfigClass, "getDelay", "()I"); + jstring hostString = (jstring)env->CallObjectMethod(config, getHostMethod); + const char *host = env->GetStringUTFChars(hostString, NULL); + if(host == NULL || strlen(host)==0) { + ms_error("LinphoneCore.tunnelAddServer(): no tunnel host defined"); + } + LinphoneTunnelConfig *tunnelConfig = linphone_tunnel_config_new(); + linphone_tunnel_config_set_host(tunnelConfig, host); + linphone_tunnel_config_set_port(tunnelConfig, env->CallIntMethod(config, getPortMethod)); + linphone_tunnel_config_set_remote_udp_mirror_port(tunnelConfig, env->CallIntMethod(config, getRemoteUdpMirrorPortMethod)); + linphone_tunnel_config_set_delay(tunnelConfig, env->CallIntMethod(config, getDelayMethod)); + linphone_tunnel_add_server(tunnel, tunnelConfig); + env->ReleaseStringUTFChars(hostString, host); + } else { + ms_error("LinphoneCore.tunnelAddServer(): tunnel feature is not enabled"); + } +} + +extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_tunnelGetServers(JNIEnv *env, jobject thiz, jlong pCore) { + LinphoneTunnel *tunnel = linphone_core_get_tunnel((LinphoneCore *)pCore); + jclass TunnelConfigClass = env->FindClass("org/linphone/core/TunnelConfig"); + jmethodID setHostMethod = env->GetMethodID(TunnelConfigClass, "setHost", "(Ljava/lang/String;)V"); + jmethodID setPortMethod = env->GetMethodID(TunnelConfigClass, "setPort", "(I)V"); + jmethodID setRemoteUdpMirrorPortMethod = env->GetMethodID(TunnelConfigClass, "setRemoteUdpMirrorPort", "(I)V"); + jmethodID setDelayMethod = env->GetMethodID(TunnelConfigClass, "setDelay", "(I)V"); + jobjectArray tunnelConfigArray = NULL; + + if(tunnel != NULL) { + const MSList *servers = linphone_tunnel_get_servers(tunnel); + const MSList *it; + int i; + ms_message("servers=%p", (void *)servers); + ms_message("taille=%i", ms_list_size(servers)); + tunnelConfigArray = env->NewObjectArray(ms_list_size(servers), TunnelConfigClass, NULL); + for(it = servers, i=0; it != NULL; it = it->next, i++) { + const LinphoneTunnelConfig *conf = (const LinphoneTunnelConfig *)it->data; + jobject elt = env->AllocObject(TunnelConfigClass); + env->CallVoidMethod(elt, setHostMethod, env->NewStringUTF(linphone_tunnel_config_get_host(conf))); + env->CallVoidMethod(elt, setPortMethod, linphone_tunnel_config_get_port(conf)); + env->CallVoidMethod(elt, setRemoteUdpMirrorPortMethod, linphone_tunnel_config_get_remote_udp_mirror_port(conf)); + env->CallVoidMethod(elt, setDelayMethod, linphone_tunnel_config_get_delay(conf)); + env->SetObjectArrayElement(tunnelConfigArray, i, elt); + } + } + return tunnelConfigArray; +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelSetHttpProxy(JNIEnv *env,jobject thiz,jlong pCore, jstring jHost, jint port, jstring username, jstring password) { @@ -3359,6 +3628,37 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnable(JNIEnv *env linphone_tunnel_enable(tunnel, enable); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelSetMode(JNIEnv *env, jobject thiz, jlong pCore, jint mode) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + linphone_tunnel_set_mode(tunnel, (LinphoneTunnelMode)mode); + } +} + +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_tunnelGetMode(JNIEnv *env, jobject thiz, jlong pCore) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + return (jint)linphone_tunnel_get_mode(tunnel); + } else { + return 0; + } +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnableSip(JNIEnv *env, jobject thiz, jlong pCore, jboolean enable) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + linphone_tunnel_enable_sip(tunnel, (bool_t)enable); + } +} + +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_tunnelSipEnabled(JNIEnv *env, jobject thiz, jlong pCore) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + return (jboolean)linphone_tunnel_sip_enabled(tunnel); + } else { + return JNI_FALSE; + } +} extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUserAgent(JNIEnv *env,jobject thiz,jlong pCore, jstring name, jstring version){ const char* cname=env->GetStringUTFChars(name, NULL); @@ -3399,6 +3699,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); } @@ -3419,6 +3727,13 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioDscp(JNIEnv* env linphone_core_set_audio_dscp((LinphoneCore*)ptr,dscp); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAndroidPowerManager(JNIEnv *env, jclass cls, jobject pm) { +#ifdef ANDROID + if(pm != NULL) bellesip_wake_lock_init(env, pm); + else bellesip_wake_lock_uninit(env); +#endif +} + extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getAudioDscp(JNIEnv* env,jobject thiz,jlong ptr){ return linphone_core_get_audio_dscp((LinphoneCore*)ptr); } @@ -3665,22 +3980,25 @@ extern "C" jintArray Java_org_linphone_core_LpConfigImpl_getIntRange(JNIEnv *env static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent *content){ jclass contentClass; jmethodID ctor; - jstring jtype, jsubtype, jencoding; - jbyteArray jdata=NULL; + jstring jtype, jsubtype, jencoding, jname; + jbyteArray jdata = NULL; + jint jsize = 0; contentClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneContentImpl")); - ctor = env->GetMethodID(contentClass,"", "(Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;)V"); + ctor = env->GetMethodID(contentClass,"", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)V"); - jtype=env->NewStringUTF(content->type); - jsubtype=env->NewStringUTF(content->subtype); - jencoding=content->encoding ? env->NewStringUTF(content->encoding) : NULL; + jtype = env->NewStringUTF(content->type); + jsubtype = env->NewStringUTF(content->subtype); + jencoding = content->encoding ? env->NewStringUTF(content->encoding) : NULL; + jname = content->name ? env->NewStringUTF(content->name) : NULL; + jsize = (jint) content->size; if (content->data){ - jdata=env->NewByteArray(content->size); - env->SetByteArrayRegion(jdata,0,content->size,(jbyte*)content->data); + jdata = env->NewByteArray(content->size); + env->SetByteArrayRegion(jdata, 0, content->size, (jbyte*)content->data); } - jobject jobj=env->NewObject(contentClass,ctor,jtype, jsubtype, jdata,jencoding); + jobject jobj = env->NewObject(contentClass, ctor, jname, jtype, jsubtype, jdata, jencoding, jsize); env->DeleteGlobalRef(contentClass); return jobj; } @@ -3736,7 +4054,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_addHeader( * Signature: (JLjava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getHeader(JNIEnv *env, jobject jobj, jlong infoptr, jstring jname){ - const char *name=name=env->GetStringUTFChars(jname,NULL); + const char *name=env->GetStringUTFChars(jname,NULL); const char *ret=linphone_info_message_get_header((LinphoneInfoMessage*)infoptr,name); env->ReleaseStringUTFChars(jname,name); return ret ? env->NewStringUTF(ret) : NULL; @@ -4408,6 +4726,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceActivityImpl_setDescriptio const char *cdescription = description ? env->GetStringUTFChars(description, NULL) : NULL; linphone_presence_activity_set_description(activity, cdescription); if (cdescription) env->ReleaseStringUTFChars(description, cdescription); + return (jint)0; } /* @@ -4459,6 +4778,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setId(JNIEnv * const char *cid = id ? env->GetStringUTFChars(id, NULL) : NULL; linphone_presence_service_set_id(service, cid); if (cid) env->ReleaseStringUTFChars(id, cid); + return (jint)0; } /* @@ -4504,6 +4824,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setContact(JNI const char *ccontact = contact ? env->GetStringUTFChars(contact, NULL) : NULL; linphone_presence_service_set_contact(service, ccontact); if (ccontact) env->ReleaseStringUTFChars(contact, ccontact); + return (jint)0; } /* @@ -4594,6 +4915,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_setId(JNIEnv *e const char *cid = id ? env->GetStringUTFChars(id, NULL) : NULL; linphone_presence_person_set_id(person, cid); if (cid) env->ReleaseStringUTFChars(id, cid); + return (jint)0; } /* @@ -4766,6 +5088,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceNoteImpl_setContent(JNIEnv const char *ccontent = content ? env->GetStringUTFChars(content, NULL) : NULL; linphone_presence_note_set_content(note, ccontent); if (ccontent) env->ReleaseStringUTFChars(content, ccontent); + return (jint)0; } /* @@ -4789,6 +5112,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceNoteImpl_setLang(JNIEnv *e const char *clang = lang ? env->GetStringUTFChars(lang, NULL) : NULL; linphone_presence_note_set_lang(note, clang); if (clang) env->ReleaseStringUTFChars(lang, clang); + return (jint)0; } /* @@ -4897,3 +5221,117 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getDetails(JNIEnv } #endif +/* Linphone Player */ +struct LinphonePlayerData { + LinphonePlayerData(JNIEnv *env, jobject listener, jobject jLinphonePlayer) : + mListener(env->NewGlobalRef(listener)), + mJLinphonePlayer(env->NewGlobalRef(jLinphonePlayer)) + { + mListenerClass = (jclass)env->NewGlobalRef(env->GetObjectClass(listener)); + mEndOfFileMethodID = env->GetMethodID(mListenerClass, "endOfFile", "(Lorg/linphone/core/LinphonePlayer;)V"); + if(mEndOfFileMethodID == NULL) { + ms_error("Could not get endOfFile method ID"); + env->ExceptionClear(); + } + } + + ~LinphonePlayerData() { + JNIEnv *env; + jvm->AttachCurrentThread(&env, NULL); + env->DeleteGlobalRef(mListener); + env->DeleteGlobalRef(mListenerClass); + env->DeleteGlobalRef(mJLinphonePlayer); + } + + jobject mListener; + jclass mListenerClass; + jobject mJLinphonePlayer; + jmethodID mEndOfFileMethodID; +}; + +static void _eof_callback(LinphonePlayer *player, void *user_data) { + JNIEnv *env; + LinphonePlayerData *player_data = (LinphonePlayerData *)user_data; + jvm->AttachCurrentThread(&env, NULL); + env->CallVoidMethod(player_data->mListener, player_data->mEndOfFileMethodID, player_data->mJLinphonePlayer); +} + +extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_open(JNIEnv *env, jobject jPlayer, jlong ptr, jstring filename, jobject listener) { + LinphonePlayerData *data = NULL; + LinphonePlayerEofCallback cb = NULL; + if(listener) { + data = new LinphonePlayerData(env, listener, jPlayer); + cb = _eof_callback; + } + if(linphone_player_open((LinphonePlayer *)ptr, env->GetStringUTFChars(filename, NULL), cb, data) == -1) { + if(data) delete data; + return -1; + } + return 0; +} + +extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_start(JNIEnv *env, jobject jobj, jlong ptr) { + return (jint)linphone_player_start((LinphonePlayer *)ptr); +} + +extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_pause(JNIEnv *env, jobject jobj, jlong ptr) { + return (jint)linphone_player_pause((LinphonePlayer *)ptr); +} + +extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_seek(JNIEnv *env, jobject jobj, jlong ptr, jint timeMs) { + return (jint)linphone_player_seek((LinphonePlayer *)ptr, timeMs); +} + +extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_getState(JNIEnv *env, jobject jobj, jlong ptr) { + return (jint)linphone_player_get_state((LinphonePlayer *)ptr); +} + +extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_getDuration(JNIEnv *env, jobject jobj, jlong ptr) { + return (jint)linphone_player_get_duration((LinphonePlayer *)ptr); +} + +extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_getCurrentPosition(JNIEnv *env, jobject jobj, jlong ptr) { + return (jint)linphone_player_get_current_position((LinphonePlayer *)ptr); +} + +extern "C" void Java_org_linphone_core_LinphonePlayerImpl_close(JNIEnv *env, jobject playerPtr, jlong ptr) { + LinphonePlayer *player = (LinphonePlayer *)ptr; + if(player->user_data) { + LinphonePlayerData *data = (LinphonePlayerData *)player->user_data; + if(data) delete data; + player->user_data = NULL; + } + linphone_player_close(player); +} + +extern "C" void Java_org_linphone_core_LinphonePlayerImpl_destroy(JNIEnv *env, jobject jobj, jlong playerPtr) { + LinphonePlayer *player = (LinphonePlayer *)playerPtr; + if(player == NULL) { + ms_error("Cannot destroy the LinphonePlayerImpl object. Native pointer is NULL"); + return; + } + if(player->user_data) { + delete (LinphonePlayerData *)player->user_data; + } + jobject window_id = (jobject)ms_media_player_get_window_id((MSMediaPlayer *)player->impl); + if(window_id) env->DeleteGlobalRef(window_id); + linphone_player_destroy(player); +} + +extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createLocalPlayer(JNIEnv *env, jobject jobj, jlong ptr, jobject window) { + jobject window_ref = NULL; + MSSndCard *snd_card = ms_snd_card_manager_get_default_playback_card(ms_snd_card_manager_get()); + if(snd_card == NULL) { + ms_error("No default playback sound card found"); + return 0; + } + window_ref = env->NewGlobalRef(window); + LinphonePlayer *player = linphone_core_create_local_player((LinphoneCore *)ptr, snd_card, "MSAndroidDisplay", window_ref); + if(player == NULL) { + ms_error("Fails to create a player"); + if(window_ref) env->DeleteGlobalRef(window_ref); + return 0; + } else { + return (jlong)player; + } +} diff --git a/coreapi/linphonefriend.h b/coreapi/linphonefriend.h index 891bf7631..f64286c0e 100644 --- a/coreapi/linphonefriend.h +++ b/coreapi/linphonefriend.h @@ -356,7 +356,8 @@ LINPHONE_PUBLIC void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneF /** * Get Buddy list of LinphoneFriend - * @param lc #LinphoneCore object + * @param[in] lc #LinphoneCore object + * @return \mslist{LinphoneFriend} */ LINPHONE_PUBLIC const MSList * linphone_core_get_friend_list(const LinphoneCore *lc); diff --git a/coreapi/localplayer.c b/coreapi/localplayer.c new file mode 100644 index 000000000..ad06e1751 --- /dev/null +++ b/coreapi/localplayer.c @@ -0,0 +1,98 @@ +/* +linphone +Copyright (C) 2000 - 2010 Simon MORLAT (simon.morlat@linphone.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "private.h" +#include +#include + +static int _local_player_open(LinphonePlayer *obj, const char *filename); +static int _local_player_start(LinphonePlayer *obj); +static int _local_player_pause(LinphonePlayer *obj); +static int _local_player_seek(LinphonePlayer *obj, int time_ms); +static MSPlayerState _local_player_get_state(LinphonePlayer *obj); +static int _local_player_get_duration(LinphonePlayer *obj); +static int _local_player_get_current_position(LinphonePlayer *obj); +static void _local_player_close(LinphonePlayer *obj); +static void _local_player_destroy(LinphonePlayer *obj); +static void _local_player_eof_callback(void *user_data); + +LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, void *window_id) { + LinphonePlayer *obj = ms_new0(LinphonePlayer, 1); + if(snd_card == NULL) snd_card = lc->sound_conf.play_sndcard; + if(video_out == NULL) video_out = linphone_core_get_video_display_filter(lc); + obj->impl = ms_media_player_new(snd_card, video_out, window_id); + obj->open = _local_player_open; + obj->start = _local_player_start; + obj->pause = _local_player_pause; + obj->seek = _local_player_seek; + obj->get_state = _local_player_get_state; + obj->get_duration = _local_player_get_duration; + obj->get_position = _local_player_get_current_position; + obj->close = _local_player_close; + obj->destroy = _local_player_destroy; + ms_media_player_set_eof_callback((MSMediaPlayer *)obj->impl, _local_player_eof_callback, obj); + return obj; +} + +bool_t linphone_local_player_matroska_supported(void) { + return ms_media_player_matroska_supported(); +} + +static int _local_player_open(LinphonePlayer *obj, const char *filename) { + return ms_media_player_open((MSMediaPlayer *)obj->impl, filename) ? 0 : -1; +} + +static int _local_player_start(LinphonePlayer *obj) { + return ms_media_player_start((MSMediaPlayer *)obj->impl) ? 0 : -1; +} + +static int _local_player_pause(LinphonePlayer *obj) { + ms_media_player_pause((MSMediaPlayer *)obj->impl); + return 0; +} + +static int _local_player_seek(LinphonePlayer *obj, int time_ms) { + return ms_media_player_seek((MSMediaPlayer *)obj->impl, time_ms) ? 0 : -1; +} + +static MSPlayerState _local_player_get_state(LinphonePlayer *obj) { + return ms_media_player_get_state((MSMediaPlayer *)obj->impl); +} + +static int _local_player_get_duration(LinphonePlayer *obj) { + return ms_media_player_get_duration((MSMediaPlayer *)obj->impl); +} + +static int _local_player_get_current_position(LinphonePlayer *obj) { + return ms_media_player_get_current_position((MSMediaPlayer *)obj->impl); +} + +static void _local_player_destroy(LinphonePlayer *obj) { + ms_media_player_free((MSMediaPlayer *)obj->impl); + _linphone_player_destroy(obj); +} + +static void _local_player_close(LinphonePlayer *obj) { + ms_media_player_close((MSMediaPlayer *)obj->impl); +} + +static void _local_player_eof_callback(void *user_data) { + LinphonePlayer *obj = (LinphonePlayer *)user_data; + obj->cb(obj, obj->user_data); +} diff --git a/coreapi/lpc2xml.c b/coreapi/lpc2xml.c index 46a71a2b9..1446a94cc 100644 --- a/coreapi/lpc2xml.c +++ b/coreapi/lpc2xml.c @@ -29,7 +29,7 @@ struct _lpc2xml_context { const LpConfig *lpc; lpc2xml_function cbf; void *ctx; - + xmlDoc *doc; char errorBuffer[LPC2XML_BZ]; char warningBuffer[LPC2XML_BZ]; @@ -42,7 +42,7 @@ lpc2xml_context* lpc2xml_context_new(lpc2xml_function cbf, void *ctx) { xmlCtx->lpc = NULL; xmlCtx->cbf = cbf; xmlCtx->ctx = ctx; - + xmlCtx->doc = NULL; xmlCtx->errorBuffer[0]='\0'; xmlCtx->warningBuffer[0]='\0'; @@ -64,8 +64,8 @@ static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) { } static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) { - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); if(xmlCtx->cbf != NULL) { xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args); } @@ -75,8 +75,8 @@ static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ... static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) { lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx; int sl = strlen(xmlCtx->errorBuffer); - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args); va_end(args); } @@ -85,8 +85,8 @@ static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) { static void lpc2xml_genericxml_warning(void *ctx, const char *fmt, ...) { lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx; int sl = strlen(xmlCtx->warningBuffer); - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args); va_end(args); } @@ -114,25 +114,27 @@ struct __processSectionCtx { static void processSection_cb(const char *entry, struct __processSectionCtx *ctx) { if(ctx->ret == 0) { const char *comment = "#"; + xmlNode *node; + xmlAttr *name_attr; if (strncmp(comment, entry, strlen(comment)) == 0) { lpc2xml_log(ctx->ctx, LPC2XML_WARNING, "Skipped commented entry %s", entry); ctx->ret = 0; return; } - xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL); + node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL); if(node == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"entry\" element"); ctx->ret = -1; return; } - xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry); + name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry); if(name_attr == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"entry\" element"); ctx->ret = -1; return; } - + ctx->ret = processEntry(ctx->section, entry, node, ctx->ctx); } } @@ -154,12 +156,13 @@ struct __processConfigCtx { static void processConfig_cb(const char *section, struct __processConfigCtx *ctx) { if(ctx->ret == 0) { xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"section", NULL); + xmlAttr *name_attr; if(node == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"section\" element"); ctx->ret = -1; return; } - xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section); + name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section); if(name_attr == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"section\" element"); ctx->ret = -1; @@ -177,22 +180,25 @@ static int processConfig(xmlNode *node, lpc2xml_context *ctx) { static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) { int ret = 0; + xmlNs *xsi_ns; + xmlNs *lpc_ns; + xmlAttr *schemaLocation; xmlNode *root_node = xmlNewNode(NULL, (const xmlChar *)"config"); if(root_node == NULL) { lpc2xml_log(ctx, LPC2XML_ERROR, "Can't create \"config\" element"); return -1; } - xmlNs *lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL); + lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL); if(lpc_ns == NULL) { lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create lpc namespace"); } else { xmlSetNs(root_node, lpc_ns); } - xmlNs *xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi"); + xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi"); if(lpc_ns == NULL) { lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create xsi namespace"); } - xmlAttr *schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd"); + schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd"); if(schemaLocation == NULL) { lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create schemaLocation"); } @@ -203,12 +209,13 @@ static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) { static int internal_convert_lpc2xml(lpc2xml_context *ctx) { int ret = 0; + xmlDoc *doc; lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation started"); if(ctx->doc != NULL) { xmlFreeDoc(ctx->doc); ctx->doc = NULL; } - xmlDoc *doc = xmlNewDoc((const xmlChar *)"1.0"); + doc = xmlNewDoc((const xmlChar *)"1.0"); ret = processDoc(doc, ctx); if(ret == 0) { ctx->doc = doc; @@ -226,9 +233,10 @@ int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) { int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) { int ret = -1; + xmlSaveCtxtPtr save_ctx; lpc2xml_context_clear_logs(context); xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); - xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT); + save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT); if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { @@ -248,9 +256,10 @@ int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) { int lpc2xml_convert_fd(lpc2xml_context* context, int fd) { int ret = -1; + xmlSaveCtxtPtr save_ctx; lpc2xml_context_clear_logs(context); xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); - xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT); + save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT); if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { @@ -271,9 +280,10 @@ int lpc2xml_convert_fd(lpc2xml_context* context, int fd) { int lpc2xml_convert_string(lpc2xml_context* context, char **content) { int ret = -1; xmlBufferPtr buffer = xmlBufferCreate(); + xmlSaveCtxtPtr save_ctx; lpc2xml_context_clear_logs(context); xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); - xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT); + save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT); if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 9dcce9f4d..a940fb696 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -39,7 +39,19 @@ #endif #endif /*_WIN32_WCE*/ +#ifdef _MSC_VER +#ifdef WINAPI_FAMILY_PHONE_APP +#include +#else +#include +#endif +#else +#include +#endif +#ifdef WIN32 +#define RENAME_REQUIRES_NONEXISTENT_NEW_PATH 1 +#endif #define lp_new0(type,n) (type*)calloc(sizeof(type),n) @@ -67,6 +79,7 @@ struct _LpConfig{ int refcnt; FILE *file; char *filename; + char *tmpfilename; MSList *sections; int modified; int readonly; @@ -271,7 +284,7 @@ static LpSection* lp_config_parse_line(LpConfig* lpconfig, const char* line, LpS /* remove ending white spaces */ for (; pos2>pos1 && pos2[-1]==' ';pos2--) pos2[-1]='\0'; - if (pos2-pos1>=0){ + if (pos2-pos1>0){ /* found a pair key,value */ if (cur!=NULL){ @@ -339,22 +352,34 @@ LpConfig *lp_config_new_with_factory(const char *config_filename, const char *fa if (config_filename!=NULL){ ms_message("Using (r/w) config information from %s", config_filename); lpconfig->filename=ortp_strdup(config_filename); - lpconfig->file=fopen(config_filename,"r+"); - if (lpconfig->file!=NULL){ - lp_config_parse(lpconfig,lpconfig->file); - fclose(lpconfig->file); + lpconfig->tmpfilename=ortp_strdup_printf("%s.tmp",config_filename); + #if !defined(WIN32) - { - struct stat fileStat; - if ((stat(config_filename,&fileStat) == 0) && (S_ISREG(fileStat.st_mode))) { - /* make existing configuration files non-group/world-accessible */ - if (chmod(config_filename, S_IRUSR | S_IWUSR) == -1) { - ms_warning("unable to correct permissions on " - "configuration file: %s", strerror(errno)); - } + { + struct stat fileStat; + if ((stat(config_filename,&fileStat) == 0) && (S_ISREG(fileStat.st_mode))) { + /* make existing configuration files non-group/world-accessible */ + if (chmod(config_filename, S_IRUSR | S_IWUSR) == -1) { + ms_warning("unable to correct permissions on " + "configuration file: %s", strerror(errno)); } } + } #endif /*WIN32*/ + /*open with r+ to check if we can write on it later*/ + lpconfig->file=fopen(lpconfig->filename,"r+"); +#ifdef RENAME_REQUIRES_NONEXISTENT_NEW_PATH + if (lpconfig->file==NULL){ + lpconfig->file=fopen(lpconfig->tmpfilename,"r+"); + if (lpconfig->file){ + ms_warning("Could not open %s but %s works, app may have crashed during last sync.",lpconfig->filename,lpconfig->tmpfilename); + } + } +#endif + if (lpconfig->file!=NULL){ + lp_config_parse(lpconfig,lpconfig->file); + fclose(lpconfig->file); + lpconfig->file=NULL; lpconfig->modified=0; } @@ -386,6 +411,7 @@ void lp_item_set_value(LpItem *item, const char *value){ static void _lp_config_destroy(LpConfig *lpconfig){ if (lpconfig->filename!=NULL) ortp_free(lpconfig->filename); + if (lpconfig->tmpfilename) ortp_free(lpconfig->tmpfilename); ms_list_for_each(lpconfig->sections,(void (*)(void*))lp_section_destroy); ms_list_free(lpconfig->sections); free(lpconfig); @@ -457,10 +483,10 @@ int lp_config_get_int(const LpConfig *lpconfig,const char *section, const char * const char *str=lp_config_get_string(lpconfig,section,key,NULL); if (str!=NULL) { int ret=0; - + if (strstr(str,"0x")==str){ sscanf(str,"%x",&ret); - }else + }else sscanf(str,"%i",&ret); return ret; } @@ -493,14 +519,14 @@ void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *ke if (sec!=NULL){ item=lp_section_find_item(sec,key); if (item!=NULL){ - if (value!=NULL) + if (value!=NULL && value[0] != '\0') lp_item_set_value(item,value); else lp_section_remove_item(sec,item); }else{ - if (value!=NULL) + if (value!=NULL && value[0] != '\0') lp_section_add_item(sec,lp_item_new(key,value)); } - }else if (value!=NULL){ + }else if (value!=NULL && value[0] != '\0'){ sec=lp_section_new(section); lp_config_add_section(lpconfig,sec); lp_section_add_item(sec,lp_item_new(key,value)); @@ -542,12 +568,19 @@ void lp_config_set_float(LpConfig *lpconfig,const char *section, const char *key void lp_item_write(LpItem *item, FILE *file){ if (item->is_comment) fprintf(file,"%s",item->value); - else + else if (item->value && item->value[0] != '\0' ) fprintf(file,"%s=%s\n",item->key,item->value); + else { + ms_warning("Not writing item %s to file, it is empty", item->key); + } } void lp_section_param_write(LpSectionParam *param, FILE *file){ - fprintf(file, " %s=%s", param->key, param->value); + if( param->value && param->value[0] != '\0') { + fprintf(file, " %s=%s", param->key, param->value); + } else { + ms_warning("Not writing param %s to file, it is empty", param->key); + } } void lp_section_write(LpSection *sec, FILE *file){ @@ -566,7 +599,7 @@ int lp_config_sync(LpConfig *lpconfig){ /* don't create group/world-accessible files */ (void) umask(S_IRWXG | S_IRWXO); #endif - file=fopen(lpconfig->filename,"w"); + file=fopen(lpconfig->tmpfilename,"w"); if (file==NULL){ ms_warning("Could not write %s ! Maybe it is read-only. Configuration will not be saved.",lpconfig->filename); lpconfig->readonly=1; @@ -574,6 +607,16 @@ int lp_config_sync(LpConfig *lpconfig){ } ms_list_for_each2(lpconfig->sections,(void (*)(void *,void*))lp_section_write,(void *)file); fclose(file); +#ifdef RENAME_REQUIRES_NONEXISTENT_NEW_PATH + /* On windows, rename() does not accept that the newpath is an existing file, while it is accepted on Unix. + * As a result, we are forced to first delete the linphonerc file, and then rename.*/ + if (remove(lpconfig->filename)!=0){ + ms_error("Cannot remove %s: %s",lpconfig->filename, strerror(errno)); + } +#endif + if (rename(lpconfig->tmpfilename,lpconfig->filename)!=0){ + ms_error("Cannot rename %s into %s: %s",lpconfig->tmpfilename,lpconfig->filename,strerror(errno)); + } lpconfig->modified=0; return 0; } @@ -650,3 +693,66 @@ const char* lp_config_get_default_string(const LpConfig *lpconfig, const char *s return lp_config_get_string(lpconfig, default_section, key, default_value); } + +static char *_lp_config_dirname(char *path) { +#ifdef _MSC_VER +#ifdef WINAPI_FAMILY_PHONE_APP + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + _splitpath(path, drive, dir, fname, ext); + return ms_strdup_printf("%s%s", drive, dir); +#else + char *dir = ms_strdup(path); + PathRemoveFileSpec(dir); + return dir; +#endif +#else + char *tmp = ms_strdup(path); + char *dir = ms_strdup(dirname(tmp)); + ms_free(tmp); + return dir; +#endif +} + +void lp_config_write_relative_file(const LpConfig *lpconfig, const char *filename, const char *data) { + if(strlen(data) > 0) { + char *dir = _lp_config_dirname(lpconfig->filename); + char *filepath = ms_strdup_printf("%s/%s", dir, filename); + FILE *file = fopen(filepath, "w"); + if(file != NULL) { + fprintf(file, "%s", data); + fclose(file); + } else { + ms_error("Could not open %s for write", filepath); + } + ms_free(dir); + ms_free(filepath); + } else { + ms_warning("%s has not been created because there is no data to write", filename); + } +} + +char *lp_config_read_relative_file(const LpConfig *lpconfig, const char *filename) { + char *dir = _lp_config_dirname(lpconfig->filename); + char *filepath = ms_strdup_printf("%s/%s", dir, filename); + char *result = NULL; + if(ortp_file_exist(filepath) == 0) { + FILE *file = fopen(filepath, "r"); + if(file != NULL) { + result = ms_new0(char, MAX_LEN); + if(fgets(result, MAX_LEN, file) == NULL) { + ms_error("%s could not be loaded", filepath); + } + fclose(file); + } else { + ms_error("Could not open %s for read", filepath); + } + } else { + ms_message("%s does not exist", filepath); + } + ms_free(dir); + ms_free(filepath); + return result; +} diff --git a/coreapi/lpconfig.h b/coreapi/lpconfig.h index bd229803e..3498f00d2 100644 --- a/coreapi/lpconfig.h +++ b/coreapi/lpconfig.h @@ -272,6 +272,22 @@ LINPHONE_PUBLIC LpConfig *lp_config_ref(LpConfig *lpconfig); **/ LINPHONE_PUBLIC void lp_config_unref(LpConfig *lpconfig); +/** + * @brief Write a string in a file placed relatively with the Linphone configuration file. + * @param lpconfig LpConfig instance used as a reference + * @param filename Name of the file where to write data. The name is relative to the place of the config file + * @param data String to write + */ +LINPHONE_PUBLIC void lp_config_write_relative_file(const LpConfig *lpconfig, const char *filename, const char *data); + +/** + * @brief Read a string from a file placed relatively with the Linphone configuration file + * @param lpconfig LpConfig instance used as a reference + * @param filename Name of the file where data will be read from. The name is relative to the place of the config file + * @return The read string + */ +LINPHONE_PUBLIC char *lp_config_read_relative_file(const LpConfig *lpconfig, const char *filename); + #ifdef __cplusplus } #endif diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c index 7caf4536b..8cbd088f2 100644 --- a/coreapi/message_storage.c +++ b/coreapi/message_storage.c @@ -21,10 +21,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "linphonecore.h" #ifdef MSG_STORAGE_ENABLED +#ifndef PRIu64 +#define PRIu64 "I64u" +#endif #include "sqlite3.h" -static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){ +static ORTP_INLINE LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){ MSList* transients = cr->transient_messages; LinphoneChatMessage* chat; while( transients ){ @@ -37,6 +40,49 @@ static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, u return NULL; } +/* DB layout: + * | 0 | storage_id + * | 1 | type + * | 2 | subtype + * | 3 | name + * | 4 | encoding + * | 5 | size + * | 6 | data + */ +// Callback for sql request when getting linphone content +static int callback_content(void *data, int argc, char **argv, char **colName) { + LinphoneChatMessage *message = (LinphoneChatMessage *)data; + + if (message->file_transfer_information) { + linphone_content_uninit(message->file_transfer_information); + ms_free(message->file_transfer_information); + message->file_transfer_information = NULL; + } + message->file_transfer_information = (LinphoneContent *)malloc(sizeof(LinphoneContent)); + memset(message->file_transfer_information, 0, sizeof(*(message->file_transfer_information))); + + message->file_transfer_information->type = argv[1] ? ms_strdup(argv[1]) : NULL; + message->file_transfer_information->subtype = argv[2] ? ms_strdup(argv[2]) : NULL; + message->file_transfer_information->name = argv[3] ? ms_strdup(argv[3]) : NULL; + message->file_transfer_information->encoding = argv[4] ? ms_strdup(argv[4]) : NULL; + message->file_transfer_information->size = (size_t) atoi(argv[5]); + + return 0; +} + +static void fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id) { + char* errmsg = NULL; + int ret; + char * buf; + + buf = sqlite3_mprintf("SELECT * FROM content WHERE id = %i", content_id); + ret = sqlite3_exec(db, buf, callback_content, message, &errmsg); + if (ret != SQLITE_OK) { + ms_error("Error in creation: %s.", errmsg); + sqlite3_free(errmsg); + } + sqlite3_free(buf); +} /* DB layout: * | 0 | storage_id @@ -50,10 +96,12 @@ static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, u * | 8 | external body url * | 9 | utc timestamp * | 10 | app data text + * | 11 | linphone content */ static void create_chat_message(char **argv, void *data){ LinphoneChatRoom *cr = (LinphoneChatRoom *)data; LinphoneAddress *from; + LinphoneAddress *to; unsigned int storage_id = atoi(argv[0]); @@ -65,12 +113,18 @@ static void create_chat_message(char **argv, void *data){ if(atoi(argv[3])==LinphoneChatMessageIncoming){ new_message->dir=LinphoneChatMessageIncoming; from=linphone_address_new(argv[2]); + to=linphone_address_new(argv[1]); } else { new_message->dir=LinphoneChatMessageOutgoing; from=linphone_address_new(argv[1]); + to=linphone_address_new(argv[2]); } linphone_chat_message_set_from(new_message,from); linphone_address_destroy(from); + if (to){ + linphone_chat_message_set_to(new_message,to); + linphone_address_destroy(to); + } if( argv[9] != NULL ){ new_message->time = (time_t)atol(argv[9]); @@ -83,6 +137,13 @@ static void create_chat_message(char **argv, void *data){ new_message->storage_id=storage_id; new_message->external_body_url= argv[8] ? ms_strdup(argv[8]) : NULL; new_message->appdata = argv[10]? ms_strdup(argv[10]) : NULL; + + if (argv[11] != NULL) { + int id = atoi(argv[11]); + if (id >= 0) { + fetch_content_from_database(cr->lc->db, new_message, id); + } + } } cr->messages_hist=ms_list_prepend(cr->messages_hist,new_message); } @@ -105,7 +166,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 +176,7 @@ int linphone_sql_request(sqlite3* db,const char *stmt){ int ret; ret=sqlite3_exec(db,stmt,NULL,NULL,&errmsg); if(ret != SQLITE_OK) { - ms_error("linphone_sql_request: error sqlite3_exec(): %s.\n", errmsg); + ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg); sqlite3_free(errmsg); } return ret; @@ -127,29 +188,59 @@ void linphone_sql_request_all(sqlite3* db,const char *stmt, LinphoneCore* lc){ int ret; ret=sqlite3_exec(db,stmt,callback_all,lc,&errmsg); if(ret != SQLITE_OK) { - ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.\n", errmsg); + ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.", errmsg); sqlite3_free(errmsg); } } +static int linphone_chat_message_store_content(LinphoneChatMessage *msg) { + LinphoneCore *lc = linphone_chat_room_get_lc(msg->chat_room); + int id = -1; + if (lc->db) { + LinphoneContent *content = msg->file_transfer_information; + char *buf = sqlite3_mprintf("INSERT INTO content VALUES(NULL,%Q,%Q,%Q,%Q,%i,%Q);", + content->type, + content->subtype, + content->name, + content->encoding, + content->size, + NULL + ); + linphone_sql_request(lc->db, buf); + sqlite3_free(buf); + id = (unsigned int) sqlite3_last_insert_rowid (lc->db); + } + return id; +} + unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){ LinphoneCore *lc=linphone_chat_room_get_lc(msg->chat_room); - int id=0; + int id = 0; if (lc->db){ - char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room)); - char *local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg)); - char *buf=sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%i,%Q);", + int content_id = -1; + char *peer; + char *local_contact; + char *buf; + if (msg->file_transfer_information) { + content_id = linphone_chat_message_store_content(msg); + } + + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room)); + local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg)); + buf = sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%lld,%Q,%i);", local_contact, - peer, - msg->dir, - msg->message, - "-1", /* use UTC field now */ - msg->is_read, - msg->state, - msg->external_body_url, - msg->time, - msg->appdata); + peer, + msg->dir, + msg->message, + "-1", /* use UTC field now */ + msg->is_read, + msg->state, + msg->external_body_url, + (int64_t)msg->time, + msg->appdata, + content_id + ); linphone_sql_request(lc->db,buf); sqlite3_free(buf); ms_free(local_contact); @@ -162,8 +253,8 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){ void linphone_chat_message_store_state(LinphoneChatMessage *msg){ LinphoneCore *lc=msg->chat_room->lc; if (lc->db){ - char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (message = %Q OR url = %Q) AND utc = %i;", - msg->state,msg->message,msg->external_body_url,msg->time); + char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %i);", + msg->state,msg->storage_id); linphone_sql_request(lc->db,buf); sqlite3_free(buf); } @@ -189,11 +280,13 @@ void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){ void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); int read=1; + char *peer; + char *buf; if (lc->db==NULL) return ; - char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - char *buf=sqlite3_mprintf("UPDATE history SET read=%i WHERE remoteContact = %Q;", + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + buf=sqlite3_mprintf("UPDATE history SET read=%i WHERE remoteContact = %Q;", read,peer); linphone_sql_request(lc->db,buf); sqlite3_free(buf); @@ -202,24 +295,28 @@ void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { LinphoneCore *lc=linphone_chat_room_get_lc(cr); + char *buf; if (lc->db==NULL) return ; - char *buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%i;",msg->external_body_url,msg->storage_id); + buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%i;",msg->external_body_url,msg->storage_id); linphone_sql_request(lc->db,buf); sqlite3_free(buf); } -int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ +static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); int numrows=0; + char *peer; + char *buf; + sqlite3_stmt *selectStatement; + int returnValue; if (lc->db==NULL) return 0; - char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - char *buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q AND read = 0;",peer); - sqlite3_stmt *selectStatement; - int returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL); + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?"AND read = 0":""); + returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL); if (returnValue == SQLITE_OK){ if(sqlite3_step(selectStatement) == SQLITE_ROW){ numrows= sqlite3_column_int(selectStatement, 0); @@ -231,53 +328,85 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ return numrows; } +int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ + return linphone_chat_room_get_messages_count(cr, TRUE); +} + +int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){ + return linphone_chat_room_get_messages_count(cr, FALSE); +} + void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { LinphoneCore *lc=cr->lc; + char *buf; if (lc->db==NULL) return ; - char *buf=sqlite3_mprintf("DELETE FROM history WHERE id = %i;", msg->storage_id); + buf=sqlite3_mprintf("DELETE FROM history WHERE id = %i;", msg->storage_id); linphone_sql_request(lc->db,buf); sqlite3_free(buf); } void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ LinphoneCore *lc=cr->lc; + char *peer; + char *buf; if (lc->db==NULL) return ; - char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - char *buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer); + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer); linphone_sql_request(lc->db,buf); sqlite3_free(buf); ms_free(peer); } -MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ +MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); MSList *ret; char *buf; char *peer; uint64_t begin,end; + int buf_max_size = 512; if (lc->db==NULL) return NULL; - peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + cr->messages_hist = NULL; - if (nb_message > 0) - buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC LIMIT %i ;",peer,nb_message); - else - buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC;",peer); + + /*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/ + buf=ms_malloc(buf_max_size); + buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer); + + if (startm<0) startm=0; + + if (endm>0&&endm>=startm){ + buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT %i ",buf,endm+1-startm); + }else if(startm>0){ + ms_message("%s(): end is lower than start (%d < %d). No end assumed.",__FUNCTION__,endm,startm); + buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT -1",buf); + } + + if (startm>0){ + buf=sqlite3_snprintf(buf_max_size-1,buf,"%s OFFSET %i ",buf,startm); + } + begin=ortp_get_cur_time_ms(); linphone_sql_request_message(lc->db,buf,cr); end=ortp_get_cur_time_ms(); - ms_message("linphone_chat_room_get_history(): completed in %i ms",(int)(end-begin)); - sqlite3_free(buf); + ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin)); + ms_free(buf); ret=cr->messages_hist; cr->messages_hist=NULL; ms_free(peer); return ret; } +MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ + return linphone_chat_room_get_history_range(cr, 0, nb_message); +} + + void linphone_close_storage(sqlite3* db){ sqlite3_close(db); } @@ -333,7 +462,7 @@ static int migrate_messages_timestamp(void* data,int argc, char** argv, char** c time_t new_time = parse_time_from_db(argv[1]); if( new_time ){ /* replace 'time' by -1 and set 'utc' to the timestamp */ - char *buf = sqlite3_mprintf("UPDATE history SET utc=%i,time='-1' WHERE id=%i;", new_time, atoi(argv[0])); + char *buf = sqlite3_mprintf("UPDATE history SET utc=%lld,time='-1' WHERE id=%i;", new_time, atoi(argv[0])); if( buf) { linphone_sql_request((sqlite3*)data, buf); sqlite3_free(buf); @@ -357,9 +486,10 @@ static void linphone_migrate_timestamps(sqlite3* db){ sqlite3_free(errmsg); linphone_sql_request(db, "ROLLBACK"); } else { + uint64_t end; linphone_sql_request(db, "COMMIT"); - uint64_t end=ortp_get_cur_time_ms(); - ms_message("Migrated message timestamps to UTC in %i ms",(int)(end-begin)); + end=ortp_get_cur_time_ms(); + ms_message("Migrated message timestamps to UTC in %lu ms",(unsigned long)(end-begin)); } } @@ -373,7 +503,7 @@ void linphone_update_table(sqlite3* db) { ms_message("Table already up to date: %s.", errmsg); sqlite3_free(errmsg); } else { - ms_debug("Table updated successfully for URL."); + ms_debug("Table history updated successfully for URL."); } // for UTC timestamp storage @@ -382,7 +512,7 @@ void linphone_update_table(sqlite3* db) { ms_message("Table already up to date: %s.", errmsg); sqlite3_free(errmsg); } else { - ms_debug("Table updated successfully for UTC."); + ms_debug("Table history updated successfully for UTC."); // migrate from old text-based timestamps to unix time-based timestamps linphone_migrate_timestamps(db); } @@ -393,7 +523,32 @@ void linphone_update_table(sqlite3* db) { ms_message("Table already up to date: %s.", errmsg); sqlite3_free(errmsg); } else { - ms_debug("Table updated successfully for app-specific data."); + ms_debug("Table history updated successfully for app-specific data."); + } + + // new field for linphone content storage + ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN content INTEGER;",NULL,NULL,&errmsg); + if(ret != SQLITE_OK) { + ms_message("Table already up to date: %s.", errmsg); + sqlite3_free(errmsg); + } else { + ms_debug("Table history updated successfully for content data."); + ret = sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS content (" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "type TEXT," + "subtype TEXT," + "name TEXT," + "encoding TEXT," + "size INTEGER," + "data BLOB" + ");", + 0,0,&errmsg); + if(ret != SQLITE_OK) { + ms_error("Error in creation: %s.\n", errmsg); + sqlite3_free(errmsg); + } else { + ms_debug("Table content successfully created."); + } } } @@ -477,6 +632,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 +658,8 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ return 0; } +int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){ + return 0; +} + #endif diff --git a/coreapi/misc.c b/coreapi/misc.c index 38b0efa5d..6a9141ea1 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -69,7 +69,7 @@ static bool_t payload_type_enabled(const PayloadType *pt) { return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0); } -bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt){ +bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt){ if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){ return payload_type_enabled(pt); } @@ -77,12 +77,12 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *p return FALSE; } -bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt){ +bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt){ if (pt->type==PAYLOAD_VIDEO) return TRUE; return !!(pt->flags & PAYLOAD_TYPE_IS_VBR); } -int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){ +int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enabled){ if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){ payload_type_set_enable(pt,enabled); _linphone_core_codec_config_write(lc); @@ -108,7 +108,7 @@ const char *linphone_core_get_payload_type_description(LinphoneCore *lc, Payload return NULL; } -void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate){ +void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate){ if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){ if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){ pt->normal_bitrate=bitrate*1000; @@ -117,8 +117,9 @@ void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, i ms_error("Cannot set an explicit bitrate for codec %s/%i, because it is not VBR.",pt->mime_type,pt->clock_rate); return; } + } else { + ms_error("linphone_core_set_payload_type_bitrate() payload type not in audio or video list !"); } - ms_error("linphone_core_set_payload_type_bitrate() payload type not in audio or video list !"); } @@ -131,7 +132,7 @@ static double get_audio_payload_bandwidth_from_codec_bitrate(const PayloadType * double npacket=50; double packet_size; int bitrate; - + if (strcmp(payload_type_get_mime(&payload_type_aaceld_44k), payload_type_get_mime(pt))==0) { /*special case of aac 44K because ptime= 10ms*/ npacket=100; @@ -181,7 +182,7 @@ static int get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt, }else return (int)ceil(get_audio_payload_bandwidth_from_codec_bitrate(pt)/1000.0);/*rounding codec bandwidth should be avoid, specially for AMR*/ } -int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt){ +int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePayloadType *pt){ int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), linphone_core_get_upload_bandwidth(lc)); if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){ @@ -209,7 +210,7 @@ void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){ int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), linphone_core_get_upload_bandwidth(lc)); int max_codec_bitrate=0; - + for(elem=linphone_core_get_audio_codecs(lc);elem!=NULL;elem=elem->next){ PayloadType *pt=(PayloadType*)elem->data; if (payload_type_enabled(pt)){ @@ -250,7 +251,19 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, cons /* return TRUE if codec can be used with bandwidth, FALSE else*/ bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, const PayloadType *pt){ - return linphone_core_is_payload_type_usable_for_bandwidth(lc, pt, linphone_core_get_payload_type_bitrate(lc,pt)); + bool_t ret=linphone_core_is_payload_type_usable_for_bandwidth(lc, pt, linphone_core_get_payload_type_bitrate(lc,pt)); + if ((pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED) + && lc->sound_conf.capt_sndcard + && !(ms_snd_card_get_capabilities(lc->sound_conf.capt_sndcard) & MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER) + && linphone_core_echo_cancellation_enabled(lc) + && (pt->clock_rate!=16000 && pt->clock_rate!=8000) + && strcasecmp(pt->mime_type,"opus")!=0 + && ms_filter_lookup_by_name("MSWebRTCAEC")!=NULL){ + ms_warning("Payload type %s/%i cannot be used because software echo cancellation is required but is unable to operate at this rate.", + pt->mime_type,pt->clock_rate); + ret=FALSE; + } + return ret; } bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret){ @@ -421,8 +434,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ ms_error("Could not obtain stun server addrinfo."); return -1; } - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Stun lookup in progress...")); + linphone_core_notify_display_status(lc,_("Stun lookup in progress...")); /*create the two audio and video RTP sockets, and send STUN message to our stun server */ sock1=create_socket(call->media_ports[0].rtp_port); @@ -603,8 +615,7 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call) ms_warning("Fail to resolve STUN server for ICE gathering."); return -1; } - if (lc->vtable.display_status != NULL) - lc->vtable.display_status(lc, _("ICE local candidates gathering in progress...")); + linphone_core_notify_display_status(lc, _("ICE local candidates gathering in progress...")); /* Gather local host candidates. */ if (linphone_core_get_local_ip_for(AF_INET, NULL, local_addr) < 0) { @@ -658,7 +669,7 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call) } else { call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed; } - if (call->params.has_video && (video_check_list != NULL)) { + if (call->params->has_video && (video_check_list != NULL)) { if (ice_check_list_state(video_check_list) == ICL_Completed) { switch (ice_check_list_selected_valid_candidate_type(video_check_list)) { case ICT_HostCandidate: @@ -678,12 +689,12 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call) } } else if (session_state == IS_Running) { call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; - if (call->params.has_video && (video_check_list != NULL)) { + if (call->params->has_video && (video_check_list != NULL)) { call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress; } } else { call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed; - if (call->params.has_video && (video_check_list != NULL)) { + if (call->params->has_video && (video_check_list != NULL)) { call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed; } } @@ -939,25 +950,13 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md){ int i; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; md && i < md->nb_streams; i++) { if (md->streams[i].type == SalVideo && md->streams[i].rtp_port!=0) return TRUE; } return FALSE; } -LinphoneCall * is_a_linphone_call(void *user_pointer){ - LinphoneCall *call=(LinphoneCall*)user_pointer; - if (call==NULL) return NULL; - return call->magic==linphone_call_magic ? call : NULL; -} - -LinphoneProxyConfig * is_a_linphone_proxy_config(void *user_pointer){ - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)user_pointer; - if (cfg==NULL) return NULL; - return cfg->magic==linphone_proxy_config_magic ? cfg : NULL; -} - unsigned int linphone_core_get_audio_features(LinphoneCore *lc){ unsigned int ret=0; const char *features=lp_config_get_string(lc->config,"sound","features",NULL); @@ -980,6 +979,8 @@ unsigned int linphone_core_get_audio_features(LinphoneCore *lc){ else if (strcasecmp(name,"DTMF")==0) ret|=AUDIO_STREAM_FEATURE_DTMF; else if (strcasecmp(name,"DTMF_ECHO")==0) ret|=AUDIO_STREAM_FEATURE_DTMF_ECHO; else if (strcasecmp(name,"MIXED_RECORDING")==0) ret|=AUDIO_STREAM_FEATURE_MIXED_RECORDING; + else if (strcasecmp(name,"LOCAL_PLAYING")==0) ret|=AUDIO_STREAM_FEATURE_LOCAL_PLAYING; + else if (strcasecmp(name,"REMOTE_PLAYING")==0) ret|=AUDIO_STREAM_FEATURE_REMOTE_PLAYING; else if (strcasecmp(name,"ALL")==0) ret|=AUDIO_STREAM_FEATURE_ALL; else if (strcasecmp(name,"NONE")==0) ret=0; else ms_error("Unsupported audio feature %s requested in config file.",name); @@ -1008,7 +1009,7 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size){ struct ifaddrs *ifpstart; char retaddr[LINPHONE_IPADDR_SIZE]={0}; bool_t found=FALSE; - + if (getifaddrs(&ifpstart) < 0) { return -1; } @@ -1109,6 +1110,9 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ int err; +#ifdef HAVE_GETIFADDRS + int found_ifs; +#endif strcpy(result,type==AF_INET ? "127.0.0.1" : "::1"); if (dest==NULL){ @@ -1124,8 +1128,6 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ #ifdef HAVE_GETIFADDRS /*we use getifaddrs for lookup of default interface */ - int found_ifs; - found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE); if (found_ifs==1){ return 0; @@ -1137,6 +1139,26 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ return 0; } +void linphone_core_get_local_ip(LinphoneCore *lc, int af, const char *dest, char *result) { + if (af == AF_UNSPEC) { + if (linphone_core_ipv6_enabled(lc)) { + bool_t has_ipv6 = linphone_core_get_local_ip_for(AF_INET6, dest, result) == 0; + if (strcmp(result, "::1") != 0) + return; /*this machine has real ipv6 connectivity*/ + if ((linphone_core_get_local_ip_for(AF_INET, dest, result) == 0) && (strcmp(result, "127.0.0.1") != 0)) + return; /*this machine has only ipv4 connectivity*/ + if (has_ipv6) { + /*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/ + strncpy(result, "::1", LINPHONE_IPADDR_SIZE); + return; + } + } + /*in all other cases use IPv4*/ + af = AF_INET; + } + linphone_core_get_local_ip_for(af, dest, result); +} + SalReason linphone_reason_to_sal(LinphoneReason reason){ switch(reason){ case LinphoneReasonNone: diff --git a/coreapi/player.c b/coreapi/player.c new file mode 100644 index 000000000..1b2a01022 --- /dev/null +++ b/coreapi/player.c @@ -0,0 +1,198 @@ + +/* +linphone +Copyright (C) 2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "private.h" + +/** + * Open a new source on this player. + * @param obj the player + * @param filename file to open. + * @param cb a callback used to notify end of play. + * @param user_data a user-data provided in the callback to help the application to retrieve its context. + * @return 0 if successful, -1 otherwise +**/ +int linphone_player_open(LinphonePlayer *obj, const char *filename, LinphonePlayerEofCallback cb, void *user_data){ + obj->user_data=user_data; + obj->cb=cb; + return obj->open(obj,filename); +} + +/** + * Start a play operation. The player must have been open previously with linphone_player_open(). + * @param obj the player. + * @return 0 if successful, -1 otherwise +**/ +int linphone_player_start(LinphonePlayer *obj){ + return obj->start(obj); +} + +/** + * Suspend a play operation. The player must have been started previously with linphone_player_start(). + * @param obj the player. + * @return 0 if successful, -1 otherwise +**/ +int linphone_player_pause(LinphonePlayer *obj){ + return obj->pause(obj); +} + +/** + * Seek at a given position given in milliseconds. The player must be in the paused state. + * @param obj the player. + * @param time_ms the position to seek to. + * @return 0 if successful, -1 otherwise +**/ +int linphone_player_seek(LinphonePlayer *obj, int time_ms){ + return obj->seek(obj,time_ms); +} + +/** + * Get the state of play operation. + * @param obj the player. + * @return the state of the player within MSPlayerClosed, MSPlayerStarted, MSPlayerPaused. +**/ +MSPlayerState linphone_player_get_state(LinphonePlayer *obj){ + return obj->get_state(obj); +} + +/** + * Get the duration of the media + * @param obj the player + * @return The duration in milliseconds + */ +int linphone_player_get_duration(LinphonePlayer *obj) { + return obj->get_duration(obj); +} + +/** + * Get the position of the playback + * @param obj the player + * @return Position of the playback in milliseconds + */ +int linphone_player_get_current_position(LinphonePlayer *obj) { + return obj->get_position(obj); +} + +/** + * Close the player. + * @param obj the player. +**/ +void linphone_player_close(LinphonePlayer *obj){ + return obj->close(obj); +} + +/** + * @brief Destroy a player + * @param obj The player + */ +void linphone_player_destroy(LinphonePlayer *obj) { + if(obj->destroy) obj->destroy(obj); +} + +void _linphone_player_destroy(LinphonePlayer *player) { + ms_free(player); +} + + +/* + * Call player implementation below. + */ + + +static bool_t call_player_check_state(LinphonePlayer *player, bool_t check_player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (call->state!=LinphoneCallStreamsRunning){ + ms_warning("Call [%p]: in-call player not usable in state [%s]",call,linphone_call_state_to_string(call->state)); + return FALSE; + } + if (call->audiostream==NULL) { + ms_error("call_player_check_state(): no audiostream."); + return FALSE; + } + if (check_player && call->audiostream->av_player.player==NULL){ + ms_error("call_player_check_state(): no player."); + return FALSE; + } + return TRUE; +} + +static void on_eof(void *user_data, MSFilter *f, unsigned int event_id, void *arg){ + LinphonePlayer *player=(LinphonePlayer *)user_data; + if (player->cb) player->cb(player,player->user_data); +} + +static int call_player_open(LinphonePlayer* player, const char *filename){ + LinphoneCall *call=(LinphoneCall*)player->impl; + MSFilter *filter; + if (!call_player_check_state(player,FALSE)) return -1; + filter=audio_stream_open_remote_play(call->audiostream,filename); + if (!filter) return -1; + ms_filter_add_notify_callback(filter,&on_eof,player,FALSE); + return 0; +} + +static int call_player_start(LinphonePlayer *player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (!call_player_check_state(player,TRUE)) return -1; + return ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_START); +} + +static int call_player_pause(LinphonePlayer *player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (!call_player_check_state(player,TRUE)) return -1; + return ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_PAUSE); +} + +static MSPlayerState call_player_get_state(LinphonePlayer *player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + MSPlayerState state=MSPlayerClosed; + if (!call_player_check_state(player,TRUE)) return MSPlayerClosed; + ms_filter_call_method(call->audiostream->av_player.player,MS_PLAYER_GET_STATE,&state); + return state; +} + +static int call_player_seek(LinphonePlayer *player, int time_ms){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (!call_player_check_state(player,TRUE)) return -1; + return ms_filter_call_method(call->audiostream->av_player.player,MS_PLAYER_SEEK_MS,&time_ms); +} + +static void call_player_close(LinphonePlayer *player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (!call_player_check_state(player,TRUE)) return; + audio_stream_close_remote_play(call->audiostream); + +} + +static void on_call_destroy(void *obj, belle_sip_object_t *call_being_destroyed){ + _linphone_player_destroy(obj); +} + +LinphonePlayer *linphone_call_build_player(LinphoneCall *call){ + LinphonePlayer *obj=ms_new0(LinphonePlayer,1); + obj->open=call_player_open; + obj->close=call_player_close; + obj->start=call_player_start; + obj->seek=call_player_seek; + obj->pause=call_player_pause; + obj->get_state=call_player_get_state; + obj->impl=call; + belle_sip_object_weak_ref(call,on_call_destroy,obj); + return obj; +} diff --git a/coreapi/presence.c b/coreapi/presence.c index 97aca82b4..53d206ea5 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -89,9 +89,9 @@ static char presence_id_valid_start_characters[] = ":_abcdefghijklmnopqrstuvwxyz static char * generate_presence_id(void) { char id[7]; int i; - id[0] = presence_id_valid_start_characters[random() % (sizeof(presence_id_valid_start_characters)-1)]; + id[0] = presence_id_valid_start_characters[ortp_random() % (sizeof(presence_id_valid_start_characters)-1)]; for (i = 1; i < 6; i++) { - id[i] = presence_id_valid_characters[random() % (sizeof(presence_id_valid_characters)-1)]; + id[i] = presence_id_valid_characters[ortp_random() % (sizeof(presence_id_valid_characters)-1)]; } id[6] = '\0'; @@ -1443,9 +1443,9 @@ void linphone_core_add_subscriber(LinphoneCore *lc, const char *subscriber, SalO linphone_friend_set_inc_subscribe_policy(fl,LinphoneSPAccept); fl->inc_subscribe_pending=TRUE; lc->subscribers=ms_list_append(lc->subscribers,(void *)fl); - if (lc->vtable.new_subscription_requested!=NULL) { + { char *tmp=linphone_address_as_string(fl->uri); - lc->vtable.new_subscription_requested(lc,fl,tmp); + linphone_core_notify_new_subscription_requested(lc,fl,tmp); ms_free(tmp); } } @@ -1876,8 +1876,7 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa } lf->presence = presence; lf->subscribe_active=TRUE; - if (lc->vtable.notify_presence_received) - lc->vtable.notify_presence_received(lc,(LinphoneFriend*)lf); + linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf); ms_free(tmp); }else{ ms_message("But this person is not part of our friend list, so we don't care."); diff --git a/coreapi/private.h b/coreapi/private.h index 2df416fba..e42d6c177 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -80,6 +80,8 @@ extern "C" { #endif struct _LinphoneCallParams{ + belle_sip_object_t base; + void *user_data; LinphoneCall *referer; /*in case this call creation is consecutive to an incoming transfer, this points to the original call */ int audio_bw; /* bandwidth limit for audio stream */ LinphoneMediaEncryption media_encryption; @@ -100,10 +102,14 @@ struct _LinphoneCallParams{ bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/ bool_t in_conference; /*in conference mode */ bool_t low_bandwidth; + bool_t no_user_consent;/*when set to TRUE an UPDATE request will be used instead of reINVITE*/ + uint16_t avpf_rr_interval; /*in milliseconds*/ LinphonePrivacyMask privacy; - uint16_t avpf_rr_interval; }; +BELLE_SIP_DECLARE_VPTR(LinphoneCallParams); + + struct _LinphoneQualityReporting{ reporting_session_report_t * reports[2]; /**Store information on audio and video media streams (RFC 6035) */ bool_t was_video_running; /*Keep video state since last check in order to detect its (de)activation*/ @@ -111,26 +117,28 @@ struct _LinphoneQualityReporting{ }; struct _LinphoneCallLog{ + belle_sip_object_t base; + void *user_data; struct _LinphoneCore *lc; LinphoneCallDir dir; /**< The direction of the call*/ LinphoneCallStatus status; /**< The status of the call*/ LinphoneAddress *from; /**config, "proxy", "contact_parameters", NULL) : NULL; const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL; - memset(obj, 0, sizeof(LinphoneProxyConfig)); - obj->magic = linphone_proxy_config_magic; obj->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600; - obj->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 0) : 0; + obj->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 1) : 1; obj->dial_prefix = dial_prefix ? ms_strdup(dial_prefix) : NULL; obj->dial_escape_plus = lc ? lp_config_get_default_int(lc->config, "proxy", "dial_escape_plus", 0) : 0; obj->privacy = lc ? lp_config_get_default_int(lc->config, "proxy", "privacy", LinphonePrivacyDefault) : LinphonePrivacyDefault; obj->reg_identity = identity ? ms_strdup(identity) : NULL; obj->reg_proxy = proxy ? ms_strdup(proxy) : NULL; obj->reg_route = route ? ms_strdup(route) : NULL; + obj->domain = NULL; obj->realm = realm ? ms_strdup(realm) : NULL; obj->quality_reporting_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0; obj->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL; obj->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 0) : 0; obj->contact_params = contact_params ? ms_strdup(contact_params) : NULL; obj->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL; - obj->avpf_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf", 0) : 0; + obj->avpf_mode = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf", LinphoneAVPFDefault) : LinphoneAVPFDefault; obj->avpf_rr_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf_rr_interval", 5) : 5; obj->publish_expires=-1; } @@ -133,20 +132,35 @@ LinphoneProxyConfig *linphone_proxy_config_new() { return linphone_core_create_proxy_config(NULL); } +static void _linphone_proxy_config_destroy(LinphoneProxyConfig *obj); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneProxyConfig); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneProxyConfig, belle_sip_object_t, + (belle_sip_object_destroy_t)_linphone_proxy_config_destroy, + NULL, // clone + NULL, // marshal + FALSE +); + LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) { - LinphoneProxyConfig *obj=NULL; - obj=ms_new(LinphoneProxyConfig,1); + LinphoneProxyConfig *obj = belle_sip_object_new(LinphoneProxyConfig); linphone_proxy_config_init(lc,obj); return obj; } -/** - * Destroys a proxy config. - * - * @note: LinphoneProxyConfig that have been removed from LinphoneCore with - * linphone_core_remove_proxy_config() must not be freed. -**/ -void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ +void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj){ + if (obj->op) { + sal_op_release(obj->op); + obj->op=NULL; + } + if (obj->publish_op){ + sal_op_release(obj->publish_op); + obj->publish_op=NULL; + } +} + +void _linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy); if (obj->reg_identity!=NULL) ms_free(obj->reg_identity); if (obj->reg_route!=NULL) ms_free(obj->reg_route); @@ -156,13 +170,36 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ if (obj->realm!=NULL) ms_free(obj->realm); if (obj->type!=NULL) ms_free(obj->type); if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix); - if (obj->op) sal_op_release(obj->op); - if (obj->publish_op) sal_op_release(obj->publish_op); if (obj->contact_params) ms_free(obj->contact_params); if (obj->contact_uri_params) ms_free(obj->contact_uri_params); if (obj->saved_proxy!=NULL) linphone_address_destroy(obj->saved_proxy); if (obj->saved_identity!=NULL) linphone_address_destroy(obj->saved_identity); - ms_free(obj); + _linphone_proxy_config_release_ops(obj); +} + +/** + * Destroys a proxy config. + * @deprecated + * + * @note: LinphoneProxyConfig that have been removed from LinphoneCore with + * linphone_core_remove_proxy_config() must not be freed. +**/ +void linphone_proxy_config_destroy(LinphoneProxyConfig *cfg) { + belle_sip_object_unref(cfg); +} + +void _linphone_proxy_config_release(LinphoneProxyConfig *cfg) { + _linphone_proxy_config_release_ops(cfg); + belle_sip_object_unref(cfg); +} + +LinphoneProxyConfig *linphone_proxy_config_ref(LinphoneProxyConfig *cfg) { + belle_sip_object_ref(cfg); + return cfg; +} + +void linphone_proxy_config_unref(LinphoneProxyConfig *cfg) { + belle_sip_object_unref(cfg); } /** @@ -278,14 +315,14 @@ int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route) bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){ if (obj->reg_proxy==NULL){ - if (lc && lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\"" + if (lc) + linphone_core_notify_display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\"" " followed by a hostname.")); return FALSE; } if (obj->reg_identity==NULL){ - if (lc && lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like " + if (lc) + linphone_core_notify_display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like " "sip:username@proxydomain, such as sip:alice@example.net")); return FALSE; } @@ -445,9 +482,6 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ linphone_proxy_config_set_state(obj,LinphoneRegistrationCleared,"Registration cleared"); } _linphone_proxy_config_unregister(obj); - - - } } @@ -847,8 +881,11 @@ static bool_t is_a_phone_number(const char *username){ *p==')' || *p=='(' || *p=='/' || - *p=='+') continue; - else return FALSE; + *p=='+' || + (unsigned char)*p== 0xca // non-breakable space (iOS uses it to format contacts phone number) + ) + continue; + return FALSE; } return TRUE; } @@ -1108,7 +1145,7 @@ int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){ ms_warning("ProxyConfig already entered, ignored."); return 0; } - lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg); + lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)linphone_proxy_config_ref(cfg)); linphone_proxy_config_apply(cfg,lc); return 0; } @@ -1134,10 +1171,7 @@ void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cf linphone_proxy_config_edit(cfg); linphone_proxy_config_enable_register(cfg,FALSE); linphone_proxy_config_done(cfg); - linphone_proxy_config_update(cfg); /*so that it has an effect*/ - - /*as cfg no longer in proxies, unregister will never be issued*/ - _linphone_proxy_config_unregister(cfg); + linphone_proxy_config_update(cfg); } if (lc->default_proxy==cfg){ lc->default_proxy=NULL; @@ -1158,14 +1192,25 @@ void linphone_core_clear_proxy_config(LinphoneCore *lc){ ms_list_free(copy); linphone_proxy_config_write_all_to_config_file(lc); } + +static int linphone_core_get_default_proxy_config_index(LinphoneCore *lc) { + int pos = -1; + if (lc->default_proxy != NULL) { + pos = ms_list_position(lc->sip_conf.proxies, ms_list_find(lc->sip_conf.proxies, (void *)lc->default_proxy)); + } + return pos; +} + /** * Sets the default proxy. * * This default proxy must be part of the list of already entered LinphoneProxyConfig. * Toggling it as default will make LinphoneCore use the identity associated with * the proxy configuration in all incoming and outgoing calls. + * @param[in] lc LinphoneCore object + * @param[in] config The proxy configuration to use as the default one. **/ -void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config){ +void linphone_core_set_default_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config){ /* check if this proxy is in our list */ if (config!=NULL){ if (ms_list_find(lc->sip_conf.proxies,config)==NULL){ @@ -1176,7 +1221,7 @@ void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *conf } lc->default_proxy=config; if (linphone_core_ready(lc)) - lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL)); + lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy_config_index(lc)); } void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){ @@ -1186,18 +1231,26 @@ void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){ /** * Returns the default proxy configuration, that is the one used to determine the current identity. + * @deprecated Use linphone_core_get_default_proxy_config() instead. **/ int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config){ - int pos=-1; if (config!=NULL) *config=lc->default_proxy; - if (lc->default_proxy!=NULL){ - pos=ms_list_position(lc->sip_conf.proxies,ms_list_find(lc->sip_conf.proxies,(void *)lc->default_proxy)); - } - return pos; + return linphone_core_get_default_proxy_config_index(lc); +} + +/** + * Returns the default proxy configuration, that is the one used to determine the current identity. + * @param[in] lc LinphoneCore object + * @return The default proxy configuration. +**/ +LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc) { + return lc->default_proxy; } /** * Returns an unmodifiable list of entered proxy configurations. + * @param[in] lc The LinphoneCore object + * @return \mslist{LinphoneProxyConfig} **/ const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){ return lc->sip_conf.proxies; @@ -1241,7 +1294,7 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC lp_config_set_int(config,key,"reg_expires",obj->expires); lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister); lp_config_set_int(config,key,"publish",obj->publish); - lp_config_set_int(config, key, "avpf", obj->avpf_enabled); + lp_config_set_int(config, key, "avpf", obj->avpf_mode); lp_config_set_int(config, key, "avpf_rr_interval", obj->avpf_rr_interval); lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus); lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix); @@ -1293,7 +1346,7 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc CONFIGURE_INT_VALUE(cfg,config,key,expires,"reg_expires") CONFIGURE_BOOL_VALUE(cfg,config,key,register,"reg_sendregister") CONFIGURE_BOOL_VALUE(cfg,config,key,publish,"publish") - CONFIGURE_BOOL_VALUE(cfg,config,key,avpf,"avpf") + CONFIGURE_INT_VALUE(cfg,config,key,avpf_mode,"avpf") CONFIGURE_INT_VALUE(cfg,config,key,avpf_rr_interval,"avpf_rr_interval") CONFIGURE_INT_VALUE(cfg,config,key,dial_escape_plus,"dial_escape_plus") CONFIGURE_STRING_VALUE(cfg,config,key,dial_prefix,"dial_prefix") @@ -1320,9 +1373,9 @@ static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){ caps=sip_setup_context_get_capabilities(ssc); if (caps & SIP_SETUP_CAP_ACCOUNT_MANAGER){ if (sip_setup_context_login_account(ssc,cfg->reg_identity,NULL,NULL)!=0){ - if (lc->vtable.display_warning){ + { char *tmp=ms_strdup_printf(_("Could not login as %s"),cfg->reg_identity); - lc->vtable.display_warning(lc,tmp); + linphone_core_notify_display_warning(lc,tmp); ms_free(tmp); } return; @@ -1358,12 +1411,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){ } #endif //BUILD_UPNP if (lc->sip_conf.register_only_when_network_is_up){ - LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc); - if (tunnel && linphone_tunnel_enabled(tunnel)){ - return linphone_tunnel_connected(tunnel); - }else{ - return lc->network_reachable; - } + return lc->network_reachable; } return TRUE; } @@ -1496,12 +1544,12 @@ void linphone_account_creator_destroy(LinphoneAccountCreator *obj){ } } -void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud) { - cr->user_data=ud; +void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cfg, void *ud) { + cfg->user_data = ud; } -void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) { - return cr->user_data; +void * linphone_proxy_config_get_user_data(const LinphoneProxyConfig *cfg) { + return cfg->user_data; } void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){ @@ -1522,9 +1570,8 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat if (update_friends){ linphone_core_update_friends_subscriptions(lc,cfg,TRUE); } - if (lc && lc->vtable.registration_state_changed){ - lc->vtable.registration_state_changed(lc,cfg,state,message); - } + if (lc) + linphone_core_notify_registration_state_changed(lc,cfg,state,message); } else { /*state already reported*/ } @@ -1607,11 +1654,22 @@ int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *obj) { } void linphone_proxy_config_enable_avpf(LinphoneProxyConfig *cfg, bool_t enable) { - cfg->avpf_enabled = enable; + cfg->avpf_mode=enable ? LinphoneAVPFEnabled : LinphoneAVPFDisabled; } bool_t linphone_proxy_config_avpf_enabled(LinphoneProxyConfig *cfg) { - return cfg->avpf_enabled; + if (cfg->avpf_mode==LinphoneAVPFDefault && cfg->lc){ + return linphone_core_get_avpf_mode(cfg->lc)==LinphoneAVPFEnabled; + } + return cfg->avpf_mode == LinphoneAVPFEnabled; +} + +LinphoneAVPFMode linphone_proxy_config_get_avpf_mode(const LinphoneProxyConfig *cfg){ + return cfg->avpf_mode; +} + +void linphone_proxy_config_set_avpf_mode(LinphoneProxyConfig *cfg, LinphoneAVPFMode mode){ + cfg->avpf_mode=mode; } void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig *cfg, uint8_t interval) { @@ -1622,3 +1680,7 @@ void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig *cfg, uint8_ uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cfg) { return cfg->avpf_rr_interval; } + +char* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg) { + return sal_op_get_public_uri(cfg->op); +} diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 63944e55d..52d88a7a2 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H -#include "../config.h" +#include "config.h" #endif #include "linphonecore.h" @@ -386,7 +386,7 @@ static void update_ip(LinphoneCall * call, int stats_type) { if (local_desc != NULL) { /*since this function might be called for video stream AFTER it has been uninitialized, local description might be invalid. In any other case, IP/port should be always filled and valid*/ - if (local_desc->rtp_addr != NULL && strlen(local_desc->rtp_addr) > 0) { + if (strlen(local_desc->rtp_addr) > 0) { call->log->reporting.reports[stats_type]->info.local_addr.port = local_desc->rtp_port; STR_REASSIGN(call->log->reporting.reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr)); } @@ -397,7 +397,7 @@ static void update_ip(LinphoneCall * call, int stats_type) { call->log->reporting.reports[stats_type]->info.remote_addr.port = remote_desc->rtp_port; /*for IP it can be not set if we are using a direct route*/ - if (remote_desc->rtp_addr != NULL && strlen(remote_desc->rtp_addr) > 0) { + if (strlen(remote_desc->rtp_addr) > 0) { STR_REASSIGN(call->log->reporting.reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr)); } else { STR_REASSIGN(call->log->reporting.reports[stats_type]->info.remote_addr.ip, ms_strdup(sal_call_get_remote_media_description(call->op)->addr)); @@ -405,15 +405,9 @@ static void update_ip(LinphoneCall * call, int stats_type) { } } -typedef struct on_action_suggested_struct{ - LinphoneCall *call; - int stats_type; -}on_action_suggested_struct_t; - static void qos_analyzer_on_action_suggested(void *user_data, int datac, const char** datav){ - on_action_suggested_struct_t * oass = (on_action_suggested_struct_t *)user_data; - LinphoneCall *call = oass->call; - reporting_session_report_t *report = call->log->reporting.reports[oass->stats_type]; + reporting_session_report_t *report = (reporting_session_report_t*)user_data; + LinphoneCall *call = report->call; char * appendbuf; int i; int ptime = -1; @@ -653,16 +647,16 @@ int linphone_reporting_publish_interval_report(LinphoneCall* call) { void linphone_reporting_call_state_updated(LinphoneCall *call){ LinphoneCallState state=linphone_call_get_state(call); + MSQosAnalyzer *analyzer; + int i; - if (! quality_reporting_enabled(call)){ + if (state == LinphoneCallReleased||!quality_reporting_enabled(call)){ return; } switch (state){ case LinphoneCallStreamsRunning:{ bool_t video_enabled=media_report_enabled(call, LINPHONE_CALL_STATS_VIDEO); - int i; MediaStream *streams[2] = {(MediaStream*) call->audiostream, (MediaStream *) call->videostream}; - MSQosAnalyzer *analyzer; for (i=0;i<2;i++){ if (streams[i]==NULL||streams[i]->rc==NULL){ @@ -673,14 +667,12 @@ void linphone_reporting_call_state_updated(LinphoneCall *call){ analyzer=ms_bitrate_controller_get_qos_analyzer(streams[i]->rc); if (analyzer){ - on_action_suggested_struct_t * oass = ms_new0(on_action_suggested_struct_t, 1); - oass->call = call; - oass->stats_type = i; + call->log->reporting.reports[i]->call=call; STR_REASSIGN(call->log->reporting.reports[i]->qos_analyzer.name, ms_strdup(ms_qos_analyzer_get_name(analyzer))); ms_qos_analyzer_set_on_action_suggested(analyzer, qos_analyzer_on_action_suggested, - oass); + call->log->reporting.reports[i]); } } linphone_reporting_update_ip(call); @@ -691,6 +683,16 @@ void linphone_reporting_call_state_updated(LinphoneCall *call){ break; } case LinphoneCallEnd:{ + MediaStream *streams[2] = {(MediaStream*) call->audiostream, (MediaStream *) call->videostream}; + for (i=0;i<2;i++){ + if (streams[i]==NULL||streams[i]->rc==NULL){ + continue; + } + analyzer=ms_bitrate_controller_get_qos_analyzer(streams[i]->rc); + if (analyzer){ + ms_qos_analyzer_set_on_action_suggested(analyzer, NULL, NULL); + } + } if (call->log->status==LinphoneCallSuccess || call->log->status==LinphoneCallAborted){ linphone_reporting_publish_session_report(call, TRUE); } diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index 319353fc0..794c78288 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -137,6 +137,7 @@ typedef struct reporting_session_report { // for internal processing time_t last_report_date; + LinphoneCall *call; } reporting_session_report_t; diff --git a/coreapi/remote_provisioning.c b/coreapi/remote_provisioning.c index 1b081a354..fd5d2eb92 100644 --- a/coreapi/remote_provisioning.c +++ b/coreapi/remote_provisioning.c @@ -60,7 +60,7 @@ static void linphone_remote_provisioning_apply(LinphoneCore *lc, const char *xml , error_msg); } -static int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path){ +int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path){ int status = -1; FILE* f = fopen(file_path, "r"); diff --git a/coreapi/sal.c b/coreapi/sal.c index 8a48c79d0..b8395c897 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -280,9 +280,11 @@ int sal_stream_description_equals(const SalStreamDescription *sd1, const SalStre if (sd1->proto != sd2->proto) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) { if ((sd1->crypto[i].tag != sd2->crypto[i].tag) - || (sd1->crypto[i].algo != sd2->crypto[i].algo) - || (strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) { - result |= SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED; + || (sd1->crypto[i].algo != sd2->crypto[i].algo)){ + result|=SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED; + } + if ((strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) { + result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED; } } @@ -307,7 +309,7 @@ int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaD int i; if (strcmp(md1->addr, md2->addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; - if (md1->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; + if (md1->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED; if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; for(i = 0; i < md1->nb_streams; ++i){ result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]); @@ -735,3 +737,9 @@ belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal) { return sal->stack; } +char* sal_op_get_public_uri(SalOp *op) { + if (op && op->refresher) { + return belle_sip_refresher_get_public_uri(op->refresher); + } + return NULL; +} diff --git a/coreapi/sipsetup.c b/coreapi/sipsetup.c index 91abf5d62..bf1b411e8 100644 --- a/coreapi/sipsetup.c +++ b/coreapi/sipsetup.c @@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H -#include "../config.h" +#include "config.h" #endif #include "linphonecore.h" diff --git a/coreapi/upnp.c b/coreapi/upnp.c index 562078570..c8082514f 100644 --- a/coreapi/upnp.c +++ b/coreapi/upnp.c @@ -834,7 +834,7 @@ int linphone_upnp_call_process(LinphoneCall *call) { linphone_core_start_update_call(lc, call); break; case LinphoneCallUpdatedByRemote: - linphone_core_start_accept_call_update(lc, call); + linphone_core_start_accept_call_update(lc, call,call->prevstate,linphone_call_state_to_string(call->prevstate)); break; case LinphoneCallOutgoingInit: linphone_core_proceed_with_invite_if_ready(lc, call, NULL); diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 0daee4a7d..f979376ef 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -18,7 +18,7 @@ UI_FILES= about.ui \ audio_assistant.ui PIXMAPS= \ - stock_people.png + stock_people.png LINPHONE_ICO_RC_FILE=linphone.rc LINPHONE_ICO_FILE=linphone.ico @@ -54,7 +54,8 @@ linphone_SOURCES= \ conference.c \ config-fetching.c \ audio_assistant.c \ - linphone.h + videowindow.c \ + linphone.h if BUILD_WIZARD linphone_SOURCES+= \ setupwizard.c @@ -84,7 +85,7 @@ endif AM_CFLAGS= -DIN_LINPHONE -I$(top_srcdir)/coreapi/ \ $(MEDIASTREAMER_CFLAGS) \ $(ORTP_CFLAGS) $(BELLESIP_CFLAGS) \ - $(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \ + $(STRICT_OPTIONS) $(STRICT_OPTIONS_CC) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \ $(TUNNEL_CFLAGS) \ $(SQLITE3_CFLAGS) diff --git a/gtk/audio_assistant.c b/gtk/audio_assistant.c index c394b02fa..83a89a3eb 100644 --- a/gtk/audio_assistant.c +++ b/gtk/audio_assistant.c @@ -168,11 +168,12 @@ static void dialog_click(GtkWidget *dialog, guint response_id, GtkWidget *page){ } static void calibration_finished(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay, void *data){ + GtkWidget * dialog; + GtkWidget *speaker_page; ms_message("echo calibration finished %s.",status==LinphoneEcCalibratorDone ? "successfully" : "with faillure"); if (status==LinphoneEcCalibratorDone) ms_message("Measured delay is %i",delay); - GtkWidget * dialog; - GtkWidget *speaker_page = get_widget_from_assistant("speaker_page"); + speaker_page = get_widget_from_assistant("speaker_page"); dialog = gtk_message_dialog_new ( GTK_WINDOW(audio_assistant), @@ -208,6 +209,7 @@ void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){ AudioStream *stream = NULL; MSSndCardManager *manager = ms_snd_card_manager_get(); gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); + gint timeout_id; if(active){ gchar *path = get_record_file(); @@ -217,12 +219,12 @@ void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){ path,NULL,ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); g_object_set_data(G_OBJECT(audio_assistant),"record_stream",stream); } - gint timeout_id = gtk_timeout_add(6000,(GtkFunction)linphone_gtk_stop_record,NULL); + timeout_id = gtk_timeout_add(6000,(GtkFunction)linphone_gtk_stop_record,NULL); g_object_set_data(G_OBJECT(audio_assistant),"timeout_id",GINT_TO_POINTER(timeout_id)); g_object_set_data(G_OBJECT(audio_assistant),"path",path); } else { stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"record_stream"); - gint timeout_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(audio_assistant),"timeout_id")); + timeout_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(audio_assistant),"timeout_id")); gtk_timeout_remove(timeout_id); if(stream != NULL){ audio_stream_stop(stream); @@ -322,7 +324,7 @@ static GtkWidget *create_intro(){ static GtkWidget *create_mic_page(){ GtkWidget *vbox=gtk_table_new(3,2,FALSE); LinphoneCore *lc=linphone_gtk_get_core(); - + const char **sound_devices; GtkWidget *labelMicChoice=gtk_label_new(_("Capture device")); GtkWidget *labelMicLevel=gtk_label_new(_("Recorded volume")); GtkWidget *mic_audiolevel=gtk_progress_bar_new(); @@ -348,8 +350,8 @@ static GtkWidget *create_mic_page(){ set_widget_to_assistant("mic_audiolevel",mic_audiolevel); set_widget_to_assistant("label_audiolevel",label_audiolevel); - - const char **sound_devices=linphone_core_get_sound_devices(lc); + + sound_devices=linphone_core_get_sound_devices(lc); linphone_gtk_fill_combo_box(capture_device, sound_devices, linphone_core_get_capture_device(lc), CAP_CAPTURE); gtk_widget_show_all(vbox); @@ -370,6 +372,7 @@ static GtkWidget *create_speaker_page(){ GtkWidget *playback_device=gtk_combo_box_new(); GtkWidget *mixer_button=gtk_button_new_with_label("System sound preferences"); GtkWidget *image; + const char **sound_devices; image=gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_MENU); gtk_button_set_image(GTK_BUTTON(mixer_button),image); @@ -382,7 +385,7 @@ static GtkWidget *create_speaker_page(){ gtk_table_set_row_spacings(GTK_TABLE(vbox),10); - const char **sound_devices=linphone_core_get_sound_devices(lc); + sound_devices=linphone_core_get_sound_devices(lc); linphone_gtk_fill_combo_box(playback_device, sound_devices, linphone_core_get_playback_device(lc),CAP_PLAYBACK); gtk_widget_show_all(vbox); @@ -414,9 +417,9 @@ static GtkWidget *create_play_record_page(){ gtk_table_attach(GTK_TABLE(vbox), rec_button, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0,0); gtk_table_attach_defaults(GTK_TABLE(vbox), labelPlay, 0, 1, 1, 2); gtk_table_attach(GTK_TABLE(vbox), play_button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0,0); - + gtk_widget_show_all(vbox); - + set_widget_to_assistant("rec_button",rec_button); set_widget_to_assistant("play_button",play_button); g_signal_connect(G_OBJECT(rec_button),"toggled",(GCallback)linphone_gtk_start_record_sound,vbox); @@ -480,18 +483,23 @@ void linphone_gtk_audio_assistant_apply(GtkWidget *w){ void linphone_gtk_show_audio_assistant(void){ GtkWidget *w; + GtkWidget *welcome; + GtkWidget *mic_page; + GtkWidget *speaker_page; + GtkWidget *play_record_page; + GtkWidget *end_page; if(audio_assistant!=NULL) return; w=audio_assistant=linphone_gtk_create_window("audio_assistant"); gtk_window_set_resizable (GTK_WINDOW(w), FALSE); gtk_window_set_title(GTK_WINDOW(w),_("Audio Assistant")); - - GtkWidget *welcome=create_intro(); - GtkWidget *mic_page=create_mic_page(); - GtkWidget *speaker_page=create_speaker_page(); - GtkWidget *play_record_page=create_play_record_page(); - GtkWidget *end_page=create_end_page(); + + welcome=create_intro(); + mic_page=create_mic_page(); + speaker_page=create_speaker_page(); + play_record_page=create_play_record_page(); + end_page=create_end_page(); gtk_assistant_append_page(GTK_ASSISTANT(w),welcome); gtk_assistant_set_page_type(GTK_ASSISTANT(w),welcome,GTK_ASSISTANT_PAGE_INTRO); diff --git a/gtk/calllogs.c b/gtk/calllogs.c index 7a4840aa8..a4b86240a 100644 --- a/gtk/calllogs.c +++ b/gtk/calllogs.c @@ -36,7 +36,7 @@ void call_log_selection_changed(GtkTreeView *v){ GtkTreeSelection *select; GtkTreeIter iter; GtkTreeModel *model=NULL; - + select = gtk_tree_view_get_selection(v); if (select!=NULL){ if (gtk_tree_selection_get_selected (select, &model, &iter)){ @@ -51,7 +51,7 @@ void call_log_selection_changed(GtkTreeView *v){ void linphone_gtk_call_log_chat_selected(GtkWidget *w){ GtkTreeSelection *select; GtkTreeIter iter; - + select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); if (select!=NULL){ GtkTreeModel *model=NULL; @@ -72,7 +72,7 @@ void linphone_gtk_call_log_chat_selected(GtkWidget *w){ void linphone_gtk_call_log_add_contact(GtkWidget *w){ GtkTreeSelection *select; GtkTreeIter iter; - + select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); if (select!=NULL){ GtkTreeModel *model=NULL; @@ -109,7 +109,7 @@ static bool_t put_selection_to_uribar(GtkWidget *treeview){ cl = (LinphoneCallLog *)pcl; la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl); tmp = linphone_address_as_string(la); - if(tmp!=NULL) + if(tmp!=NULL) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),tmp); ms_free(tmp); return TRUE; @@ -133,7 +133,7 @@ static GtkWidget *linphone_gtk_create_call_log_menu(GtkWidget *call_log){ GtkWidget *image; GtkTreeSelection *select; GtkTreeIter iter; - + select=gtk_tree_view_get_selection(GTK_TREE_VIEW(call_log)); if (select!=NULL){ GtkTreeModel *model=NULL; @@ -202,7 +202,7 @@ void linphone_gtk_call_log_clear_missed_call(){ GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU); GtkWidget *l; const gchar*text=gtk_label_get_text(GTK_LABEL(linphone_gtk_get_widget(mw,"label3"))); - + l=gtk_label_new(text); gtk_box_pack_start(GTK_BOX(box),image,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(box),l,FALSE,FALSE,0); @@ -228,7 +228,7 @@ void linphone_gtk_call_log_display_missed_call(int nb){ GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU); GtkWidget *l; gchar *buf; - + buf=g_markup_printf_escaped(_("Recent calls (%i)"),nb); l=gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(l),buf); @@ -281,7 +281,9 @@ void linphone_gtk_call_log_update(GtkWidget *w){ LinphoneFriend *lf=NULL; int duration=linphone_call_log_get_duration(cl); time_t start_date_time=linphone_call_log_get_start_date(cl); - + GdkPixbuf *incoming; + GdkPixbuf *outgoing; + #if GLIB_CHECK_VERSION(2,26,0) if (start_date_time){ GDateTime *dt=g_date_time_new_from_unix_local(start_date_time); @@ -332,7 +334,7 @@ void linphone_gtk_call_log_update(GtkWidget *w){ if (status==NULL) { headtxt=g_markup_printf_escaped(_("%s\t%s"),display,start_date ? start_date : ""); logtxt=g_markup_printf_escaped( - _("%s\t" + _("%s\t" "Quality: %s\n%s\t%s\t"), addr, quality, minutes, seconds); } else { @@ -346,8 +348,8 @@ void linphone_gtk_call_log_update(GtkWidget *w){ if (start_date) g_free(start_date); gtk_tree_store_append (store,&iter,NULL); - GdkPixbuf *incoming = create_pixbuf("call_status_incoming.png"); - GdkPixbuf *outgoing = create_pixbuf("call_status_outgoing.png"); + incoming = create_pixbuf("call_status_incoming.png"); + outgoing = create_pixbuf("call_status_outgoing.png"); gtk_tree_store_set (store,&iter, 0, linphone_call_log_get_dir(cl)==LinphoneCallOutgoing ? outgoing : incoming, 1, headtxt,2,cl,-1); diff --git a/gtk/chat.c b/gtk/chat.c index 9f6e21943..940437950 100644 --- a/gtk/chat.c +++ b/gtk/chat.c @@ -30,9 +30,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. const char *linphone_gtk_message_storage_get_db_file(const char *filename){ const int path_max=1024; static char *db_file=NULL; - + if (db_file) return db_file; - + db_file=(char *)malloc(path_max*sizeof(char)); if (filename==NULL) filename=CONFIG_FILE; /*try accessing a local file first if exists*/ @@ -63,7 +63,7 @@ void linphone_gtk_quit_chatroom(LinphoneChatRoom *cr) { GtkWidget *w=g_object_get_data(G_OBJECT(friendlist),"chatview"); gchar *from; GHashTable *table=g_object_get_data(G_OBJECT(w),"table"); - + g_return_if_fail(w!=NULL); gtk_notebook_remove_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),w)); linphone_chat_room_mark_as_read(cr); @@ -95,7 +95,7 @@ GtkWidget *create_tab_chat_header(LinphoneChatRoom *cr,const LinphoneAddress *ur GtkWidget *l; GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_CLOSE,GTK_ICON_SIZE_MENU); GtkWidget *b=gtk_button_new(); - + gtk_button_set_image(GTK_BUTTON(b),image); gtk_button_set_relief(GTK_BUTTON(b),GTK_RELIEF_NONE); gtk_widget_set_size_request(b,25,20); @@ -131,14 +131,15 @@ void udpate_tab_chat_header(GtkWidget *chat_view,const LinphoneAddress *uri,Linp static gboolean scroll_to_end(GtkTextView *w){ GtkTextBuffer *buffer=gtk_text_view_get_buffer(w); + GtkTextMark *mark; GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer,&iter); - GtkTextMark *mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE); - gtk_text_view_scroll_mark_onscreen(w,mark); + mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE); + gtk_text_view_scroll_mark_onscreen(w,mark); return FALSE; } -void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, +void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, gboolean me,LinphoneChatRoom *cr,LinphoneChatMessage *msg, gboolean hist){ GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview")); GtkTextBuffer *buffer=gtk_text_view_get_buffer(text); @@ -153,7 +154,7 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, struct tm *tm; int tnow_day; int tnow_year; - + gtk_text_buffer_get_start_iter(buffer,&begin); gtk_text_buffer_get_end_iter(buffer,&iter); off=gtk_text_iter_get_offset(&iter); @@ -178,7 +179,7 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, case LinphoneChatMessageStateInProgress: { g_hash_table_insert(table,(gpointer)msg,GINT_TO_POINTER(gtk_text_iter_get_line(&iter))); - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1, + gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1, "right","small","italic","font_grey","bg",NULL); g_object_set_data(G_OBJECT(w),"table",table); break; @@ -195,15 +196,15 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, } else { strftime(buf,80,"%H:%M",tm); } - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1, + gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1, "right","small","italic","font_grey",me ? "bg":NULL,NULL); break; } case LinphoneChatMessageStateNotDelivered: - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message not sent",-1, + gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message not sent",-1, "right","small","italic","font_grey",me ? "bg":NULL,NULL); break; - default : gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1, + default : gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1, "right","small","italic","font_grey",me ? "bg":NULL,NULL); } gtk_text_buffer_get_end_iter(buffer,&iter); @@ -225,7 +226,7 @@ void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessag GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); GtkWidget *page=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); GHashTable *table=(GHashTable*)g_object_get_data(G_OBJECT(page),"table"); - + if(page!=NULL){ GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(page,"textview")); GtkTextBuffer *b=gtk_text_view_get_buffer(text); @@ -272,7 +273,7 @@ void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessag gtk_text_buffer_insert_with_tags_by_name(b,&iter,result,-1, "right","small","italic","font_grey","bg",NULL); g_object_set_data(G_OBJECT(page),"table",table); - } + } } static void on_chat_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state, void *user_pointer){ @@ -330,8 +331,8 @@ void display_history_message(GtkWidget *chat_view,MSList *messages,const Linphon LinphoneChatMessage *msg=(LinphoneChatMessage *)it->data; from_str=linphone_address_as_string_uri_only(linphone_chat_message_get_from(msg)); with_str=linphone_address_as_string_uri_only(with); - linphone_gtk_push_text(chat_view,strcmp(from_str,with_str)==0? with : - linphone_chat_message_get_from(msg), + linphone_gtk_push_text(chat_view,strcmp(from_str,with_str)==0? with : + linphone_chat_message_get_from(msg), strcmp(from_str,with_str)==0? FALSE : TRUE, linphone_chat_message_get_chat_room(msg),msg,TRUE); } @@ -343,7 +344,7 @@ void display_history_message(GtkWidget *chat_view,MSList *messages,const Linphon ms_free(from_str); ms_free(with_str); linphone_gtk_free_list(messages); - } + } } void linphone_gtk_chat_add_contact(const LinphoneAddress *addr){ @@ -378,7 +379,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres GdkColor colorb; int idx; GtkWidget *button; - GtkWidget *entry; + GtkWidget *entry = linphone_gtk_get_widget(chat_view,"text_entry"); MSList *messages; GHashTable *table; char *with_str; @@ -422,7 +423,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres display_history_message(chat_view,messages,with); button = linphone_gtk_get_widget(chat_view,"send"); g_signal_connect_swapped(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_send_text,NULL); - entry = linphone_gtk_get_widget(chat_view,"text_entry"); + g_signal_connect_swapped(G_OBJECT(entry),"activate",(GCallback)linphone_gtk_send_text,NULL); g_signal_connect_swapped(G_OBJECT(entry),"changed",(GCallback)linphone_gtk_compose_text,NULL); g_signal_connect(G_OBJECT(notebook),"switch_page",(GCallback)linphone_gtk_notebook_tab_select,NULL); @@ -445,7 +446,7 @@ void linphone_gtk_load_chatroom(LinphoneChatRoom *cr,const LinphoneAddress *uri, char *uri_str=linphone_address_as_string(uri); char *uri_only=linphone_address_as_string_uri_only(uri); MSList *messages=NULL; - + if(g_strcmp0(from_str,uri_only)!=0){ GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview")); GtkTextIter start; @@ -483,7 +484,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room, gboolean send=TRUE; /*GtkNotebook *notebook= ( GtkNotebook * ) linphone_gtk_get_widget ( main_window,"viewswitch" );*/ const LinphoneAddress *from= linphone_chat_message_get_from ( msg ); - + w= ( GtkWidget* ) g_object_get_data ( G_OBJECT ( friendlist ),"chatview" ); if ( w!=NULL ) { /* Chat window opened */ @@ -496,7 +497,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room, } send=FALSE; } - } else { + } else { /* Chat window closed */ #ifdef MSG_STORAGE_ENABLED send=FALSE; @@ -530,7 +531,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room, } linphone_core_play_local(lc,linphone_gtk_get_sound_path("incoming_chat.wav")); linphone_gtk_show_friends(); - + } void linphone_gtk_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { diff --git a/gtk/conference.c b/gtk/conference.c index 08262c771..1bfee3afc 100644 --- a/gtk/conference.c +++ b/gtk/conference.c @@ -61,9 +61,9 @@ static GtkWidget *find_conferencee_from_call(LinphoneCall *call){ GtkWidget *conferencee_box=get_conferencee_box(mw); GList *elem; GtkWidget *ret=NULL; - + if (conferencee_box==NULL) return NULL; - + if (call!=NULL){ GList *l=gtk_container_get_children(GTK_CONTAINER(conferencee_box)); for(elem=l;elem!=NULL;elem=elem->next){ @@ -87,13 +87,14 @@ static GtkWidget * create_conference_panel(void){ GtkWidget *image=create_pixmap("stopcall-small.png"); GtkWidget *box; GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch"); - + GtkWidget *participant; + gtk_button_set_image(GTK_BUTTON(button_conf),image); g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL); g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame); - + box=gtk_vbox_new(FALSE,0); - GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame"); + participant=linphone_gtk_create_widget("main","callee_frame"); gtk_widget_show(participant); gtk_box_set_homogeneous(GTK_BOX(box),TRUE); init_local_participant(participant); @@ -101,7 +102,7 @@ static GtkWidget * create_conference_panel(void){ gtk_widget_show(box); g_object_set_data(G_OBJECT(mw),"conferencee_box",box); gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS); - + gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame, create_conference_label()); return conf_frame; @@ -111,19 +112,20 @@ void linphone_gtk_set_in_conference(LinphoneCall *call){ GtkWidget *mw=linphone_gtk_get_main_window(); GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch"); - + GtkWidget *participant; + if(conf_frame==NULL){ conf_frame=create_conference_panel(); } - GtkWidget *participant=find_conferencee_from_call(call); - + participant=find_conferencee_from_call(call); + if (participant==NULL){ /*create and add it */ GtkWidget *conferencee_box=get_conferencee_box(mw); GtkWidget *sound_meter; const LinphoneAddress *addr=linphone_call_get_remote_address(call); gchar *markup; - + participant=linphone_gtk_create_widget("main","callee_frame"); gtk_widget_show(participant); if (linphone_address_get_display_name(addr)!=NULL){ @@ -140,7 +142,7 @@ void linphone_gtk_set_in_conference(LinphoneCall *call){ gtk_box_pack_start(GTK_BOX(conferencee_box),participant,FALSE,FALSE,PADDING_PIXELS); g_object_set_data_full(G_OBJECT(participant),"call",linphone_call_ref(call),(GDestroyNotify)linphone_call_unref); gtk_notebook_set_current_page(GTK_NOTEBOOK(viewswitch), - gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame)); + gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame)); } } @@ -153,13 +155,13 @@ void linphone_gtk_terminate_conference_participant(LinphoneCall *call){ void linphone_gtk_unset_from_conference(LinphoneCall *call){ GtkWidget *frame=find_conferencee_from_call(call); - + if (frame){ GtkWidget *mw=linphone_gtk_get_main_window(); GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); GtkWidget *conferencee_box=g_object_get_data(G_OBJECT(mw),"conferencee_box"); GList *children; - + g_message("Removing a participant from conference"); gtk_widget_destroy(frame); children=gtk_container_get_children(GTK_CONTAINER(conferencee_box)); diff --git a/gtk/friendlist.c b/gtk/friendlist.c index f86f8b4c6..70be2484f 100644 --- a/gtk/friendlist.c +++ b/gtk/friendlist.c @@ -198,7 +198,7 @@ void linphone_gtk_delete_history(GtkWidget *button){ GtkWidget *chat_view; LinphoneFriend *lf=NULL; GtkWidget *friendlist; - + friendlist=linphone_gtk_get_widget(w,"contact_list"); chat_view=(GtkWidget *)g_object_get_data(G_OBJECT(friendlist),"chatview"); select = gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist)); @@ -216,7 +216,7 @@ void linphone_gtk_delete_history(GtkWidget *button){ GtkTextIter start; GtkTextIter end; GtkTextBuffer *text_buffer; - + text_buffer=gtk_text_view_get_buffer(text_view); gtk_text_buffer_get_bounds(text_buffer, &start, &end); gtk_text_buffer_delete (text_buffer, &start, &end); @@ -290,7 +290,7 @@ void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){ LinphoneFriend *lf=NULL; LinphoneChatRoom *cr=NULL; GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch"); - + lf=linphone_core_find_friend(linphone_gtk_get_core(),la); if(lf==NULL){ cr=linphone_gtk_create_chatroom(la); @@ -331,7 +331,7 @@ void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){ } }while(gtk_tree_model_iter_next(model,&iter)); } - } + } } void linphone_gtk_notebook_tab_select(GtkNotebook *notebook,GtkWidget *page,guint page_num, gpointer data){ @@ -595,11 +595,11 @@ static int get_friend_weight(const LinphoneFriend *lf){ int w=0; LinphoneCore *lc=linphone_gtk_get_core(); LinphoneChatRoom *cr=linphone_core_get_chat_room(lc,linphone_friend_get_address(lf)); - + if (cr && linphone_chat_room_get_unread_messages_count(cr)>0){ w+=2000; } - + switch(linphone_friend_get_status(lf)){ case LinphoneStatusOnline: w+=1000; @@ -685,7 +685,7 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist){ gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(friendlist),friend_search_func,NULL,NULL); gtk_tree_view_set_search_column(GTK_TREE_VIEW(friendlist),FRIEND_NAME); gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_NAME,friend_sort,NULL,NULL); - + /*Name and presence column*/ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Presence status"), @@ -781,8 +781,9 @@ gboolean linphone_gtk_directory_search_focus_in(GtkWidget *entry){ void linphone_gtk_directory_search_activate(GtkWidget *entry){ LinphoneProxyConfig *cfg; + GtkWidget *w; linphone_core_get_default_proxy(linphone_gtk_get_core(),&cfg); - GtkWidget *w=linphone_gtk_show_buddy_lookup_window(linphone_proxy_config_get_sip_setup_context(cfg)); + w=linphone_gtk_show_buddy_lookup_window(linphone_proxy_config_get_sip_setup_context(cfg)); if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(entry),"active"))==1) linphone_gtk_buddy_lookup_set_keyword(w,gtk_entry_get_text(GTK_ENTRY(entry))); } @@ -809,7 +810,7 @@ void linphone_gtk_show_friends(void){ if (gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))==NULL){ linphone_gtk_friend_list_init(friendlist); } - + store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))); gtk_list_store_clear(store); @@ -1076,7 +1077,7 @@ static gint tree_view_get_cell_from_pos(GtkTreeView *view, guint x, guint y){ gint colx = 0; GtkTreePath *path; GtkTreeViewDropPosition pos; - + g_return_val_if_fail ( view != NULL, 0 ); columns = gtk_tree_view_get_columns(view); @@ -1086,8 +1087,7 @@ static gint tree_view_get_cell_from_pos(GtkTreeView *view, guint x, guint y){ GtkTreeViewColumn *checkcol = (GtkTreeViewColumn*) node->data; if (x >= colx && x < (colx + checkcol->width)){ col = checkcol; - gint num = get_col_number_from_tree_view_column(col); - return num; + return get_col_number_from_tree_view_column(col); } else { colx += checkcol->width; } diff --git a/gtk/incall_view.c b/gtk/incall_view.c index a70fb468d..5329508b6 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -269,7 +269,7 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp); g_free(tmp); if (has_video){ - gchar *size_r=g_strdup_printf(_("%ix%i @ %f fps"),size_received.width,size_received.height, + gchar *size_r=g_strdup_printf(_("%ix%i @ %f fps"),size_received.width,size_received.height, linphone_call_params_get_received_framerate(curparams)); gchar *size_s=g_strdup_printf(_("%ix%i @ %f fps"),size_sent.width,size_sent.height, linphone_call_params_get_sent_framerate(curparams)); @@ -366,6 +366,11 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){ GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch"); static int call_index=1; int idx; + GtkWidget *transfer; + GtkWidget *conf; + GtkWidget *button; + GtkWidget *image; + if (ms_list_size(linphone_core_get_calls(linphone_gtk_get_core()))==1){ /*this is the only call at this time */ @@ -386,19 +391,19 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){ linphone_gtk_enable_mute_button( GTK_BUTTON(linphone_gtk_get_widget(call_view,"incall_mute")),FALSE); - GtkWidget *transfer = linphone_gtk_get_widget(call_view,"transfer_button"); + transfer = linphone_gtk_get_widget(call_view,"transfer_button"); gtk_button_set_image(GTK_BUTTON(transfer),gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,GTK_ICON_SIZE_BUTTON)); g_signal_connect(G_OBJECT(transfer),"clicked",(GCallback)transfer_button_clicked,call); gtk_widget_hide(transfer); - GtkWidget *conf = linphone_gtk_get_widget(call_view,"conference_button"); + conf = linphone_gtk_get_widget(call_view,"conference_button"); gtk_button_set_image(GTK_BUTTON(conf),gtk_image_new_from_stock (GTK_STOCK_ADD,GTK_ICON_SIZE_BUTTON)); g_signal_connect(G_OBJECT(conf),"clicked",(GCallback)conference_button_clicked,call); gtk_widget_hide(conf); - GtkWidget *button=linphone_gtk_get_widget(call_view,"terminate_call"); - GtkWidget *image=create_pixmap("stopcall-small.png"); + button=linphone_gtk_get_widget(call_view,"terminate_call"); + image=create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-small.png")); gtk_button_set_label(GTK_BUTTON(button),_("Hang up")); gtk_button_set_image(GTK_BUTTON(button),image); gtk_widget_show(image); @@ -418,6 +423,7 @@ static void video_button_clicked(GtkWidget *button, LinphoneCall *call){ void linphone_gtk_update_video_button(LinphoneCall *call){ GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call); GtkWidget *button; + GtkWidget *conf_frame; const LinphoneCallParams *params=linphone_call_get_current_params(call); gboolean has_video=linphone_call_params_video_enabled(params); if (call_view==NULL) return; @@ -434,7 +440,7 @@ void linphone_gtk_update_video_button(LinphoneCall *call){ g_signal_connect(G_OBJECT(button),"clicked",(GCallback)video_button_clicked,call); g_object_set_data(G_OBJECT(button),"signal_connected",GINT_TO_POINTER(1)); } - GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame"); + conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame"); gtk_widget_set_sensitive(button,linphone_call_get_state(call)==LinphoneCallStreamsRunning); if(conf_frame!=NULL){ gtk_widget_set_sensitive(button,FALSE); @@ -681,6 +687,14 @@ void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call){ } } +char *linphone_gtk_address(const LinphoneAddress *addr){ + const char *displayname=linphone_address_get_display_name(addr); + if (!displayname) return linphone_address_as_string_uri_only(addr); + return ms_strdup(displayname); +} + + + void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){ GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); @@ -690,6 +704,8 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){ gboolean in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"call_stats"); + linphone_gtk_in_call_show_video(call); + display_peer_name_in_label(callee,linphone_call_get_remote_address (call)); gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel")); @@ -730,7 +746,7 @@ void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){ GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel")); gtk_label_set_markup(GTK_LABEL(status),_("Paused call")); - + linphone_gtk_in_call_show_video(call); linphone_gtk_in_call_set_animation_image(callview,GTK_STOCK_MEDIA_PAUSE,TRUE); } @@ -753,11 +769,16 @@ static gboolean in_call_view_terminated(LinphoneCall *call){ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg){ GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); + GtkWidget *status; + GtkWidget *video_window; + gboolean in_conf; + guint taskid; if(callview==NULL) return; - GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); - guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid")); - gboolean in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); - + video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window"); + status=linphone_gtk_get_widget(callview,"in_call_status"); + taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid")); + in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); + if (video_window) gtk_widget_destroy(video_window); if (status==NULL) return; if (error_msg==NULL) gtk_label_set_markup(GTK_LABEL(status),_("Call ended.")); @@ -896,8 +917,9 @@ void linphone_gtk_record_call_toggled(GtkWidget *button){ GtkWidget *callview; GtkWidget *label; if (call){ + const LinphoneCallParams *params; callview=(GtkWidget*)linphone_call_get_user_pointer (call); - const LinphoneCallParams *params=linphone_call_get_current_params(call); + params=linphone_call_get_current_params(call); filepath=linphone_call_params_get_record_file(params); label=linphone_gtk_get_widget(callview,"record_status"); }else if (is_conf){ diff --git a/gtk/linphone.h b/gtk/linphone.h index 2a256cab5..70f1c58e3 100644 --- a/gtk/linphone.h +++ b/gtk/linphone.h @@ -48,6 +48,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define LINPHONE_VERSION LINPHONE_VERSION_DATE #endif +#define LINPHONE_ICON "linphone.png" + enum { COMPLETION_HISTORY, COMPLETION_LDAP @@ -195,4 +197,6 @@ void linphone_gtk_set_configuration_uri(void); GtkWidget * linphone_gtk_show_config_fetching(void); void linphone_gtk_close_config_fetching(GtkWidget *w, LinphoneConfiguringState state); const char *linphone_gtk_get_sound_path(const char *file); +void linphone_gtk_in_call_show_video(LinphoneCall *call); +char *linphone_gtk_address(const LinphoneAddress *addr);/*return human readable identifier for a LinphoneAddress */ diff --git a/gtk/main.c b/gtk/main.c index a08681dde..5dd2b046f 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -48,7 +48,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef ENABLE_NLS #include #endif -#define LINPHONE_ICON "linphone.png" + const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION; @@ -318,6 +318,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file, g_free(secrets_file); linphone_core_enable_video_capture(the_core, TRUE); linphone_core_enable_video_display(the_core, TRUE); + linphone_core_set_native_video_window_id(the_core,-1);/*don't create the window*/ if (no_video) { _linphone_gtk_enable_video(FALSE); linphone_gtk_set_ui_config_int("videoselfview",0); @@ -439,9 +440,9 @@ GtkWidget *linphone_gtk_create_widget(const char *filename, const char *widget_n return w; } -static void entry_unmapped(GtkWidget *entry){ - g_message("Entry is unmapped, calling unrealize to workaround chinese bug."); - gtk_widget_unrealize(entry); +static void entry_unmapped(GtkWidget *widget){ + ms_message("%s is unmapped, calling unrealize to workaround chinese bug.",G_OBJECT_TYPE_NAME(widget)); + gtk_widget_unrealize(widget); } GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){ @@ -458,10 +459,10 @@ GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){ g_error("No widget named %s found in xml interface.",name); } if (workaround_gtk_entry_chinese_bug){ - if (strcmp(G_OBJECT_TYPE_NAME(w),"GtkEntry")==0){ + if (strcmp(G_OBJECT_TYPE_NAME(w),"GtkEntry")==0 || strcmp(G_OBJECT_TYPE_NAME(w),"GtkTextView")==0){ if (g_object_get_data(G_OBJECT(w),"entry_bug_workaround")==NULL){ g_object_set_data(G_OBJECT(w),"entry_bug_workaround",GINT_TO_POINTER(1)); - g_message("%s is a GtkEntry",name); + ms_message("%s is a %s",name,G_OBJECT_TYPE_NAME(w)); g_signal_connect(G_OBJECT(w),"unmap",(GCallback)entry_unmapped,NULL); } } @@ -566,102 +567,6 @@ void linphone_gtk_show_about(){ gtk_widget_show(about); } -static void set_video_window_decorations(GdkWindow *w){ - const char *title=linphone_gtk_get_ui_config("title","Linphone"); - const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON); - char video_title[256]; - GdkPixbuf *pbuf=create_pixbuf(icon_path); - - if (!linphone_core_in_call(linphone_gtk_get_core())){ - snprintf(video_title,sizeof(video_title),"%s video",title); - /* When not in call, treat the video as a normal window */ - gdk_window_set_keep_above(w, FALSE); - }else{ - LinphoneAddress *uri = - linphone_address_clone(linphone_core_get_current_call_remote_address(linphone_gtk_get_core())); - char *display_name; - - linphone_address_clean(uri); - if (linphone_address_get_display_name(uri)!=NULL){ - display_name=ms_strdup(linphone_address_get_display_name(uri)); - }else{ - display_name=linphone_address_as_string(uri); - } - snprintf(video_title,sizeof(video_title),_("Call with %s"),display_name); - linphone_address_destroy(uri); - ms_free(display_name); - - /* During calls, bring up the video window, arrange so that - it is above all the other windows */ - gdk_window_deiconify(w); - gdk_window_set_keep_above(w,TRUE); - /* Maybe we should have the following, but then we want to - have a timer that turns it off after a little while. */ - /* gdk_window_set_urgency_hint(w,TRUE); */ - } - gdk_window_set_title(w,video_title); - /* Refrain the video window to be closed at all times. */ - gdk_window_set_functions(w, - GDK_FUNC_RESIZE|GDK_FUNC_MOVE| - GDK_FUNC_MINIMIZE|GDK_FUNC_MAXIMIZE); - if (pbuf){ - GList *l=NULL; - l=g_list_append(l,pbuf); - gdk_window_set_icon_list(w,l); - g_list_free(l); - g_object_unref(G_OBJECT(pbuf)); - } -} - -static gboolean video_needs_update=FALSE; - -static void update_video_title(){ - video_needs_update=TRUE; -} - -static void update_video_titles(LinphoneCore *lc){ - unsigned long id; - static unsigned long previd=0; - static unsigned long preview_previd=0; - id=linphone_core_get_native_video_window_id(lc); - if (id!=previd || video_needs_update){ - GdkWindow *w; - previd=id; - if (id!=0){ - ms_message("Updating window decorations"); -#ifndef WIN32 - w=gdk_window_foreign_new((GdkNativeWindow)id); -#else - w=gdk_window_foreign_new((HANDLE)id); -#endif - if (w) { - set_video_window_decorations(w); - g_object_unref(G_OBJECT(w)); - } - else ms_error("gdk_window_foreign_new() failed"); - if (video_needs_update) video_needs_update=FALSE; - } - } - id=linphone_core_get_native_preview_window_id (lc); - if (id!=preview_previd ){ - GdkWindow *w; - preview_previd=id; - if (id!=0){ - ms_message("Updating window decorations for preview"); -#ifndef WIN32 - w=gdk_window_foreign_new((GdkNativeWindow)id); -#else - w=gdk_window_foreign_new((HANDLE)id); -#endif - if (w) { - set_video_window_decorations(w); - g_object_unref(G_OBJECT(w)); - } - else ms_error("gdk_window_foreign_new() failed"); - if (video_needs_update) video_needs_update=FALSE; - } - } -} static gboolean linphone_gtk_iterate(LinphoneCore *lc){ static gboolean first_time=TRUE; @@ -677,7 +582,6 @@ static gboolean linphone_gtk_iterate(LinphoneCore *lc){ first_time=FALSE; } - update_video_titles(lc); if (addr_to_call!=NULL){ /*make sure we are not showing the login screen*/ GtkWidget *mw=linphone_gtk_get_main_window(); @@ -864,7 +768,7 @@ static gboolean launch_contact_provider_search(void *userdata) if( ldap && strlen(predicate) >= 3 ){ // don't search too small predicates unsigned int max_res_count = linphone_ldap_contact_provider_get_max_result(ldap); - + LinphoneContactSearch* search; if( previous_search && (strstr(predicate, previous_search) == predicate) && // last search contained results from this one (prev_res_count != max_res_count) ){ // and we didn't reach the max result limit @@ -879,7 +783,7 @@ static gboolean launch_contact_provider_search(void *userdata) gtk_object_set_data(GTK_OBJECT(uribar), "previous_search", ms_strdup(predicate)); ms_message("launch_contact_provider_search"); - LinphoneContactSearch* search =linphone_contact_provider_begin_search( + search =linphone_contact_provider_begin_search( linphone_contact_provider_cast(ldap_provider), predicate, on_contact_provider_search_results, uribar ); @@ -928,7 +832,6 @@ void linphone_gtk_call_terminated(LinphoneCall *call, const char *error){ } if (linphone_gtk_use_in_call_view() && call) linphone_gtk_in_call_view_terminate(call,error); - update_video_title(); } static void linphone_gtk_update_call_buttons(LinphoneCall *call){ @@ -940,6 +843,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){ //bool_t stop_active=FALSE; bool_t add_call=FALSE; int call_list_size=ms_list_size(calls); + GtkWidget *conf_frame; if (calls==NULL){ start_active=TRUE; @@ -962,7 +866,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){ gtk_widget_set_visible(button,add_call); //gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),stop_active); - GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); + conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); if(conf_frame==NULL){ linphone_gtk_enable_transfer_button(lc,call_list_size>1); linphone_gtk_enable_conference_button(lc,call_list_size>1); @@ -970,7 +874,6 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){ linphone_gtk_enable_transfer_button(lc,FALSE); linphone_gtk_enable_conference_button(lc,FALSE); } - update_video_title(); if (call) { linphone_gtk_update_video_button(call); } @@ -1000,7 +903,7 @@ gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_ break; } } - + if (address){ id=linphone_address_get_username(address); if (id==NULL) id=linphone_address_get_domain(address); @@ -1172,13 +1075,14 @@ static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint respon static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url){ GtkWidget *dialog; + gchar *message; if (linphone_gtk_get_ui_config_int("subscribe_deny_all",0)){ linphone_core_reject_subscriber(linphone_gtk_get_core(),lf); return; } - gchar *message=g_strdup_printf(_("%s would like to add you to his contact list.\nWould you allow him to see your presence status or add him to your contact list ?\nIf you answer no, this person will be temporarily blacklisted."),url); + message=g_strdup_printf(_("%s would like to add you to his contact list.\nWould you allow him to see your presence status or add him to your contact list ?\nIf you answer no, this person will be temporarily blacklisted."),url); dialog = gtk_message_dialog_new ( GTK_WINDOW(linphone_gtk_get_main_window()), GTK_DIALOG_DESTROY_WITH_PARENT, @@ -1540,7 +1444,7 @@ static void update_registration_status(LinphoneProxyConfig *cfg, LinphoneRegistr }while(gtk_tree_model_iter_next(model,&iter)); } if (!found) { - g_warning("Could not find proxy config in combo box of identities."); + /*ignored, this is a notification for a removed proxy config.*/ return; } switch (rs){ @@ -2001,10 +1905,11 @@ void linphone_gtk_keypad_key_released(GtkWidget *w, GdkEvent *event, gpointer us void linphone_gtk_create_keypad(GtkWidget *button){ GtkWidget *mw=linphone_gtk_get_main_window(); GtkWidget *k=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"keypad"); + GtkWidget *keypad; if(k!=NULL){ gtk_widget_destroy(k); } - GtkWidget *keypad=linphone_gtk_create_window("keypad"); + keypad=linphone_gtk_create_window("keypad"); linphone_gtk_connect_digits(keypad); linphone_gtk_init_dtmf_table(keypad); g_object_set_data(G_OBJECT(mw),"keypad",(gpointer)keypad); diff --git a/gtk/propertybox.c b/gtk/propertybox.c index 7ed960c46..677fe5f06 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -179,6 +179,7 @@ void linphone_gtk_ldap_save(GtkWidget *button) GtkEntry* entry; GtkToggleButton* toggle; GtkSpinButton* spin; + GtkComboBox* cbox; ms_message("SAVE LDAP"); @@ -204,7 +205,7 @@ void linphone_gtk_ldap_save(GtkWidget *button) linphone_dictionary_set_string(dict, "sasl_realm", gtk_entry_get_text(entry)); - GtkComboBox* cbox = GTK_COMBO_BOX(linphone_gtk_get_widget(ldap_widget,"ldap_auth_method")); + cbox = GTK_COMBO_BOX(linphone_gtk_get_widget(ldap_widget,"ldap_auth_method")); linphone_dictionary_set_string(dict, "auth_method", gtk_combo_box_get_active_text(cbox)); entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_base_object")); @@ -245,10 +246,11 @@ void linphone_gtk_ldap_save(GtkWidget *button) } void linphone_gtk_fill_video_sizes(GtkWidget *combo){ - const MSVideoSizeDef *def=linphone_core_get_supported_video_sizes(linphone_gtk_get_core());; - int i,active=0; + int i; + int active=0; char vsize_def[256]; MSVideoSize cur=linphone_core_get_preferred_video_size(linphone_gtk_get_core()); + const MSVideoSizeDef *def=linphone_core_get_supported_video_sizes(linphone_gtk_get_core());; /* glade creates a combo box without list model and text renderer, unless we fill it with a dummy text. This dummy text needs to be removed first*/ @@ -828,8 +830,11 @@ void linphone_gtk_show_sip_accounts(GtkWidget *w){ static void linphone_gtk_proxy_closed(GtkWidget *w){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)g_object_get_data(G_OBJECT(w),"config"); + gboolean was_editing=! GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_new")); if (cfg){ - linphone_proxy_config_done(cfg); + if (was_editing){ + linphone_proxy_config_done(cfg); + }else linphone_proxy_config_destroy(cfg); } } @@ -907,7 +912,15 @@ void linphone_gtk_proxy_address_changed(GtkEditable *editable){ void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){ GtkWidget *w=linphone_gtk_create_window("sip_account"); const char *tmp; - if (cfg){ + gboolean is_new=FALSE; + + if (!cfg) { + cfg=linphone_core_create_proxy_config(linphone_gtk_get_core()); + is_new=TRUE; + g_object_set_data(G_OBJECT(w),"is_new",GINT_TO_POINTER(TRUE)); + } + + if (!is_new){ linphone_proxy_config_edit(cfg); gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"identity")), linphone_proxy_config_get_identity(cfg)); @@ -916,17 +929,19 @@ void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){ if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"route")),tmp); tmp=linphone_proxy_config_get_contact_parameters(cfg); if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"params")),tmp); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"regperiod")), - linphone_proxy_config_get_expires(cfg)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"register")), - linphone_proxy_config_register_enabled(cfg)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"publish")), - linphone_proxy_config_publish_enabled(cfg)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"avpf")), - linphone_proxy_config_avpf_enabled(cfg)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"avpf_rr_interval")), - linphone_proxy_config_get_avpf_rr_interval(cfg)); } + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"regperiod")), + linphone_proxy_config_get_expires(cfg)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"register")), + linphone_proxy_config_register_enabled(cfg)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"publish")), + linphone_proxy_config_publish_enabled(cfg)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"avpf")), + linphone_proxy_config_avpf_enabled(cfg)); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"avpf_rr_interval")), + linphone_proxy_config_get_avpf_rr_interval(cfg)); + g_object_set_data(G_OBJECT(w),"config",(gpointer)cfg); g_object_set_data(G_OBJECT(w),"parameters",(gpointer)pb); g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_proxy_closed,w); @@ -944,12 +959,8 @@ void linphone_gtk_proxy_ok(GtkButton *button){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)g_object_get_data(G_OBJECT(w),"config"); int index=gtk_combo_box_get_active(GTK_COMBO_BOX(linphone_gtk_get_widget(w,"transport"))); LinphoneTransportType tport=(LinphoneTransportType)index; - gboolean was_editing=TRUE; + gboolean was_editing=! GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_new")); - if (!cfg){ - was_editing=FALSE; - cfg=linphone_proxy_config_new(); - } linphone_proxy_config_set_identity(cfg, gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"identity")))); if (linphone_proxy_config_set_server_addr(cfg, @@ -1098,14 +1109,14 @@ static void linphone_gtk_fill_langs(GtkWidget *pb){ const char *all_langs="C " LINPHONE_ALL_LANGS; const char *name; int i=0,index=0; + int cur_lang_index=-1; + char text[256]={0}; const char *cur_lang; #if defined(WIN32) || defined(__APPLE__) cur_lang=getenv("LANG"); #else cur_lang=getenv("LANGUAGE"); #endif - int cur_lang_index=-1; - char text[256]={0}; if (cur_lang==NULL) cur_lang="C"; /* glade creates a combo box without list model and text renderer, unless we fill it with a dummy text. @@ -1581,7 +1592,7 @@ void linphone_gtk_edit_tunnel(GtkButton *button){ if (port==0) port=443; gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port); - if (linphone_tunnel_enabled(tunnel)){ + if (linphone_tunnel_get_mode(tunnel)){ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")),1); } else{ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_disable")),1); @@ -1625,7 +1636,7 @@ void linphone_gtk_tunnel_ok(GtkButton *button){ linphone_tunnel_config_set_host(config, host); linphone_tunnel_config_set_port(config, port); linphone_tunnel_add_server(tunnel, config); - linphone_tunnel_enable(tunnel,enabled); + linphone_tunnel_set_mode(tunnel, (enabled ? LinphoneTunnelModeEnable : LinphoneTunnelModeDisable)); linphone_tunnel_set_http_proxy(tunnel,http_host,http_port,username,password); gtk_widget_destroy(w); diff --git a/gtk/setupwizard.c b/gtk/setupwizard.c index 27f7363b7..491014625 100644 --- a/gtk/setupwizard.c +++ b/gtk/setupwizard.c @@ -44,7 +44,7 @@ static GtkWidget *create_setup_signin_choice(){ GtkWidget *t2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I have already a linphone.org account and I just want to use it")); GtkWidget *t3=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I have already a sip account and I just want to use it")); GtkWidget *t4=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I want to specify a remote configuration URI")); - + gtk_box_pack_start (GTK_BOX (vbox), t1, TRUE, TRUE, 2); gtk_box_pack_start (GTK_BOX (vbox), t2, TRUE, TRUE, 2); gtk_box_pack_start (GTK_BOX (vbox), t3, TRUE, TRUE, 2); @@ -89,14 +89,20 @@ static GtkWidget *create_linphone_account_informations_page() { GtkWidget *label=gtk_label_new(_("Enter your linphone.org username")); GdkColor color; + GtkWidget *labelEmpty; + GtkWidget *labelUsername; + GtkWidget *entryUsername; + GtkWidget *labelPassword; + GtkWidget *entryPassword; + gdk_color_parse ("red", &color); - GtkWidget *labelEmpty=gtk_label_new(NULL); + labelEmpty=gtk_label_new(NULL); gtk_widget_modify_fg(labelEmpty, GTK_STATE_NORMAL, &color); - GtkWidget *labelUsername=gtk_label_new(_("Username:")); - GtkWidget *entryUsername=gtk_entry_new(); - GtkWidget *labelPassword=gtk_label_new(_("Password:")); - GtkWidget *entryPassword=gtk_entry_new(); + labelUsername=gtk_label_new(_("Username:")); + entryUsername=gtk_entry_new(); + labelPassword=gtk_label_new(_("Password:")); + entryPassword=gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); gtk_table_attach_defaults(GTK_TABLE(vbox), label, 0, 2, 0, 1); @@ -118,19 +124,28 @@ static GtkWidget *create_account_informations_page() { GtkWidget *label=gtk_label_new(_("Enter your account informations")); GdkColor color; + GtkWidget *labelEmpty; + GtkWidget *labelUsername; + GtkWidget *labelPassword; + GtkWidget *entryPassword; + GtkWidget *labelDomain; + GtkWidget *labelProxy; + GtkWidget *entryUsername; + GtkWidget *entryDomain; + GtkWidget *entryRoute; gdk_color_parse ("red", &color); - GtkWidget *labelEmpty=gtk_label_new(NULL); + labelEmpty=gtk_label_new(NULL); gtk_widget_modify_fg(labelEmpty, GTK_STATE_NORMAL, &color); - GtkWidget *labelUsername=gtk_label_new(_("Username*")); - GtkWidget *labelPassword=gtk_label_new(_("Password*")); - GtkWidget *entryPassword=gtk_entry_new(); + labelUsername=gtk_label_new(_("Username*")); + labelPassword=gtk_label_new(_("Password*")); + entryPassword=gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); - GtkWidget *labelDomain=gtk_label_new(_("Domain*")); - GtkWidget *labelProxy=gtk_label_new(_("Proxy")); - GtkWidget *entryUsername=gtk_entry_new(); - GtkWidget *entryDomain=gtk_entry_new(); - GtkWidget *entryRoute=gtk_entry_new(); + labelDomain=gtk_label_new(_("Domain*")); + labelProxy=gtk_label_new(_("Proxy")); + entryUsername=gtk_entry_new(); + entryDomain=gtk_entry_new(); + entryRoute=gtk_entry_new(); gtk_table_attach_defaults(GTK_TABLE(vbox), label, 0, 2, 0, 1); gtk_table_attach_defaults(GTK_TABLE(vbox), labelUsername, 0, 1, 1, 2); @@ -309,19 +324,25 @@ static GtkWidget *create_account_information_page() { GtkWidget *labelPassword2=gtk_label_new(_("Confirm your password: (*)")); GtkWidget *entryUsername=gtk_entry_new(); GtkWidget *entryPassword=gtk_entry_new(); + GtkWidget *entryEmail; + GtkWidget *entryPassword2; + GtkWidget *checkNewsletter; + GtkWidget *labelError; + GtkWidget *passwordVbox1; + GtkWidget *passwordVbox2; + GdkColor color; gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); - GtkWidget *entryEmail=gtk_entry_new(); - GtkWidget *entryPassword2=gtk_entry_new(); + entryEmail=gtk_entry_new(); + entryPassword2=gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(entryPassword2), FALSE); - GtkWidget *checkNewsletter=gtk_check_button_new_with_label("Keep me informed with linphone updates"); + checkNewsletter=gtk_check_button_new_with_label(_("Keep me informed with linphone updates")); - GdkColor color; gdk_color_parse ("red", &color); - GtkWidget *labelError=gtk_label_new(NULL); + labelError=gtk_label_new(NULL); gtk_widget_modify_fg(labelError, GTK_STATE_NORMAL, &color); - GtkWidget *passwordVbox1=gtk_vbox_new(FALSE,2); - GtkWidget *passwordVbox2=gtk_vbox_new(FALSE,2); + passwordVbox1=gtk_vbox_new(FALSE,2); + passwordVbox2=gtk_vbox_new(FALSE,2); gtk_box_pack_start (GTK_BOX (passwordVbox1), labelPassword, TRUE, FALSE, 2); gtk_box_pack_start (GTK_BOX (passwordVbox1), labelPassword2, TRUE, FALSE, 2); gtk_box_pack_start (GTK_BOX (passwordVbox2), entryPassword, TRUE, FALSE, 2); @@ -414,6 +435,8 @@ static void linphone_gtk_assistant_prepare(GtkWidget *assistant, GtkWidget *page if (pagenum == 5) { gtk_assistant_commit(GTK_ASSISTANT(assistant)); } else if (pagenum == gtk_assistant_get_n_pages(GTK_ASSISTANT(assistant)) - 1) { + LinphoneAddress *identity; + LinphoneAuthInfo *info; // Saving the account and making it default LinphoneAccountCreator *creator=linphone_gtk_assistant_get_creator(assistant); LinphoneProxyConfig *cfg=linphone_proxy_config_new(); @@ -424,30 +447,33 @@ static void linphone_gtk_assistant_prepare(GtkWidget *assistant, GtkWidget *page linphone_proxy_config_enable_publish(cfg, FALSE); linphone_proxy_config_enable_register(cfg, TRUE); - LinphoneAddress *identity = linphone_address_new(creator->username); - LinphoneAuthInfo *info=linphone_auth_info_new(linphone_address_get_username(identity), NULL, creator->password, NULL, NULL, linphone_address_get_domain(identity)); + identity = linphone_address_new(creator->username); + info=linphone_auth_info_new(linphone_address_get_username(identity), NULL, creator->password, NULL, NULL, linphone_address_get_domain(identity)); linphone_core_add_auth_info(linphone_gtk_get_core(),info); linphone_address_destroy(identity); - - // If account created on sip.linphone.org, we configure linphone to use TLS by default - if (strcmp(creator->domain, "sip:sip.linphone.org") == 0 && linphone_core_sip_transport_supported(linphone_gtk_get_core(),LinphoneTransportTls)) { - LinphoneAddress *addr=linphone_address_new(creator->domain); - char *tmp; - linphone_address_set_transport(addr, LinphoneTransportTls); - tmp=linphone_address_as_string(addr); - linphone_proxy_config_set_server_addr(cfg,tmp); - linphone_proxy_config_set_route(cfg,tmp); - ms_free(tmp); - linphone_address_destroy(addr); + + if (strcmp(creator->domain, "sip:sip.linphone.org") == 0 ){ + linphone_proxy_config_enable_avpf(cfg,TRUE); + // If account created on sip.linphone.org, we configure linphone to use TLS by default + if (linphone_core_sip_transport_supported(linphone_gtk_get_core(),LinphoneTransportTls)) { + LinphoneAddress *addr=linphone_address_new(creator->domain); + char *tmp; + linphone_address_set_transport(addr, LinphoneTransportTls); + tmp=linphone_address_as_string(addr); + linphone_proxy_config_set_server_addr(cfg,tmp); + linphone_proxy_config_set_route(cfg,tmp); + ms_free(tmp); + linphone_address_destroy(addr); + } } - + if (linphone_core_add_proxy_config(linphone_gtk_get_core(),cfg)==-1) return; linphone_core_set_default_proxy(linphone_gtk_get_core(),cfg); linphone_gtk_load_identities(); - + } } @@ -486,9 +512,9 @@ static int linphone_gtk_assistant_forward(int curpage, gpointer data){ else if (curpage == 2) { // Account's informations entered LinphoneAccountCreator *c=linphone_gtk_assistant_get_creator(w); gchar identity[128]; + gchar proxy[128]; g_snprintf(identity, sizeof(identity), "sip:%s@%s", gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"username"))), gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"domain")))); - gchar proxy[128]; g_snprintf(proxy, sizeof(proxy), "sip:%s", gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"domain")))); linphone_account_creator_set_username(c, identity); @@ -557,25 +583,35 @@ void linphone_gtk_close_assistant(void){ } void linphone_gtk_show_assistant(void){ + GtkWidget *w; + GtkWidget *p1; + GtkWidget *p2; + GtkWidget *p31; + GtkWidget *p32; + GtkWidget *p33; + //GtkWidget *confirm; + GtkWidget *validate; + GtkWidget *error; + GtkWidget *end; if(the_assistant!=NULL) return; - GtkWidget *w=the_assistant=gtk_assistant_new(); + w=the_assistant=gtk_assistant_new(); gtk_window_set_resizable (GTK_WINDOW(w), FALSE); gtk_window_set_title(GTK_WINDOW(w),_("SIP account configuration assistant")); ok = create_pixbuf(linphone_gtk_get_ui_config("ok","ok.png")); notok = create_pixbuf(linphone_gtk_get_ui_config("notok","notok.png")); - GtkWidget *p1=create_intro(); - GtkWidget *p2=create_setup_signin_choice(); - GtkWidget *p31=create_account_informations_page(); - GtkWidget *p32=create_linphone_account_informations_page(); - GtkWidget *p33=create_account_information_page(); - //GtkWidget *confirm=create_confirmation_page(); - GtkWidget *validate=wait_for_activation(); - GtkWidget *error=create_error_page(); - GtkWidget *end=create_finish_page(); - + p1=create_intro(); + p2=create_setup_signin_choice(); + p31=create_account_informations_page(); + p32=create_linphone_account_informations_page(); + p33=create_account_information_page(); + //confirm=create_confirmation_page(); + validate=wait_for_activation(); + error=create_error_page(); + end=create_finish_page(); + linphone_gtk_assistant_init(w); gtk_assistant_append_page(GTK_ASSISTANT(w),p1); gtk_assistant_set_page_type(GTK_ASSISTANT(w),p1,GTK_ASSISTANT_PAGE_INTRO); diff --git a/gtk/singleinstance.c b/gtk/singleinstance.c index e78f6ac6a..591d5d7cd 100644 --- a/gtk/singleinstance.c +++ b/gtk/singleinstance.c @@ -58,7 +58,7 @@ static gboolean execute_wakeup(char *buf){ static void * server_pipe_thread(void *pointer){ ortp_pipe_t child; - + do{ child=ortp_server_pipe_accept_client(server_pipe); if (server_pipe_running && child!=(ortp_pipe_t)-1){ @@ -87,8 +87,9 @@ static void linphone_gtk_init_pipe(const char *name){ } bool_t linphone_gtk_init_instance(const char *app_name, int option, const char *addr_to_call){ + ortp_pipe_t p; pipe_name=make_name(app_name); - ortp_pipe_t p=ortp_client_pipe_connect(pipe_name); + p=ortp_client_pipe_connect(pipe_name); if (p!=(ortp_pipe_t)-1){ uint8_t buf[256]={0}; g_message("There is already a running instance."); diff --git a/gtk/support.c b/gtk/support.c index 81754bb45..615ac6562 100644 --- a/gtk/support.c +++ b/gtk/support.c @@ -92,17 +92,17 @@ create_pixbuf_animation(const gchar *filename) gchar *pathname = NULL; GdkPixbufAnimation *pixbuf; GError *error = NULL; - + if (!filename || !filename[0]) return NULL; - + pathname = find_pixmap_file (filename); - + if (!pathname){ g_warning (_("Couldn't find pixmap file: %s"), filename); return NULL; } - + pixbuf = gdk_pixbuf_animation_new_from_file (pathname, &error); if (!pixbuf){ fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", @@ -156,6 +156,11 @@ const char *linphone_gtk_get_lang(const char *config_file){ void linphone_gtk_set_lang(const char *code){ LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core()); const char *curlang; + + #ifdef WIN32 + char tmp[128]; + #endif + #if defined(WIN32) || defined(__APPLE__) curlang=getenv("LANG"); #else @@ -167,12 +172,11 @@ void linphone_gtk_set_lang(const char *code){ } lp_config_set_string(cfg,"GtkUi","lang",code); #ifdef WIN32 - char tmp[128]; snprintf(tmp,sizeof(tmp),"LANG=%s",code); _putenv(tmp); #elif __APPLE__ setenv("LANG",code,1); -#else +#else setenv("LANGUAGE",code,1); #endif } diff --git a/gtk/videowindow.c b/gtk/videowindow.c new file mode 100644 index 000000000..24dc584f7 --- /dev/null +++ b/gtk/videowindow.c @@ -0,0 +1,310 @@ +/* +linphone, gtk interface. +Copyright (C) 2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "linphone.h" + +#ifdef GDK_WINDOWING_X11 +#include +#elif defined(WIN32) +#include +#elif defined(__APPLE__) +extern void *gdk_quartz_window_get_nswindow(GdkWindow *window); +extern void *gdk_quartz_window_get_nsview(GdkWindow *window); +#endif + +#include + +enum { + TARGET_STRING, + TARGET_TEXT, + TARGET_URILIST +}; + +static GtkTargetEntry targets[] = { + { "text/uri-list", GTK_TARGET_OTHER_APP, TARGET_URILIST }, +}; + +static void set_video_controls_position(GtkWidget *video_window); + +static void on_end_of_play(LinphonePlayer *player, void *user_data){ + linphone_player_close(player); +} + +static void drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, + GtkSelectionData *selection_data, guint target_type, guint time, gpointer user_data){ + int datalen=gtk_selection_data_get_length(selection_data) >= 0; + const void *data=gtk_selection_data_get_data(selection_data); + LinphoneCall *call=g_object_get_data(G_OBJECT(widget),"call"); + + ms_message("target_type=%i, datalen=%i, data=%p",target_type,datalen,data); + if (target_type==TARGET_URILIST && data){ + LinphonePlayer *player=linphone_call_get_player(call); + const char *path=(const char*)data; + if (player){ + if (strstr(path,"file://")==path) path+=strlen("file://"); + if (linphone_player_open(player,path,on_end_of_play,NULL)==0){ + linphone_player_start(player); + }else{ + GtkWidget *warn=gtk_message_dialog_new(GTK_WINDOW(widget),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, + _("Cannot play %s."),path); + g_signal_connect(warn,"response",(GCallback)gtk_widget_destroy,NULL); + gtk_widget_show(warn); + } + } + + } + gtk_drag_finish (context, TRUE, FALSE, time); +} + +static gboolean drag_drop(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data){ +#if GTK_CHECK_VERSION(2,20,0) + GList *l=gdk_drag_context_list_targets(drag_context); + GList *elem; + + if (l){ + ms_message("drag_drop"); + /* Choose the best target type */ + for(elem=l;elem!=NULL;elem=g_list_next(elem)){ + char *name=gdk_atom_name(GDK_POINTER_TO_ATOM(elem->data)); + ms_message("target: %s",name); + g_free(name); + } + }else{ + ms_warning("drag_drop no targets"); + return FALSE; + } +#endif + return TRUE; +} + +unsigned long get_native_handle(GdkWindow *gdkw){ +#ifdef GDK_WINDOWING_X11 + return (unsigned long)GDK_WINDOW_XID(gdkw); +#elif defined(WIN32) + return (unsigned long)GDK_WINDOW_HWND(gdkw); +#elif defined(__APPLE__) + return (unsigned long)gdk_quartz_window_get_nsview(gdkw); +#endif + g_warning("No way to get the native handle from gdk window"); + return 0; +} + +static gint resize_video_window(LinphoneCall *call){ + const LinphoneCallParams *params=linphone_call_get_current_params(call); + if (params){ + MSVideoSize vsize=linphone_call_params_get_received_video_size(params); + if (vsize.width>0 && vsize.height>0){ + GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); + GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window"); + if (video_window){ + MSVideoSize cur; + gtk_window_get_size(GTK_WINDOW(video_window),&cur.width,&cur.height); + if (vsize.width*vsize.height > cur.width*cur.height || + ms_video_size_get_orientation(vsize)!=ms_video_size_get_orientation(cur) ){ + g_message("Resized to %ix%i",vsize.width,vsize.height); + gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height); + } + } + } + } + return TRUE; +} + +static void on_video_window_destroy(GtkWidget *w, guint timeout){ + g_source_remove(timeout); + linphone_core_set_native_video_window_id(linphone_gtk_get_core(),(unsigned long)-1); +} + +static void video_window_set_fullscreen(GtkWidget *w, gboolean val){ + if (val){ + g_object_set_data(G_OBJECT(w),"fullscreen",GINT_TO_POINTER(1)); + gtk_window_fullscreen(GTK_WINDOW(w)); + }else{ + g_object_set_data(G_OBJECT(w),"fullscreen",GINT_TO_POINTER(0)); + gtk_window_unfullscreen(GTK_WINDOW(w)); + } +} +/*old names in old version of gdk*/ +#ifndef GDK_KEY_Escape +#define GDK_KEY_Escape GDK_Escape +#define GDK_KEY_F GDK_F +#define GDK_KEY_f GDK_f +#endif + +static void on_video_window_key_press(GtkWidget *w, GdkEvent *ev, gpointer up){ + g_message("Key press event"); + switch(ev->key.keyval){ + case GDK_KEY_f: + case GDK_KEY_F: + video_window_set_fullscreen(w,TRUE); + break; + case GDK_KEY_Escape: + video_window_set_fullscreen(w,FALSE); + break; + } +} + +static void on_controls_response(GtkWidget *dialog, int response_id, GtkWidget *video_window){ + + gtk_widget_destroy(dialog); + switch(response_id){ + case GTK_RESPONSE_YES: + video_window_set_fullscreen(video_window,TRUE); + break; + case GTK_RESPONSE_NO: + video_window_set_fullscreen(video_window,FALSE); + break; + case GTK_RESPONSE_REJECT: + { + LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(video_window),"call"); + linphone_core_terminate_call(linphone_gtk_get_core(),call); + } + break; + } + +} + +static void on_controls_destroy(GtkWidget *w){ + GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(w),"video_window"); + gint timeout=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"timeout")); + if (timeout!=0){ + g_source_remove(timeout); + g_object_set_data(G_OBJECT(w),"timeout",GINT_TO_POINTER(0)); + } + g_object_set_data(G_OBJECT(video_window),"controls",NULL); +} + +static gboolean _set_video_controls_position(GtkWidget *video_window){ + GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(video_window),"controls"); + if (w){ + gint vw,vh; + gint cw,ch; + gint x,y; + gtk_window_get_size(GTK_WINDOW(video_window),&vw,&vh); + gtk_window_get_position(GTK_WINDOW(video_window),&x,&y); + gtk_window_get_size(GTK_WINDOW(w),&cw,&ch); + gtk_window_move(GTK_WINDOW(w),x+vw/2 - cw/2, y + vh - ch); + } + return FALSE; +} + +static void set_video_controls_position(GtkWidget *video_window){ + /*do it a first time*/ + _set_video_controls_position(video_window); + /*and schedule to do it a second time in order to workaround a bug in fullscreen mode, where poistion is not taken into account the first time*/ + g_timeout_add(0,(GSourceFunc)_set_video_controls_position,video_window); +} + +static gboolean video_window_moved(GtkWidget *widget, GdkEvent *event, gpointer user_data){ + set_video_controls_position(widget); + return FALSE; +} + +static GtkWidget *show_video_controls(GtkWidget *video_window){ + GtkWidget *w; + w=(GtkWidget*)g_object_get_data(G_OBJECT(video_window),"controls"); + if (!w){ + gboolean isfullscreen=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(video_window),"fullscreen")); + const char *stock_button=isfullscreen ? GTK_STOCK_LEAVE_FULLSCREEN : GTK_STOCK_FULLSCREEN; + gint response_id=isfullscreen ? GTK_RESPONSE_NO : GTK_RESPONSE_YES ; + gint timeout; + GtkWidget *button; + w=gtk_dialog_new_with_buttons("",GTK_WINDOW(video_window),GTK_DIALOG_DESTROY_WITH_PARENT,stock_button,response_id,NULL); + gtk_window_set_opacity(GTK_WINDOW(w),0.5); + gtk_window_set_decorated(GTK_WINDOW(w),FALSE); + button=gtk_button_new_with_label(_("Hang up")); + gtk_button_set_image(GTK_BUTTON(button),create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-small.png"))); + gtk_widget_show(button); + gtk_dialog_add_action_widget(GTK_DIALOG(w),button,GTK_RESPONSE_REJECT); + g_signal_connect(w,"response",(GCallback)on_controls_response,video_window); + timeout=g_timeout_add(3000,(GSourceFunc)gtk_widget_destroy,w); + g_object_set_data(G_OBJECT(w),"timeout",GINT_TO_POINTER(timeout)); + g_signal_connect(w,"destroy",(GCallback)on_controls_destroy,NULL); + g_object_set_data(G_OBJECT(w),"video_window",video_window); + g_object_set_data(G_OBJECT(video_window),"controls",w); + set_video_controls_position(video_window); + gtk_widget_show(w); + }else{ + gint timeout=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"timeout")); + g_source_remove(timeout); + timeout=g_timeout_add(3000,(GSourceFunc)gtk_widget_destroy,w); + g_object_set_data(G_OBJECT(w),"timeout",GINT_TO_POINTER(timeout)); + } + return w; +} + +static GtkWidget *create_video_window(LinphoneCall *call){ + char *remote,*title; + GtkWidget *video_window; + const LinphoneAddress *addr; + const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON); + GdkPixbuf *pbuf=create_pixbuf(icon_path); + guint timeout; + MSVideoSize vsize=MS_VIDEO_SIZE_CIF; + GdkColor color; + + addr=linphone_call_get_remote_address(call); + remote=linphone_gtk_address(addr); + video_window=gtk_window_new(GTK_WINDOW_TOPLEVEL); + title=g_strdup_printf("%s - Video call with %s",linphone_gtk_get_ui_config("title","Linphone"),remote); + ms_free(remote); + gtk_window_set_title(GTK_WINDOW(video_window),title); + g_free(title); + if (pbuf){ + gtk_window_set_icon(GTK_WINDOW(video_window),pbuf); + } + gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height); + gdk_color_parse("black",&color); + gtk_widget_modify_bg(video_window,GTK_STATE_NORMAL,&color); + + gtk_drag_dest_set(video_window, GTK_DEST_DEFAULT_ALL, targets, sizeof(targets)/sizeof(GtkTargetEntry), GDK_ACTION_COPY); + gtk_widget_show(video_window); + gdk_window_set_events(gtk_widget_get_window(video_window), + gdk_window_get_events(gtk_widget_get_window(video_window)) | GDK_POINTER_MOTION_MASK); + timeout=g_timeout_add(500,(GSourceFunc)resize_video_window,call); + g_signal_connect(video_window,"destroy",(GCallback)on_video_window_destroy,GINT_TO_POINTER(timeout)); + g_signal_connect(video_window,"key-press-event",(GCallback)on_video_window_key_press,NULL); + g_signal_connect_swapped(video_window,"motion-notify-event",(GCallback)show_video_controls,video_window); + g_signal_connect(video_window,"configure-event",(GCallback)video_window_moved,NULL); + g_signal_connect(video_window, "drag-data-received",(GCallback)drag_data_received, NULL); + g_signal_connect(video_window, "drag-drop",(GCallback)drag_drop, NULL); + g_object_set_data(G_OBJECT(video_window),"call",call); + return video_window; +} + +void linphone_gtk_in_call_show_video(LinphoneCall *call){ + GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); + GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window"); + const LinphoneCallParams *params=linphone_call_get_current_params(call); + LinphoneCore *lc=linphone_gtk_get_core(); + + if (linphone_call_get_state(call)!=LinphoneCallPaused && params && linphone_call_params_video_enabled(params)){ + if (video_window==NULL){ + video_window=create_video_window(call); + g_object_set_data(G_OBJECT(callview),"video_window",video_window); + } + linphone_core_set_native_video_window_id(lc,get_native_handle(gtk_widget_get_window(video_window))); + }else{ + if (video_window){ + gtk_widget_destroy(video_window); + g_object_set_data(G_OBJECT(callview),"video_window",NULL); + } + } +} diff --git a/include/sal/sal.h b/include/sal/sal.h index ffca87c5f..8f81f320d 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -68,11 +68,15 @@ typedef enum { SalTransportDTLS /*DTLS*/ }SalTransport; -#define SAL_MEDIA_DESCRIPTION_UNCHANGED 0x00 -#define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED 0x01 -#define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED 0x02 -#define SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED 0x04 -#define SAL_MEDIA_DESCRIPTION_CHANGED (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED | SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) +#define SAL_MEDIA_DESCRIPTION_UNCHANGED 0x00 +#define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED (1) +#define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED (1<<1) +#define SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED (1<<2) +#define SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED (1<<3) +#define SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED (1<<4) + +#define SAL_MEDIA_DESCRIPTION_CHANGED (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED |\ + SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED |SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED | SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED) const char* sal_transport_to_string(SalTransport transport); SalTransport sal_transport_parse(const char*); @@ -413,7 +417,7 @@ typedef void (*SalOnCallReceived)(SalOp *op); typedef void (*SalOnCallRinging)(SalOp *op); typedef void (*SalOnCallAccepted)(SalOp *op); typedef void (*SalOnCallAck)(SalOp *op); -typedef void (*SalOnCallUpdating)(SalOp *op);/*< Called when a reINVITE/UPDATE is received*/ +typedef void (*SalOnCallUpdating)(SalOp *op, bool_t is_update);/*< Called when a reINVITE/UPDATE is received*/ typedef void (*SalOnCallTerminated)(SalOp *op, const char *from); typedef void (*SalOnCallFailure)(SalOp *op); typedef void (*SalOnCallReleased)(SalOp *salop); @@ -517,6 +521,10 @@ int sal_get_listening_port(Sal *ctx, SalTransport tr); int sal_unlisten_ports(Sal *ctx); int sal_transport_available(Sal *ctx, SalTransport t); void sal_set_dscp(Sal *ctx, int dscp); +void sal_set_supported_tags(Sal *ctx, const char* tags); +void sal_add_supported_tag(Sal *ctx, const char* tag); +void sal_remove_supported_tag(Sal *ctx, const char* tag); +const char *sal_get_supported_tags(Sal *ctx); int sal_reset_transports(Sal *ctx); ortp_socket_t sal_get_socket(Sal *ctx); void sal_set_user_agent(Sal *ctx, const char *user_agent); @@ -615,7 +623,7 @@ int sal_call_notify_ringing(SalOp *h, bool_t early_media); /*accept an incoming call or, during a call accept a reINVITE*/ int sal_call_accept(SalOp*h); int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/); -int sal_call_update(SalOp *h, const char *subject); +int sal_call_update(SalOp *h, const char *subject, bool_t no_user_consent); SalMediaDescription * sal_call_get_remote_media_description(SalOp *h); SalMediaDescription * sal_call_get_final_media_description(SalOp *h); int sal_call_refer(SalOp *h, const char *refer_to); @@ -751,5 +759,5 @@ int sal_body_has_type(const SalBody *body, const char *type, const char *subtype int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal); - +char* sal_op_get_public_uri(SalOp *sal); #endif diff --git a/java/common/org/.DS_Store b/java/common/org/.DS_Store deleted file mode 100644 index 2d8977d32..000000000 Binary files a/java/common/org/.DS_Store and /dev/null differ diff --git a/java/common/org/linphone/.DS_Store b/java/common/org/linphone/.DS_Store deleted file mode 100644 index f0988f202..000000000 Binary files a/java/common/org/linphone/.DS_Store and /dev/null differ diff --git a/java/common/org/linphone/core/LinphoneCall.java b/java/common/org/linphone/core/LinphoneCall.java index d75f1bbdb..404fdbcf0 100644 --- a/java/common/org/linphone/core/LinphoneCall.java +++ b/java/common/org/linphone/core/LinphoneCall.java @@ -119,6 +119,15 @@ static class State { */ public static final State CallReleased = new State(18,"Released"); + /** + * The call is updated by remote while not yet answered (SIP UPDATE in early dialog received) + */ + public static final State CallEarlyUpdatedByRemote = new State(19,"EarlyUpdatedByRemote"); + + /** + * We are updating the call while not yet answered (SIP UPDATE in early dialog sent) + **/ + public static final State CallEarlyUpdating = new State(20,"EarlyUpdating"); private State(int value,String stringValue) { mValue = value; @@ -333,4 +342,11 @@ public String toString() { * @return an Object. */ Object getUserData(); + + /** + * Get a call player + * Call player enable to stream a media file through a call + * @return A player + */ + public LinphonePlayer getPlayer(); } diff --git a/java/common/org/linphone/core/LinphoneChatMessage.java b/java/common/org/linphone/core/LinphoneChatMessage.java index d51a19251..930a064db 100644 --- a/java/common/org/linphone/core/LinphoneChatMessage.java +++ b/java/common/org/linphone/core/LinphoneChatMessage.java @@ -14,21 +14,25 @@ public static class State { private final String mStringValue; /** - * Idle + * Initial state */ public final static State Idle = new State(0,"Idle"); /** - * Incoming call received. + * Delivery in progress */ public final static State InProgress = new State(1,"InProgress"); /** - * Outgoing call initialiazed. + * Message succesffully delivered an acknoleged by remote end point */ public final static State Delivered = new State(2,"Delivered"); /** - * Outgoing call in progress. + * Message was not delivered */ public final static State NotDelivered = new State(3,"NotDelivered"); + /** + * Message was received(and acknowledged) but cannot get file from server + */ + public final static State FileTransferError = new State(4,"FileTransferError"); private State(int value,String stringValue) { mValue = value; @@ -74,6 +78,12 @@ public int toInt() { */ LinphoneAddress getFrom(); + /** + * Get destination address of the LinphoneChatMessage. + * @return the LinphoneAddress in the To field of the message. + */ + LinphoneAddress getTo(); + /** * Linphone message can carry external body as defined by rfc2017 * @param message #LinphoneChatMessage @@ -147,4 +157,26 @@ public int toInt() { * @return an ErrorInfo. */ ErrorInfo getErrorInfo(); + + /** + * Start the download of the file bundled in the message + */ + void startFileDownload(LinphoneChatMessage.StateListener listener); + + /** + * Get the file_transfer_information (used by call backs to recover informations during a rcs file transfer) + * @return a pointer to the LinphoneContent structure or NULL if not present. + */ + LinphoneContent getFileTransferInformation(); + + /** + * Sets data in the chat message + * @param data to store in the message + */ + void setAppData(String data); + + /** + * @return the data stored in the chat message if any, else null + */ + String getAppData(); } diff --git a/java/common/org/linphone/core/LinphoneChatRoom.java b/java/common/org/linphone/core/LinphoneChatRoom.java index c1e635c0a..1f8c58f8c 100644 --- a/java/common/org/linphone/core/LinphoneChatRoom.java +++ b/java/common/org/linphone/core/LinphoneChatRoom.java @@ -21,8 +21,8 @@ of the License, or (at your option) any later version. import org.linphone.core.LinphoneChatMessage.State; /** - * - * A chat room is the place where text messages are exchanged. + * + * A chat room is the place where text messages are exchanged. Can be created by linphone_core_create_chat_room(). * */ @@ -33,17 +33,19 @@ public interface LinphoneChatRoom { * @return LinphoneAddress peer address */ LinphoneAddress getPeerAddress(); + /** * send a message to peer member of this chat room. * @param message to be sent */ void sendMessage(String message); + /** * Send a message to peer member of this chat room. * @param chat message */ void sendMessage(LinphoneChatMessage message, LinphoneChatMessage.StateListener listener); - + /** * Create a LinphoneChatMessage * @param chatRoom chat room associated to the message @@ -51,31 +53,45 @@ public interface LinphoneChatRoom { * @return LinphoneChatMessage object */ LinphoneChatMessage createLinphoneChatMessage(String message); - + /** * Returns the chat history associated with the peer address associated with this chat room * @return an array of LinphoneChatMessage */ LinphoneChatMessage[] getHistory(); - + /** * Returns the chat history associated with the peer address associated with this chat room * @param limit the maximum number of messages to fetch * @return an array of LinphoneChatMessage */ LinphoneChatMessage[] getHistory(int limit); - + + /** + * Returns the chat history associated with the peer address associated with this chat room for the given range, sorted from oldest to most recent + * @param begin the first (most recent) message to retrieve. Newest message has index 0. If negative, use value 0 instead. + * @param end the last (oldest) message to retrieve. Oldest message has value "history size" - 1 (equivalent to -1). If negative or lower than begin value, value is given, use -1. + * @return an array of LinphoneChatMessage, empty if nothing has been found + */ + LinphoneChatMessage[] getHistoryRange(int begin, int end); + /** * Destroys a LinphoneChatRoom. */ void destroy(); - + /** * Returns the amount of unread messages associated with the peer of this chatRoom. * @return the amount of unread messages */ int getUnreadMessagesCount(); - + + /** + * Returns the amount of messages associated with the peer of this chatRoom. + * @return the amount of messages in the conversation + */ + int getHistorySize(); + /** * Deletes all the messages associated with the peer of this chat room */ @@ -91,32 +107,46 @@ public interface LinphoneChatRoom { * @return true if the remote is currently composing a message, false otherwise. */ boolean isRemoteComposing(); - + /** * Marks all the messages in this conversation as read */ void markAsRead(); - + /** * Deletes a message * @param message the message to delete */ void deleteMessage(LinphoneChatMessage message); - + /** * Update the value stored in the database for the external_body_url field * @param message to update */ void updateUrl(LinphoneChatMessage message); - + /** * Create a LinphoneChatMessage * @return LinphoneChatMessage object */ LinphoneChatMessage createLinphoneChatMessage(String message, String url, State state, long timestamp, boolean isRead, boolean isIncoming); + /** * Returns a back pointer to the core managing the chat room. * @return the LinphoneCore */ LinphoneCore getCore(); + + /** + * Create a message attached to a dedicated chat room with a particular content. + * @param content LinphoneContent initial content. + * @return a new LinphoneChatMessage + */ + LinphoneChatMessage createFileTransferMessage(LinphoneContent content); + + /** + * Cancel an ongoing file transfer attached to this message (upload or download) + * @param message + */ + void cancelFileTransfer(LinphoneChatMessage message); } diff --git a/java/common/org/linphone/core/LinphoneContent.java b/java/common/org/linphone/core/LinphoneContent.java index 10c6e3dc9..eb41c62f7 100644 --- a/java/common/org/linphone/core/LinphoneContent.java +++ b/java/common/org/linphone/core/LinphoneContent.java @@ -31,10 +31,21 @@ public interface LinphoneContent { **/ byte [] getData(); /** - * Get the data size. - * @return the data size. + * Get the expected data size. + * @return the expected data size */ - int getSize(); + int getExpectedSize(); + + /** + * Sets the expected data size + */ + void setExpectedSize(int size); + + /** + * Return the size of the data field + * @return the size of the data field + */ + int getRealSize(); /** * Set the content type, for example "application" @@ -59,4 +70,8 @@ public interface LinphoneContent { * Set the data, as a byte buffer. **/ void setData(byte data[]); + + void setName(String name); + + String getName(); } diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index a74ebc125..af878e24f 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -26,7 +26,7 @@ of the License, or (at your option) any later version. import android.view.SurfaceView; /** - * Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}. + * Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}. * */ @@ -35,12 +35,12 @@ public interface LinphoneCore { * linphone core states */ static public class GlobalState { - + static private Vector values = new Vector(); /** * Off */ - static public GlobalState GlobalOff = new GlobalState(0,"GlobalOff"); + static public GlobalState GlobalOff = new GlobalState(0,"GlobalOff"); /** * Startup */ @@ -61,7 +61,7 @@ static public class GlobalState { private final int mValue; private final String mStringValue; - + private GlobalState(int value,String stringValue) { mValue = value; values.addElement(this); @@ -83,12 +83,12 @@ public String toString() { * linphone remote provisioning states */ static public class RemoteProvisioningState { - + static private Vector values = new Vector(); /** * Off */ - static public RemoteProvisioningState ConfiguringSuccessful = new RemoteProvisioningState(0,"ConfiguringSuccessful"); + static public RemoteProvisioningState ConfiguringSuccessful = new RemoteProvisioningState(0,"ConfiguringSuccessful"); /** * Startup */ @@ -101,7 +101,7 @@ static public class RemoteProvisioningState { private final int mValue; private final String mStringValue; - + private RemoteProvisioningState(int value,String stringValue) { mValue = value; values.addElement(this); @@ -124,12 +124,12 @@ public String toString() { * */ static public class RegistrationState { - + private static Vector values = new Vector(); /** * None */ - public static RegistrationState RegistrationNone = new RegistrationState(0,"RegistrationNone"); + public static RegistrationState RegistrationNone = new RegistrationState(0,"RegistrationNone"); /** * In Progress */ @@ -149,7 +149,7 @@ static public class RegistrationState { private final int mValue; private final String mStringValue; - + private RegistrationState(int value,String stringValue) { mValue = value; values.addElement(this); @@ -172,12 +172,12 @@ public String toString() { * */ static public class FirewallPolicy { - + static private Vector values = new Vector(); /** * No firewall is assumed. */ - static public FirewallPolicy NoFirewall = new FirewallPolicy(0,"NoFirewall"); + static public FirewallPolicy NoFirewall = new FirewallPolicy(0,"NoFirewall"); /** * Use NAT address (discouraged) */ @@ -194,11 +194,11 @@ static public class FirewallPolicy { * Use uPnP. */ static public FirewallPolicy UseUpnp = new FirewallPolicy(4,"UseUpnp"); - + private final int mValue; private final String mStringValue; - + private FirewallPolicy(int value,String stringValue) { mValue = value; values.addElement(this); @@ -219,7 +219,7 @@ public int value(){ return mValue; } } - + /** * Linphone core SIP transport ports. * Use with {@link LinphoneCore#setSignalingTransportPorts(Transports)} @@ -238,7 +238,7 @@ static public class Transports { * tls port to listening on, negative value if not set * */ public int tls; - + public Transports() {}; public Transports(Transports t) { this.udp = t.udp; @@ -254,12 +254,12 @@ public String toString() { * */ static public final class MediaEncryption { - + static private Vector values = new Vector(); /** * None */ - static public final MediaEncryption None = new MediaEncryption(0,"None"); + static public final MediaEncryption None = new MediaEncryption(0,"None"); /** * SRTP */ @@ -271,7 +271,7 @@ static public final class MediaEncryption { protected final int mValue; private final String mStringValue; - + private MediaEncryption(int value,String stringValue) { mValue = value; values.addElement(this); @@ -289,11 +289,43 @@ public String toString() { return mStringValue; } } + static public final class AdaptiveRateAlgorithm { + + static private Vector values = new Vector(); + /** + * Simple + */ + static public final AdaptiveRateAlgorithm Simple = new AdaptiveRateAlgorithm(0,"Simple"); + /** + * Stateful + */ + static public final AdaptiveRateAlgorithm Stateful = new AdaptiveRateAlgorithm(1,"Stateful"); + protected final int mValue; + private final String mStringValue; + + + private AdaptiveRateAlgorithm(int value,String stringValue) { + mValue = value; + values.addElement(this); + mStringValue=stringValue; + } + public static AdaptiveRateAlgorithm fromString(String value) { + + for (int i=0; i values = new Vector(); /* Do not change the values of these constants or the strings associated with them to prevent breaking the collection of echo canceller calibration results during the wizard! */ @@ -321,7 +353,7 @@ static public class EcCalibratorStatus { private final int mValue; private final String mStringValue; - + private EcCalibratorStatus(int value,String stringValue) { mValue = value; values.addElement(this); @@ -342,11 +374,11 @@ public int value(){ return mValue; } } - + static public class UpnpState { static private Vector values = new Vector(); /** - * Idle + * Idle */ static public UpnpState Idle = new UpnpState(0, "Idle"); /** @@ -370,11 +402,11 @@ static public class UpnpState { */ static public UpnpState Ok = new UpnpState(5, "Ok"); /** - * Ko + * Ko */ static public UpnpState Ko = new UpnpState(6, "Ko"); /** - * Blacklisted + * Blacklisted */ static public UpnpState Blacklisted = new UpnpState(7, "Blacklisted"); @@ -413,34 +445,34 @@ public String toString() { * @throws LinphoneCoreException */ public void addProxyConfig(LinphoneProxyConfig proxyCfg) throws LinphoneCoreException; - + /** * Removes a proxy configuration. * @param proxyCfg */ public void removeProxyConfig(LinphoneProxyConfig proxyCfg); - + /** * Sets the default proxy. *
- * This default proxy must be part of the list of already entered {@link LinphoneProxyConfig}. + * This default proxy must be part of the list of already entered {@link LinphoneProxyConfig}. * Toggling it as default will make LinphoneCore favor the identity associated with the proxy configuration in all incoming and outgoing calls. * Better proxy configuration match may override this choice. Pass null to unset the default proxy. - * @param proxyCfg + * @param proxyCfg */ public void setDefaultProxyConfig(LinphoneProxyConfig proxyCfg); - + /** * get he default proxy configuration, that is the one used to determine the current identity. - * @return null if no default proxy config + * @return null if no default proxy config */ public LinphoneProxyConfig getDefaultProxyConfig() ; - + /** * Returns an array with all the auth infos stored in LinphoneCore */ LinphoneAuthInfo[] getAuthInfosList(); - + /** * Returns a matching auth info or null if no match found */ @@ -450,7 +482,7 @@ public String toString() { * @param authInfo */ public void removeAuthInfo(LinphoneAuthInfo authInfo); - + /** * clear all the added auth info */ @@ -461,7 +493,7 @@ public String toString() { * @param info */ void addAuthInfo(LinphoneAuthInfo info); - + /** * Build an address according to the current proxy config. In case destination is not a sip address, the default proxy domain is automatically appended * @param destination @@ -469,7 +501,7 @@ public String toString() { * @throws If no LinphoneAddress can be built from destination */ public LinphoneAddress interpretUrl(String destination) throws LinphoneCoreException; - + /** * Starts a call given a destination. Internally calls {@link #interpretUrl(String)} then {@link #invite(LinphoneAddress)}. * @param uri @@ -498,20 +530,20 @@ public String toString() { * Returns The LinphoneCall the current call if one is in call * **/ - public LinphoneCall getCurrentCall(); - + public LinphoneCall getCurrentCall(); + /** * get current call remote address in case of in/out call * @return null if no call engaged yet */ public LinphoneAddress getRemoteAddress(); /** - * + * * @return true if there is a call running or pending. */ public boolean isIncall(); /** - * + * * @return Returns true if in incoming call is pending, ie waiting for being answered or declined. */ public boolean isInComingInvitePending(); @@ -522,7 +554,7 @@ public String toString() { *
  • receiving of SIP messages *
  • handles timers and timeout *
  • performs registration to proxies - *
  • authentication retries The application MUST call this function from periodically, in its main loop. + *
  • authentication retries The application MUST call this function from periodically, in its main loop. *
    Be careful that this function must be call from the same thread as other liblinphone methods. In not the case make sure all liblinphone calls are serialized with a mutex. */ @@ -534,10 +566,10 @@ public String toString() { * {@link LinphoneCoreListener#callState} listener method. * The application can later respond positively to the call using * this method. - * @throws LinphoneCoreException + * @throws LinphoneCoreException */ public void acceptCall(LinphoneCall aCall) throws LinphoneCoreException; - + /** * Accept an incoming call. * @@ -545,10 +577,10 @@ public String toString() { * {@link LinphoneCoreListener#callState} listener method. * The application can later respond positively to the call using * this method. - * @throws LinphoneCoreException + * @throws LinphoneCoreException */ public void acceptCallWithParams(LinphoneCall aCall, LinphoneCallParams params) throws LinphoneCoreException; - + /** * Accept call modifications initiated by other end. * @@ -556,11 +588,11 @@ public String toString() { * {@link LinphoneCoreListener#callState} listener method. * The application can later respond positively to the call using * this method. - * @throws LinphoneCoreException + * @throws LinphoneCoreException */ public void acceptCallUpdate(LinphoneCall aCall, LinphoneCallParams params) throws LinphoneCoreException; - - + + /** * Prevent LinphoneCore from performing an automatic answer * @@ -568,21 +600,21 @@ public String toString() { * {@link LinphoneCoreListener#callState} listener method. * The application can later respond positively to the call using * this method. - * @throws LinphoneCoreException + * @throws LinphoneCoreException */ public void deferCallUpdate(LinphoneCall aCall) throws LinphoneCoreException; /** - * @return a list of LinphoneCallLog + * @return a list of LinphoneCallLog */ public LinphoneCallLog[] getCallLogs(); - + /** * This method is called by the application to notify the Linphone core library when network is reachable. * Calling this method with true trigger Linphone to initiate a registration process for all proxy * configuration with parameter register set to enable. * This method disable the automatic registration mode. It means you must call this method after each network state changes - * @param network state + * @param network state * */ public void setNetworkReachable(boolean isReachable); @@ -596,12 +628,12 @@ public String toString() { */ public void destroy(); /** - * Allow to control play level before entering sound card: + * Allow to control play level before entering sound card: * @param level in db */ public void setPlaybackGain(float gain); /** - * get play level before entering sound card: + * get play level before entering sound card: * @return level in db */ public float getPlaybackGain(); @@ -622,7 +654,7 @@ public String toString() { */ void muteMic(boolean isMuted); /** - * + * * @return true is mic is muted */ boolean isMicMuted(); @@ -643,42 +675,42 @@ public String toString() { * stop current dtmf */ void stopDtmf(); - + /** * remove all call logs */ void clearCallLogs(); - - - - + + + + /** * Get payload type from mime type and clock rate * * This function searches in audio and video codecs for the given payload type name and clockrate. * @param mime payload mime type (I.E SPEEX, PCMU, VP8) - * @param clockRate (I.E 8000, 16000, 90000, ...) + * @param clockRate (I.E 8000, 16000, 90000, ...) * @param channels number of channels * @return Returns null if not found. - */ - PayloadType findPayloadType(String mime, int clockRate, int channels); + */ + PayloadType findPayloadType(String mime, int clockRate, int channels); /*** * get payload type from mime type and clock rate.. * Same as @{link {@link #findPayloadType(String, int, int)} but ignoring channels params * @param mime payload mime type (I.E SPEEX, PCMU, VP8) - * @param clockRate (I.E 8000, 16000, 90000, ...) + * @param clockRate (I.E 8000, 16000, 90000, ...) * @return null if not found */ - PayloadType findPayloadType(String mime, int clockRate); - + PayloadType findPayloadType(String mime, int clockRate); + /*** - * get payload type from mime type + * get payload type from mime type * Same as @{link {@link #findPayloadType(String, int, int)} but ignoring channels and clock rate params * @param mime payload mime type (I.E SPEEX, PCMU, VP8) * @return null if not found */ - PayloadType findPayloadType(String mime); - + PayloadType findPayloadType(String mime); + /** * Enable payload type * @param pt payload type to enable, can be retrieve from {@link #findPayloadType} @@ -687,45 +719,64 @@ public String toString() { * */ void enablePayloadType(PayloadType pt, boolean enable) throws LinphoneCoreException; - + /** - * Returns whether or not the payload is enabled in linphonecore. + * @param pt the payload type + * @return whether or not the payload is enabled in linphonecore. */ boolean isPayloadTypeEnabled(PayloadType pt); - + + /** + * @param pt the payload type + * @return whether or not the payload epresents a VBR codec + */ + boolean payloadTypeIsVbr(PayloadType pt); + /** * Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s. * @param pt the payload type * @param bitrate target IP bitrate in kbit/s */ void setPayloadTypeBitrate(PayloadType pt, int bitrate); - + /** * Get target bitrate previously set by setPayloadTypeBitrate(). * @param pt * @return IP bitrate in kbit/s */ int getPayloadTypeBitrate(PayloadType pt); - + /** * Enable adaptive rate control. * @param enable */ void enableAdaptiveRateControl(boolean enable); - + /** * Enables or disable adaptive rate control. * @return true if adaptive rate control is enabled. */ boolean isAdaptiveRateControlEnabled(); - + + /** + * Sets adaptive rate algorithm. It will be used for each new calls + * starting from now. Calls already started will not be updated. + */ + void setAdaptiveRateAlgorithm(AdaptiveRateAlgorithm alg); + + /** + * Returns which adaptive rate algorithm is currently configured for + * future calls. + */ + AdaptiveRateAlgorithm getAdaptiveRateAlgorithm(); + /** * Enables or disable echo cancellation. * @param enable */ void enableEchoCancellation(boolean enable); /** - * get EC status + * get EC status * @return true if echo cancellation is enabled. */ boolean isEchoCancellationEnabled(); @@ -739,24 +790,24 @@ public String toString() { * @param local transports ports used for signaling (TCP, UDP and TLS) */ void setSignalingTransportPorts(Transports transports); - /**Get + /**Get * @return transports used for signaling (TCP, UDP, TLS) */ Transports getSignalingTransportPorts(); - + /** * Assign a dscp value for the SIP socket. * DSCP is an IP packet field used to indicate the type of routing service to routers. * @param dscp */ void setSipDscp(int dscp); - + /** * Get DSCP used for SIP socket. * @return the DSCP value used for the SIP socket. */ int getSipDscp(); - + /** * Activates or deactivates the speaker. * @param value @@ -800,7 +851,7 @@ public String toString() { PresenceModel getPresenceModel(); /** * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org - * @param to destination address for messages + * @param to destination address for messages * * @return {@link LinphoneChatRoom} where messaging can take place. */ @@ -836,18 +887,18 @@ public String toString() { * Returns the id of the currently active video device as found in {@link AndroidCameraConfiguration#retrieveCameras}. **/ int getVideoDevice(); - - + + /** * Teturns true if the underlying sdk support video - * + * * */ boolean isVideoSupported(); - + /** * Enables video globally. * - * + * * This function does not have any effect during calls. It just indicates #LinphoneCore to * initiate future calls with video or not. The two boolean parameters indicate in which * direction video is enabled. Setting both to false disables video entirely. @@ -859,10 +910,10 @@ public String toString() { void enableVideo(boolean vcap_enabled, boolean display_enabled); /** * Returns TRUE if video is enabled, FALSE otherwise. - * + * ***/ boolean isVideoEnabled(); - + /** * Specify a STUN server to help firewall traversal. * @param stun_server Stun server address and port, such as stun.linphone.org or stun.linphone.org:3478 @@ -873,7 +924,7 @@ public String toString() { * @return stun server address if previously set. */ String getStunServer(); - + /** * Sets policy regarding workarounding NATs * @param pol one of the FirewallPolicy members. @@ -891,7 +942,7 @@ public String toString() { * *
    The LinphoneAddress can be constructed directly using {@link LinphoneCoreFactory#createLinphoneAddress} , or created {@link LinphoneCore#interpretUrl(String)}. . * - * @return a {@link #LinphoneCall LinphoneCall} object + * @return a {@link #LinphoneCall LinphoneCall} object * @throws LinphoneCoreException in case of failure **/ LinphoneCall inviteAddressWithParams(LinphoneAddress destination, LinphoneCallParams params) throws LinphoneCoreException ; @@ -926,14 +977,14 @@ public String toString() { * @return null if not set */ String getRing(); - + /** * Sets file or folder containing trusted root CAs * * @param path path to file with multiple PEM certif or to folder with multiple PEM files - */ + */ void setRootCA(String path); - + void setUploadBandwidth(int bw); /** * Sets maximum available download bandwidth @@ -948,13 +999,13 @@ public String toString() { * @param bw the bandwidth in kbits/s, 0 for infinite */ void setDownloadBandwidth(int bw); - + /** * Sets audio packetization interval suggested for remote end. * @param ptime packetization interval in milliseconds */ void setDownloadPtime(int ptime); - + /** * Sets audio packetization interval sent to remote end. * @param ptime packetization interval in milliseconds @@ -966,7 +1017,7 @@ public String toString() { * This applies only to the stream that is captured and sent to the remote party, * since we accept all standard video size on the receive path. * @param vSize - * + * **/ void setPreferredVideoSize(VideoSize vSize); /** @@ -983,7 +1034,7 @@ public String toString() { * **/ VideoSize getPreferredVideoSize(); - + /** * Returns the currently supported audio codecs, as PayloadType elements * @return @@ -1016,17 +1067,17 @@ public String toString() { * If the device has a builtin echo canceller or calibration value is already known, it will return false. */ boolean needsEchoCalibration(); - + void enableIpv6(boolean enable); - + boolean isIpv6Enabled(); - + /** * @deprecated * @param i */ void adjustSoftwareVolume(int i); - + /** * Pauses a call. If a music file has been setup using {@link LinphoneCore#setPlayFile(String)}, * this file will be played to the remote user. @@ -1041,7 +1092,7 @@ public String toString() { * Pause all currently running calls. **/ boolean pauseAllCalls(); - + void setZrtpSecretsCache(String file); void enableEchoLimiter(boolean val); @@ -1051,12 +1102,12 @@ public String toString() { boolean isInConference(); /** * Moves the local participant inside the conference. - * - * Makes the local participant to join the conference. + * + * Makes the local participant to join the conference. * Typically, the local participant is by default always part of the conference when joining an active call into a conference. * However, by calling {@link #leaveConference()} and {@link #enterConference()} the application can decide to temporarily * move out and in the local participant from the conference. - * + * * @returns true if successful **/ boolean enterConference(); @@ -1068,49 +1119,49 @@ public String toString() { /** * Merge a call into a conference. - * + * * If this is the first call that enters the conference, the virtual conference will be created automatically. * If the local user was actively part of the call (ie not in paused state), then the local user is automatically entered into the conference. * If the call was in paused state, then it is automatically resumed when entering into the conference. * @param call an established call, either in {@link LinphoneCall.State#StreamsRunning} or {@link LinphoneCall.State#Paused} state. - * + * **/ void addToConference(LinphoneCall call); /** * Remove a call from the conference. * @param call a call that has been previously merged into the conference. - * + * * After removing the remote participant belonging to the supplied call, the call becomes a normal call in paused state. * If one single remote participant is left alone together with the local user in the conference after the removal, then the conference is * automatically transformed into a simple call in StreamsRunning state. * The conference's resources are then automatically destroyed. - * + * * In other words, unless {@link #leaveConference()} is explicitely called, the last remote participant of a conference is automatically * put in a simple call in running state. - * + * **/ void removeFromConference(LinphoneCall call); /** * Add all calls into a conference. - * + * * Merge all established calls (either in {@link LinphoneCall.State#StreamsRunning} or {@link LinphoneCall.State#Paused}) into a conference. - * + * **/ void addAllToConference(); - + /** * Terminates the conference and the calls associated with it. - * + * * All the calls that were merged to the conference are terminated, and the conference resources are destroyed. - * + * **/ void terminateConference(); /** * Returns the number of participants to the conference, including the local participant. - * + * * Typically, after merging two calls into the conference, there is total of 3 participants: * the local participant (or local user), and two remote participants that were the destinations of the two previously establised calls. - * + * * @returns the number of participants to the conference **/ int getConferenceSize(); @@ -1121,7 +1172,7 @@ public String toString() { * @param path where to write recording file **/ void startConferenceRecording(String path); - + /** * Stop recording of the conference. **/ @@ -1159,7 +1210,7 @@ public String toString() { * @param dest a running call whose remote person will receive the transfer **/ void transferCallToAnother(LinphoneCall callToTransfer, LinphoneCall destination); - + /** * Start a new call as a consequence of a transfer request received from a call. * This function is for advanced usage: the execution of transfers is automatically managed by the LinphoneCore. However if an application @@ -1197,7 +1248,7 @@ public String toString() { * which could result in an active call. * Eg: don't start a new call if one is in outgoing ringing. * Eg: don't merge to conference either as it could result - * in two active calls (conference and accepted call). + * in two active calls (conference and accepted call). * @return */ boolean soundResourcesLocked(); @@ -1228,9 +1279,84 @@ public String toString() { * @param path path to music file played to remote side when on hold. */ void setPlayFile(String path); + + + enum TunnelMode { + disable(0), + enable(1), + auto(2); + private final int value; + + private TunnelMode(int value){ + this.value = value; + } + public static int enumToInt(TunnelMode enum_mode) { + return enum_mode.value; + } + public static TunnelMode intToEnum(int value) { + switch(value) { + case 0: return disable; + case 1: return enable; + case 2: return auto; + default: return disable; + } + } + } + + /** + * @deprecated Use tunnelSetMode() instead + * Enable or disable tunnel + * @param enable True to enable and false to disable + */ void tunnelEnable(boolean enable); + + /** + * Set the tunnel mode. + * The tunnel can be enable or disable by passing 'enable' or 'disable'. + * If the mode is set to 'auto', Linphone will try to establish an RTP session + * on the mirror port of the tunnel server. If the connection fails, the tunnel + * will be activated. + * @param mode enable, disable or auto + */ + void tunnelSetMode(TunnelMode mode); + + /** + * Get the set mode + * @return + */ + TunnelMode tunnelGetMode(); + + /** + * Set whether sip packets must pass through the tunnel + * @param enable If true, tunnel will transport SIP packets in addition + * of RTP packets. + */ + void tunnelEnableSip(boolean enable); + + /** + * Check whether SIP tuneling is enabled + * @return true means the tunnel is set to transport SIP packets + */ + boolean tunnelSipEnabled(); + + /** + * @deprecated Use tunnelSetMode instaead + * Enable tunnel if the mirror RTP session cannot be established + */ void tunnelAutoDetect(); + + /** + * Clean the list of server + */ void tunnelCleanServers(); + + /** + * Set an optional HTTP proxy + * @param proxy_host + * @param port + * @param username + * @param password + */ void tunnelSetHttpProxy(String proxy_host, int port, String username, String password); /** * @param host tunnel server ip address @@ -1239,6 +1365,16 @@ public String toString() { * @param roundTripDelay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms */ void tunnelAddServerAndMirror(String host, int port, int udpMirrorPort, int roundTripDelay); + /** + * Add a server to the list of tunnel servers. + * @param config Parameters of the server to add. + */ + void tunnelAddServer(TunnelConfig config); + /** + * Returns a list of configured servers. + * @return Array of server configs. + */ + TunnelConfig[] tunnelGetServers(); boolean isTunnelAvailable(); /** @@ -1253,18 +1389,18 @@ public String toString() { * @param autoAccept video shall be accepter by default for incoming calls **/ void setVideoPolicy(boolean autoInitiate, boolean autoAccept); - + /** * Gets the policy for the autoInitiate video */ boolean getVideoAutoInitiatePolicy(); - + /** * Gets the policy for the autoAccept video */ boolean getVideoAutoAcceptPolicy(); - - /** Set static picture to be used when "Static picture" is the video device + + /** Set static picture to be used when "Static picture" is the video device * @param path to the static picture file * */ void setStaticPicture(String path); @@ -1278,17 +1414,17 @@ public String toString() { * Set the number of cores used for media processing * */ void setCpuCount(int count); - + /** * remove a call log */ public void removeCallLog(LinphoneCallLog log); - + /** * @return count of missed calls */ public int getMissedCallsCount(); - + /** * Set missed calls count to zero */ @@ -1302,111 +1438,111 @@ public String toString() { * return the version code of linphone core */ public String getVersion(); - + /** * remove a linphone friend from linphone core and linphonerc */ void removeFriend(LinphoneFriend lf); - + /** * return a linphone friend (if exists) that matches the sip address */ LinphoneFriend findFriendByAddress(String sipUri); - + /** * Sets the UDP port used for audio streaming. **/ void setAudioPort(int port); - + /** * Sets the UDP port range from which to randomly select the port used for audio streaming. */ void setAudioPortRange(int minPort, int maxPort); - + /** * Assign a DSCP value to the audio RTP sockets. * @param dscp the DSCP value. * DSCP is an IP header field used to indicate a type of service to routers. */ void setAudioDscp(int dscp); - + /** * Return DSCP value used for the audio RTP sockets. * @return the DSCP value used for the audio RTP sockets. */ int getAudioDscp(); - + /** * Sets the UDP port used for video streaming. **/ void setVideoPort(int port); - + /** * Sets the UDP port range from which to randomly select the port used for video streaming. */ void setVideoPortRange(int minPort, int maxPort); - + /** * Assign a DSCP value to the video RTP sockets. * @param dscp the DSCP value. * DSCP is an IP header field used to indicate a type of service to routers. */ void setVideoDscp(int dscp); - + /** * Return DSCP value used for the video RTP sockets. * @return the DSCP value used for the video RTP sockets. */ int getVideoDscp(); - + /** * Set the incoming call timeout in seconds. * If an incoming call isn't answered for this timeout period, it is * automatically declined. **/ void setIncomingTimeout(int timeout); - + /** * Set the call timeout in seconds. * Once this time is elapsed (ringing included), the call is automatically hung up. **/ void setInCallTimeout(int timeout); /** - * Allow to control microphone level: + * Allow to control microphone level: * @param gain in db **/ void setMicrophoneGain(float gain); - + /** * Set username and display name to use if no LinphoneProxyConfig configured */ void setPrimaryContact(String displayName, String username); - + /** * Returns the username used if no LinphoneProxyConfig configured */ String getPrimaryContactUsername(); - + /** * Returns the display name used if no LinphoneProxyConfig configured */ String getPrimaryContactDisplayName(); - + /** * Enable/Disable the use of SIP INFO for DTMFs */ void setUseSipInfoForDtmfs(boolean use); - + /** * Returns the state of use of SIP INFO for DTMFs */ boolean getUseSipInfoForDtmfs(); - + /** * Enable/Disable the use of inband DTMFs */ void setUseRfc2833ForDtmfs(boolean use); - + /** * Returns the state of use of inband DTMFs */ @@ -1422,34 +1558,34 @@ public String toString() { /** * Return the availability of uPnP. * - * @return true if uPnP is available otherwise return false. + * @return true if uPnP is available otherwise return false. */ public boolean upnpAvailable(); /** - * Return the internal state of uPnP. + * Return the internal state of uPnP. * - * @return an UpnpState. + * @return an UpnpState. */ public UpnpState getUpnpState(); /** - * Return the external ip address of router. + * Return the external ip address of router. * In some cases the uPnP can have an external ip address but not a usable uPnP - * (state different of Ok). + * (state different of Ok). * * @return a null terminated string containing the external ip address. If the - * the external ip address is not available return null. + * the external ip address is not available return null. */ public String getUpnpExternalIpaddress(); - + /** * Create an empty INFO message. * It can later be sent using {@link LinphoneCall.sendInfoMessage() }. * @return the new info message. */ public LinphoneInfoMessage createInfoMessage(); - + /** * Sends an outgoing subscription for a resource with given event, expiration period, and content. * The state changes of the new subscriptions can be followed thanks to { @link LinphoneCoreListener.subscriptionStateChanged() } and @@ -1461,7 +1597,7 @@ public String toString() { * @return a LinphoneEvent representing the subscription context. */ public LinphoneEvent subscribe(LinphoneAddress resource, String event, int expires, LinphoneContent content); - + /** * Create an outgoing subscription, specifying the destination resource, the event name, and an optional content body. * If accepted, the subscription runs for a finite period, but is automatically renewed if not terminated before. @@ -1473,7 +1609,7 @@ public String toString() { * @return a LinphoneEvent holding the context of the created subcription. */ public LinphoneEvent createSubscribe(LinphoneAddress resource, String event, int expires); - + /** * Create a publish context for an event state. * After being created, the publish must be sent using linphone_event_send_publish(). @@ -1484,7 +1620,7 @@ public String toString() { * @return the LinphoneEvent holding the context of the publish. */ public LinphoneEvent createPublish(LinphoneAddress resource, String event, int expires); - + /** * Publish an event. * After the initial publication, updates can be done with { @link LinphoneEvent.updatePublish() } @@ -1495,25 +1631,25 @@ public String toString() { * @return a LinphoneEvent representing the publish context. */ public LinphoneEvent publish(LinphoneAddress resource, String event, int expires, LinphoneContent content); - + /** * Sets the path to the database where the chat messages will be stored (if enabled) * @param path the database where the chat messages will be stored. */ public void setChatDatabasePath(String path); - + /** * Gets the chat rooms * @return an array of LinphoneChatRoom */ public LinphoneChatRoom[] getChatRooms(); - + /** * Gets the linphonecore supported resolutions for video * @return an array of String */ public String[] getSupportedVideoSizes(); - + /** * Migrate configuration so that all SIP transports are enabled. * Versions of linphone < 3.7 did not support using multiple SIP transport simultaneously. @@ -1523,7 +1659,7 @@ public String toString() { * @returns 1 if migration was done, 0 if not done because unnecessary or already done, -1 in case of error. */ public int migrateToMultiTransport(); - + /** * When receiving an incoming, accept to start a media session as early-media. * This means the call is not accepted but audio & video streams can be established if the remote party supports early media. @@ -1535,7 +1671,7 @@ public String toString() { * @return true if successful, false otherwise. */ public boolean acceptEarlyMedia(LinphoneCall call); - + /** * Accept an early media session for an incoming call. * This is identical as calling linphone_core_accept_early_media_with_params() with NULL call parameters. @@ -1545,28 +1681,29 @@ public String toString() { * @return true if successful, false otherwise. */ public boolean acceptEarlyMediaWithParams(LinphoneCall call, LinphoneCallParams params); - + /** * Creates a proxy config using the default values if they exists * @return a default proxy config */ public LinphoneProxyConfig createProxyConfig(); - + public LinphoneProxyConfig createProxyConfig(String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException; + /** * Assign an audio file to played locally upon call failure, for a given reason. * @param reason the #LinphoneReason representing the failure error code. * @param path a wav file to be played when such call failure happens. */ public void setCallErrorTone(Reason reason, String path); - + /** * Assign an audio file to be played locally in replacement of common telephony tone. * This is typically used to internationalize tones. * @param id a tone id - * @param wav a path to a 16 bit PCM linear wav file. + * @param wav a path to a 16 bit PCM linear wav file. */ public void setTone(ToneID id, String wavfile); - + /** * Inform the core about the maximum transmission unit of the network. * This is used for fragmenting video RTP packets to a size compatible with the network. @@ -1575,7 +1712,7 @@ public String toString() { public void setMtu(int mtu); /** * Returns the mtu value previously set by setMtu(). - * + * * @return the MTU in bytes. */ public int getMtu(); @@ -1589,31 +1726,65 @@ public String toString() { * @return true if INVITE has to be sent whitout SDP. */ public boolean isSdp200AckEnabled(); - + /** * Inconditionnaly disable incoming chat messages. * @param lc the core * @param deny_reason the deny reason (using ReasonNone has no effect). **/ public void disableChat(Reason denycode); - + /** * Enable reception of incoming chat messages. * By default it is enabled but it can be disabled with linphone_core_disable_chat(). * @param lc the core **/ public void enableChat(); - + /** * Returns whether chat is enabled. * @return true if chat is enabled, false otherwise. **/ public boolean chatEnabled(); - + /** - * Whenever the liblinphone is playing a ring to advertise an incoming call or ringback of an outgoing call, this function stops the ringing. + * Whenever the liblinphone is playing a ring to advertise an incoming call or ringback of an outgoing call, this function stops the ringing. * Typical use is to stop ringing when the user requests to ignore the call. **/ public void stopRinging(); + + /** + * Set audio jitter buffer size in milliseconds. + * A value of zero disables the jitter buffer. + * The new value is taken into account immediately for all running or pending calls. + * @param value the jitter buffer size in milliseconds. + */ + public void setAudioJittcomp(int value); + + /** + * Set video jitter buffer size in milliseconds. + * A value of zero disables the jitter buffer. + * The new value is taken into account immediately for all running or pending calls. + * @param value the jitter buffer size in milliseconds. + */ + public void setVideoJittcomp(int value); + + /** + * Globaly set an http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml. + * @param serverUrl URL of the file server like https://file.linphone.org/upload.php + */ + public void setFileTransferServer(String serverUrl); + + /** + * Get the globaly set http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml. + * @return the serverUrl + */ + public String getFileTransferServer(); + + /** + * Create a media player + * @return An object that implement LinphonePlayer + */ + public LinphonePlayer createLocalPlayer(AndroidVideoWindowImpl window); } diff --git a/java/common/org/linphone/core/LinphoneCoreFactory.java b/java/common/org/linphone/core/LinphoneCoreFactory.java index 5838594dc..a26f95b9a 100644 --- a/java/common/org/linphone/core/LinphoneCoreFactory.java +++ b/java/common/org/linphone/core/LinphoneCoreFactory.java @@ -104,12 +104,10 @@ public static final synchronized LinphoneCoreFactory instance() { abstract public LinphoneAddress createLinphoneAddress(String address) throws LinphoneCoreException; abstract public LpConfig createLpConfig(String file); - abstract public LinphoneProxyConfig createProxyConfig(String identity, String proxy,String route,boolean enableRegister) throws LinphoneCoreException; - /** * Enable verbose traces - * @param enable - * @param tag + * @param enable true to enable debug mode, false to disable it + * @param tag Tag which prefixes each log message. */ abstract public void setDebugMode(boolean enable, String tag); diff --git a/java/common/org/linphone/core/LinphoneCoreListener.java b/java/common/org/linphone/core/LinphoneCoreListener.java index bd83172a9..c82390c48 100644 --- a/java/common/org/linphone/core/LinphoneCoreListener.java +++ b/java/common/org/linphone/core/LinphoneCoreListener.java @@ -18,6 +18,8 @@ of the License, or (at your option) any later version. */ package org.linphone.core; +import java.nio.ByteBuffer; + import org.linphone.core.LinphoneCore.RemoteProvisioningState; @@ -188,6 +190,35 @@ void configuringStatus(LinphoneCore lc, RemoteProvisioningState state, /** @Deprecated Callback to display a warning to the user * @return */ void displayWarning(LinphoneCore lc,String message); - + + /** + * Callback to be notified about the transfer progress. + * @param lc the LinphoneCore + * @param message the LinphoneChatMessage + * @param content the LinphoneContent + * @param progress percentage of the transfer done + */ + void fileTransferProgressIndication(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, int progress); + + /** + * Callback to be notified when new data has been received + * @param lc the LinphoneCore + * @param message the LinphoneChatMessage + * @param content the LinphoneContent + * @param buffer + * @param size + */ + void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, byte[] buffer, int size); + + /** + * Callback to be notified when new data needs to be sent + * @param lc the LinphoneCore + * @param message the LinphoneChatMessage + * @param content the LinphoneContent + * @param buffer + * @param size + * @return the number of bytes written into buffer + */ + int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, ByteBuffer buffer, int size); } diff --git a/java/common/org/linphone/core/LinphonePlayer.java b/java/common/org/linphone/core/LinphonePlayer.java new file mode 100644 index 000000000..79d05dbb4 --- /dev/null +++ b/java/common/org/linphone/core/LinphonePlayer.java @@ -0,0 +1,95 @@ +/** + * Interface to manipulate different media players of Linphone + */ +package org.linphone.core; + +/** + * @author François Grisez + * + */ +public interface LinphonePlayer { + /** + * States that the player can be + * @author François Grisez + * + */ + public enum State { + closed, /*< No file is open */ + paused, /*< A file is open and playback is not running */ + playing; /*< A file is open and playback is running */ + + public static State fromValue(int value) { + if(value == 0) { + return closed; + } else if(value == 1) { + return paused; + } else if(value == 2) { + return playing; + } else { + return null; + } + } + }; + + /** + * Listener for Linphone players + * @author François Grisez + * + */ + public interface Listener { + /** + * Method called when a player reaches the end of a file + * @param player The player which called the method + */ + public void endOfFile(LinphonePlayer player); + } + + /** + * Open a file + * @param filename Name of the file to open + * @return 0 on success, -1 on failure + */ + public int open(String filename, Listener listener); + + /** + * Start playback + * @return 0 on success, -1 on failure + */ + public int start(); + + /** + * Get playback paused + * @return 0 on success, -1 on failure + */ + public int pause(); + + /** + * Go to a specific position in the timeline + * @param timeMs Time in milliseconds + * @return 0 on success, -1 on failure + */ + public int seek(int timeMs); + + /** + * Get the state of the player + * @return See State enumeration + */ + public State getState(); + + /** + * Get the duration of the media + * @return The duration in milliseconds + */ + public int getDuration(); + + /** + * Get the position of the playback + * @return The position in milliseconds + */ + public int getCurrentPosition(); + + /** + * Close a file + */ + public void close(); +} diff --git a/java/impl/org/linphone/core/LinphoneAuthInfoImpl.java b/java/impl/org/linphone/core/LinphoneAuthInfoImpl.java index 7d2b3dde2..8efdcc144 100644 --- a/java/impl/org/linphone/core/LinphoneAuthInfoImpl.java +++ b/java/impl/org/linphone/core/LinphoneAuthInfoImpl.java @@ -37,7 +37,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo { boolean ownPtr = false; protected LinphoneAuthInfoImpl(String username,String password, String realm, String domain) { - this(username, null, password, null, null, domain); + this(username, null, password, null, realm, domain); } protected LinphoneAuthInfoImpl(String username, String userid, String passwd, String ha1, String realm, String domain) { nativePtr = newLinphoneAuthInfo(); @@ -46,6 +46,7 @@ protected LinphoneAuthInfoImpl(String username, String userid, String passwd, St this.setPassword(passwd); this.setHa1(ha1); this.setDomain(domain); + this.setRealm(realm); ownPtr = true; } protected LinphoneAuthInfoImpl(long aNativePtr) { diff --git a/java/impl/org/linphone/core/LinphoneCallImpl.java b/java/impl/org/linphone/core/LinphoneCallImpl.java index ee78e9d89..b2cad202c 100644 --- a/java/impl/org/linphone/core/LinphoneCallImpl.java +++ b/java/impl/org/linphone/core/LinphoneCallImpl.java @@ -245,4 +245,10 @@ public void setUserData(Object obj) { public Object getUserData() { return userData; } + + private native long getPlayer(long callPtr); + @Override + public LinphonePlayer getPlayer() { + return new LinphonePlayerImpl(getPlayer(nativePtr)); + } } diff --git a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java index c48c8a5cc..d25ae426a 100644 --- a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java +++ b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java @@ -48,6 +48,12 @@ public LinphoneAddress getFrom() { return new LinphoneAddressImpl(getFrom(nativePtr),LinphoneAddressImpl.WrapMode.FromConst); } + private native long getTo(long ptr); + @Override + public LinphoneAddress getTo() { + return new LinphoneAddressImpl(getTo(nativePtr),LinphoneAddressImpl.WrapMode.FromConst); + } + private native void addCustomHeader(long nativePtr, String name, String value); @Override public void addCustomHeader(String name, String value) { @@ -93,7 +99,32 @@ public Reason getReason() { public ErrorInfo getErrorInfo() { return new ErrorInfoImpl(getErrorInfo(nativePtr)); } - protected void finalize(){ + protected void finalize() throws Throwable{ unref(nativePtr); + super.finalize(); + } + + private native void startFileDownload(long ptr, StateListener listener); + @Override + public void startFileDownload(StateListener listener) { + startFileDownload(nativePtr, listener); + } + + private native Object getFileTransferInformation(long ptr); + @Override + public LinphoneContent getFileTransferInformation() { + return (LinphoneContent) getFileTransferInformation(nativePtr); + } + + private native void setAppData(long ptr, String data); + @Override + public void setAppData(String data) { + setAppData(nativePtr, data); + } + + private native String getAppData(long ptr); + @Override + public String getAppData() { + return getAppData(nativePtr); } } diff --git a/java/impl/org/linphone/core/LinphoneChatRoomImpl.java b/java/impl/org/linphone/core/LinphoneChatRoomImpl.java index 8aa9c258d..d47e4e47e 100644 --- a/java/impl/org/linphone/core/LinphoneChatRoomImpl.java +++ b/java/impl/org/linphone/core/LinphoneChatRoomImpl.java @@ -27,9 +27,11 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom { private native long getPeerAddress(long ptr); private native void sendMessage(long ptr, String message); private native void sendMessage2(long ptr, Object msg, long messagePtr, StateListener listener); + private native long[] getHistoryRange(long ptr, int begin, int end); private native long[] getHistory(long ptr, int limit); private native void destroy(long ptr); private native int getUnreadMessagesCount(long ptr); + private native int getHistorySize(long ptr); private native void deleteHistory(long ptr); private native void compose(long ptr); private native boolean isRemoteComposing(long ptr); @@ -44,100 +46,106 @@ protected LinphoneChatRoomImpl(long aNativePtr) { 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 = getHistoryRange(nativePtr, begin, end); + return getHistoryPrivate(typesPtr); + } + } + + public LinphoneChatMessage[] getHistory(int limit) { 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; + return getHistoryPrivate(typesPtr); } } - - public synchronized void destroy() { + + public void destroy() { destroy(nativePtr); } - - public synchronized int getUnreadMessagesCount() { + + public int getUnreadMessagesCount() { synchronized(getCore()){ return getUnreadMessagesCount(nativePtr); } } - - public synchronized void deleteHistory() { + + public int getHistorySize() { + synchronized(getCore()){ + return getHistorySize(nativePtr); + } + } + + public void deleteHistory() { synchronized(getCore()){ deleteHistory(nativePtr); } } - public synchronized void compose() { + public void compose() { synchronized(getCore()){ compose(nativePtr); } } - public synchronized boolean isRemoteComposing() { + public boolean isRemoteComposing() { synchronized(getCore()){ return isRemoteComposing(nativePtr); } } - - public synchronized void markAsRead() { + + public void markAsRead() { synchronized(getCore()){ markAsRead(nativePtr); } } - - public synchronized void deleteMessage(LinphoneChatMessage message) { + + public void deleteMessage(LinphoneChatMessage message) { synchronized(getCore()){ if (message != null) deleteMessage(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr()); } } - - public synchronized void updateUrl(LinphoneChatMessage message) { + + public void updateUrl(LinphoneChatMessage message) { synchronized(getCore()){ if (message != null) updateUrl(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr()); } } - + @Override - public synchronized LinphoneChatMessage createLinphoneChatMessage(String message, + public LinphoneChatMessage createLinphoneChatMessage(String message, String url, State state, long timestamp, boolean isRead, boolean isIncoming) { synchronized(getCore()){ @@ -150,4 +158,30 @@ public synchronized LinphoneChatMessage createLinphoneChatMessage(String message public synchronized LinphoneCore getCore() { return (LinphoneCore)getCore(nativePtr); } + private LinphoneChatMessage[] getHistoryPrivate(long[] typesPtr) { + if (typesPtr == null) return null; + + LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length]; + for (int i=0; i < messages.length; i++) { + messages[i] = new LinphoneChatMessageImpl(typesPtr[i]); + } + + return messages; + } + + private native long createFileTransferMessage(long ptr, String name, String type, String subtype, int size); + @Override + public LinphoneChatMessage createFileTransferMessage(LinphoneContent content) { + synchronized(getCore()) { + return new LinphoneChatMessageImpl(createFileTransferMessage(nativePtr, content.getName(), content.getType(), content.getSubtype(), content.getRealSize())); + } + } + + private native void cancelFileTransfer(long ptr, long messagePtr); + @Override + public void cancelFileTransfer(LinphoneChatMessage message) { + synchronized(getCore()) { + cancelFileTransfer(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr()); + } + } } diff --git a/java/impl/org/linphone/core/LinphoneContentImpl.java b/java/impl/org/linphone/core/LinphoneContentImpl.java index b12e6580f..0231fd539 100644 --- a/java/impl/org/linphone/core/LinphoneContentImpl.java +++ b/java/impl/org/linphone/core/LinphoneContentImpl.java @@ -1,14 +1,26 @@ package org.linphone.core; public class LinphoneContentImpl implements LinphoneContent { - private String mType, mSubtype, mEncoding; + private String mType, mSubtype, mEncoding, mName; private byte[] mData; + private int mExpectedSize; - public LinphoneContentImpl(String type, String subtype, byte data[], String encoding ){ - mType=type; - mSubtype=subtype; - mData=data; - mEncoding=encoding; + public LinphoneContentImpl(String type, String subtype, byte data[], String encoding){ + mType = type; + mSubtype = subtype; + mData = data; + mEncoding = encoding; + mName = null; + mExpectedSize = 0; + } + + public LinphoneContentImpl(String name, String type, String subtype, byte data[], String encoding, int expectedSize){ + mType = type; + mSubtype = subtype; + mData = data; + mEncoding = encoding; + mName = name; + mExpectedSize = expectedSize; } @Override @@ -23,32 +35,49 @@ public String getSubtype() { @Override public String getDataAsString() { - return new String(mData); + if (mData != null) + return new String(mData); + return null; + } + + @Override + public void setExpectedSize(int size) { + mExpectedSize = size; } @Override - public int getSize() { - return mData.length; + public int getExpectedSize() { + return mExpectedSize; + } + + @Override + public int getRealSize() { + if (mData != null) + return mData.length; + return 0; } @Override public void setType(String type) { - mType=type; + mType = type; } @Override public void setSubtype(String subtype) { - mSubtype=subtype; + mSubtype = subtype; } @Override public void setStringData(String data) { - mData=data.getBytes(); + if (data != null) + mData = data.getBytes(); + else + mData = null; } @Override public void setData(byte data[]){ - mData=data; + mData = data; } @Override @@ -63,7 +92,16 @@ public byte[] getData() { @Override public void setEncoding(String encoding) { - mEncoding=encoding; + mEncoding = encoding; + } + + @Override + public void setName(String name) { + mName = name; } + @Override + public String getName() { + return mName; + } } diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java index 85bff8ffa..f0d3ae064 100644 --- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java @@ -108,12 +108,6 @@ public LinphoneCore createLinphoneCore(LinphoneCoreListener listener, Object con } } - @Override - public LinphoneProxyConfig createProxyConfig(String identity, String proxy, - String route, boolean enableRegister) throws LinphoneCoreException { - return new LinphoneProxyConfigImpl(identity,proxy,route,enableRegister); - } - @Override public native void setDebugMode(boolean enable, String tag); diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 04a679f1a..6e6f5a21f 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -25,6 +25,7 @@ of the License, or (at your option) any later version. import org.linphone.core.LinphoneCall.State; import org.linphone.mediastream.Log; +import org.linphone.mediastream.video.AndroidVideoWindowImpl; import org.linphone.mediastream.video.capture.hwconf.Hacks; import android.content.Context; @@ -34,19 +35,19 @@ of the License, or (at your option) any later version. class LinphoneCoreImpl implements LinphoneCore { private final LinphoneCoreListener mListener; //to make sure to keep a reference on this object - private long nativePtr = 0; + protected long nativePtr = 0; private Context mContext = null; private AudioManager mAudioManager = null; private boolean mSpeakerEnabled = false; private native long newLinphoneCore(LinphoneCoreListener listener,String userConfig,String factoryConfig,Object userdata); private native void iterate(long nativePtr); - private native long getDefaultProxyConfig(long nativePtr); + private native LinphoneProxyConfig getDefaultProxyConfig(long nativePtr); private native void setDefaultProxyConfig(long nativePtr,long proxyCfgNativePtr); private native int addProxyConfig(LinphoneProxyConfig jprtoxyCfg,long nativePtr,long proxyCfgNativePtr); private native void removeProxyConfig(long nativePtr, long proxyCfg); private native void clearAuthInfos(long nativePtr); - + private native void clearProxyConfigs(long nativePtr); private native void addAuthInfo(long nativePtr,long authInfoNativePtr); private native void removeAuthInfo(long nativePtr, long authInfoNativePtr); @@ -73,8 +74,11 @@ class LinphoneCoreImpl implements LinphoneCore { private native long findPayloadType(long nativePtr, String mime, int clockRate, int channels); private native int enablePayloadType(long nativePtr, long payloadType, boolean enable); private native boolean isPayloadTypeEnabled(long nativePtr, long payloadType); + private native boolean payloadTypeIsVbr(long nativePtr, long payloadType); private native void enableAdaptiveRateControl(long nativePtr,boolean enable); private native boolean isAdaptiveRateControlEnabled(long nativePtr); + private native String getAdaptiveRateAlgorithm(long nativePtr); + private native void setAdaptiveRateAlgorithm(long nativePtr, String alg); private native void enableEchoCancellation(long nativePtr,boolean enable); private native boolean isEchoCancellationEnabled(long nativePtr); private native Object getCurrentCall(long nativePtr) ; @@ -147,12 +151,12 @@ class LinphoneCoreImpl implements LinphoneCore { private native void setChatDatabasePath(long nativePtr, String path); private native long[] getChatRooms(long nativePtr); private native int migrateToMultiTransport(long nativePtr); - private native long createProxyConfig(long nativePtr); private native void setCallErrorTone(long nativePtr, int reason, String path); private native void enableSdp200Ack(long nativePtr,boolean enable); private native boolean isSdp200AckEnabled(long nativePtr); private native void stopRinging(long nativePtr); - + private native static void setAndroidPowerManager(Object pm); + LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig, File factoryConfig, Object userdata) throws IOException { mListener = listener; String user = userConfig == null ? null : userConfig.getCanonicalPath(); @@ -163,9 +167,9 @@ class LinphoneCoreImpl implements LinphoneCore { mListener = listener; nativePtr = newLinphoneCore(listener,null,null,null); } - + protected void finalize() throws Throwable { - + if (nativePtr!=0) destroy(); } private boolean contextInitialized() { @@ -178,6 +182,7 @@ private boolean contextInitialized() { public void setContext(Object context) { mContext = (Context)context; mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + setAndroidPowerManager(mContext.getSystemService(Context.POWER_SERVICE)); } public synchronized void addAuthInfo(LinphoneAuthInfo info) { @@ -192,12 +197,7 @@ public synchronized void removeAuthInfo(LinphoneAuthInfo info) { public synchronized LinphoneProxyConfig getDefaultProxyConfig() { isValid(); - long lNativePtr = getDefaultProxyConfig(nativePtr); - if (lNativePtr!=0) { - return new LinphoneProxyConfigImpl(this,lNativePtr); - } else { - return null; - } + return getDefaultProxyConfig(nativePtr); } public synchronized LinphoneCall invite(String uri) { @@ -225,8 +225,6 @@ public synchronized void addProxyConfig(LinphoneProxyConfig proxyCfg) throws Lin public synchronized void removeProxyConfig(LinphoneProxyConfig proxyCfg) { isValid(); removeProxyConfig(nativePtr, ((LinphoneProxyConfigImpl)proxyCfg).nativePtr); - ((LinphoneProxyConfigImpl)proxyCfg).mCore=null; - ((LinphoneProxyConfigImpl)proxyCfg).deleteNativePtr(); } public synchronized void clearAuthInfos() { isValid(); @@ -263,18 +261,17 @@ public synchronized void acceptCall(LinphoneCall aCall) { } public synchronized LinphoneCallLog[] getCallLogs() { isValid(); - LinphoneCallLog[] logs = new LinphoneCallLog[getNumberOfCallLogs(nativePtr)]; + LinphoneCallLog[] logs = new LinphoneCallLog[getNumberOfCallLogs(nativePtr)]; for (int i=0;i < getNumberOfCallLogs(nativePtr);i++) { logs[i] = new LinphoneCallLogImpl(getCallLog(nativePtr, i)); } return logs; } public synchronized void destroy() { - isValid(); delete(nativePtr); - nativePtr = 0; + nativePtr=0; } - + private void isValid() { if (nativePtr == 0) { throw new RuntimeException("object already destroyed"); @@ -285,7 +282,7 @@ public synchronized void setNetworkReachable(boolean isReachable) { } public synchronized void setPlaybackGain(float gain) { setPlaybackGain(nativePtr,gain); - + } public synchronized float getPlaybackGain() { return getPlaybackGain(nativePtr); @@ -302,7 +299,7 @@ public synchronized LinphoneAddress interpretUrl(String destination) throws Linp throw new LinphoneCoreException("Cannot interpret ["+destination+"]"); } } - public synchronized LinphoneCall invite(LinphoneAddress to) throws LinphoneCoreException { + public synchronized LinphoneCall invite(LinphoneAddress to) throws LinphoneCoreException { LinphoneCall call = (LinphoneCall)inviteAddress(nativePtr,((LinphoneAddressImpl)to).nativePtr); if (call!=null) { return call; @@ -335,12 +332,18 @@ public synchronized void enablePayloadType(PayloadType pt, boolean enable) if (enablePayloadType(nativePtr,((PayloadTypeImpl)pt).nativePtr,enable) != 0) { throw new LinphoneCoreException("cannot enable payload type ["+pt+"]"); } - + } public synchronized boolean isPayloadTypeEnabled(PayloadType pt) { isValid(); return isPayloadTypeEnabled(nativePtr, ((PayloadTypeImpl)pt).nativePtr); } + + public synchronized boolean payloadTypeIsVbr(PayloadType pt) { + isValid(); + return payloadTypeIsVbr(nativePtr, ((PayloadTypeImpl)pt).nativePtr); + } + public synchronized void enableEchoCancellation(boolean enable) { isValid(); enableEchoCancellation(nativePtr, enable); @@ -348,21 +351,21 @@ public synchronized void enableEchoCancellation(boolean enable) { public synchronized boolean isEchoCancellationEnabled() { isValid(); return isEchoCancellationEnabled(nativePtr); - + } public synchronized LinphoneCall getCurrentCall() { isValid(); return (LinphoneCall)getCurrentCall(nativePtr); } - + public int getPlayLevel() { // TODO Auto-generated method stub return 0; } public void setPlayLevel(int level) { // TODO Auto-generated method stub - + } private void applyAudioHacks() { @@ -398,20 +401,20 @@ public boolean isSpeakerEnabled() { } public synchronized void playDtmf(char number, int duration) { playDtmf(nativePtr,number, duration); - + } public synchronized void stopDtmf() { stopDtmf(nativePtr); } - + public synchronized void addFriend(LinphoneFriend lf) throws LinphoneCoreException { addFriend(nativePtr,((LinphoneFriendImpl)lf).nativePtr); - + } @SuppressWarnings("deprecation") public synchronized void setPresenceInfo(int minutes_away, String alternative_contact, OnlineStatus status) { setPresenceInfo(nativePtr,minutes_away,alternative_contact,status.mValue); - + } @SuppressWarnings("deprecation") public synchronized OnlineStatus getPresenceInfo() { @@ -435,7 +438,7 @@ public synchronized void setVideoWindow(Object w) { public synchronized void setDeviceRotation(int rotation) { setDeviceRotation(nativePtr, rotation); } - + public synchronized void enableVideo(boolean vcap_enabled, boolean display_enabled) { enableVideo(nativePtr,vcap_enabled, display_enabled); } @@ -457,15 +460,15 @@ public synchronized void setFirewallPolicy(FirewallPolicy pol) { public synchronized void setStunServer(String stunServer) { setStunServer(nativePtr,stunServer); } - + public synchronized LinphoneCallParams createDefaultCallParameters() { return new LinphoneCallParamsImpl(createDefaultCallParams(nativePtr)); } - + public synchronized LinphoneCall inviteAddressWithParams(LinphoneAddress to, LinphoneCallParams params) throws LinphoneCoreException { long ptrDestination = ((LinphoneAddressImpl)to).nativePtr; long ptrParams =((LinphoneCallParamsImpl)params).nativePtr; - + LinphoneCall call = (LinphoneCall)inviteAddressWithParams(nativePtr, ptrDestination, ptrParams); if (call!=null) { return call; @@ -510,19 +513,19 @@ public synchronized void setRing(String path) { public synchronized String getRing() { return getRing(nativePtr); } - + public synchronized void setRootCA(String path) { setRootCA(nativePtr, path); } - - public synchronized LinphoneProxyConfig[] getProxyConfigList() { + + public synchronized LinphoneProxyConfig[] getProxyConfigList() { return getProxyConfigList(nativePtr); } - + public synchronized PayloadType[] getVideoCodecs() { long[] typesPtr = listVideoPayloadTypes(nativePtr); if (typesPtr == null) return null; - + PayloadType[] codecs = new PayloadType[typesPtr.length]; for (int i=0; i < codecs.length; i++) { @@ -534,7 +537,7 @@ public synchronized PayloadType[] getVideoCodecs() { public synchronized PayloadType[] getAudioCodecs() { long[] typesPtr = listAudioPayloadTypes(nativePtr); if (typesPtr == null) return null; - + PayloadType[] codecs = new PayloadType[typesPtr.length]; for (int i=0; i < codecs.length; i++) { @@ -546,10 +549,10 @@ public synchronized PayloadType[] getAudioCodecs() { public synchronized boolean isNetworkReachable() { return isNetworkStateReachable(nativePtr); } - + public synchronized void enableKeepAlive(boolean enable) { enableKeepAlive(nativePtr,enable); - + } public synchronized boolean isKeepAliveEnabled() { return isKeepAliveEnabled(nativePtr); @@ -557,7 +560,7 @@ public synchronized boolean isKeepAliveEnabled() { public synchronized void startEchoCalibration(Object data) throws LinphoneCoreException { startEchoCalibration(nativePtr, data); } - + public synchronized Transports getSignalingTransportPorts() { Transports transports = new Transports(); transports.udp = getSignalingTransportPort(nativePtr, 0); @@ -592,7 +595,7 @@ public synchronized boolean pauseAllCalls() { } public synchronized void setDownloadPtime(int ptime) { setDownloadPtime(nativePtr,ptime); - + } public synchronized void setUploadPtime(int ptime) { setUploadPtime(nativePtr,ptime); @@ -615,12 +618,12 @@ public synchronized int getVideoDevice() { } - private native void leaveConference(long nativePtr); + private native void leaveConference(long nativePtr); public synchronized void leaveConference() { leaveConference(nativePtr); } - private native boolean enterConference(long nativePtr); + private native boolean enterConference(long nativePtr); public synchronized boolean enterConference() { return enterConference(nativePtr); } @@ -658,12 +661,12 @@ public synchronized LinphoneCall[] getCalls() { private native void addAllToConference(long nativePtr); public synchronized void addAllToConference() { addAllToConference(nativePtr); - + } private native void addToConference(long nativePtr, long nativePtrLcall); public synchronized void addToConference(LinphoneCall call) { addToConference(nativePtr, getCallPtr(call)); - + } private native void removeFromConference(long nativePtr, long nativeCallPtr); public synchronized void removeFromConference(LinphoneCall call) { @@ -673,7 +676,7 @@ public synchronized void removeFromConference(LinphoneCall call) { private long getCallPtr(LinphoneCall call) { return ((LinphoneCallImpl)call).nativePtr; } - + private long getCallParamsPtr(LinphoneCallParams callParams) { return ((LinphoneCallParamsImpl)callParams).nativePtr; } @@ -701,7 +704,7 @@ public synchronized boolean isMediaEncryptionMandatory() { return isMediaEncryptionMandatory(nativePtr); } public synchronized void setMediaEncryption(MediaEncryption menc) { - setMediaEncryption(nativePtr, menc.mValue); + setMediaEncryption(nativePtr, menc.mValue); } public synchronized void setMediaEncryptionMandatory(boolean yesno) { setMediaEncryptionMandatory(nativePtr, yesno); @@ -753,6 +756,18 @@ public synchronized void tunnelAddServerAndMirror(String host, int port, int mir tunnelAddServerAndMirror(nativePtr, host, port, mirror, ms); } + private native void tunnelAddServer(long nativePtr, TunnelConfig config); + @Override + public synchronized void tunnelAddServer(TunnelConfig config) { + tunnelAddServer(nativePtr, config); + } + + private native final TunnelConfig[] tunnelGetServers(long nativePtr); + @Override + public synchronized final TunnelConfig[] tunnelGetServers() { + return tunnelGetServers(nativePtr); + } + private native void tunnelAutoDetect(long nativePtr); @Override public synchronized void tunnelAutoDetect() { @@ -770,10 +785,34 @@ public synchronized void tunnelCleanServers() { public synchronized void tunnelEnable(boolean enable) { tunnelEnable(nativePtr, enable); } + + private native void tunnelSetMode(long nativePtr, int mode); + @Override + public synchronized void tunnelSetMode(LinphoneCore.TunnelMode mode) { + tunnelSetMode(nativePtr, TunnelMode.enumToInt(mode)); + } + + private native int tunnelGetMode(long nativePtr); + @Override + public synchronized LinphoneCore.TunnelMode tunnelGetMode() { + return LinphoneCore.TunnelMode.intToEnum(tunnelGetMode(nativePtr)); + } + + private native void tunnelEnableSip(long nativePtr, boolean enable); + @Override + public void tunnelEnableSip(boolean enable) { + tunnelEnableSip(nativePtr, enable); + } + + private native boolean tunnelSipEnabled(long nativePtr); + @Override + public boolean tunnelSipEnabled() { + return tunnelSipEnabled(nativePtr); + } @Override public native boolean isTunnelAvailable(); - + private native void acceptCallWithParams(long nativePtr, long aCall, long params); @Override @@ -781,14 +820,14 @@ public synchronized void acceptCallWithParams(LinphoneCall aCall, LinphoneCallParams params) throws LinphoneCoreException { acceptCallWithParams(nativePtr, getCallPtr(aCall), getCallParamsPtr(params)); } - + private native void acceptCallUpdate(long nativePtr, long aCall, long params); @Override public synchronized void acceptCallUpdate(LinphoneCall aCall, LinphoneCallParams params) throws LinphoneCoreException { - acceptCallUpdate(nativePtr, getCallPtr(aCall), getCallParamsPtr(params)); + acceptCallUpdate(nativePtr, getCallPtr(aCall), getCallParamsPtr(params)); } - + private native void deferCallUpdate(long nativePtr, long aCall); @Override public synchronized void deferCallUpdate(LinphoneCall aCall) @@ -796,7 +835,7 @@ public synchronized void deferCallUpdate(LinphoneCall aCall) deferCallUpdate(nativePtr, getCallPtr(aCall)); } - + private native void setVideoPolicy(long nativePtr, boolean autoInitiate, boolean autoAccept); public synchronized void setVideoPolicy(boolean autoInitiate, boolean autoAccept) { setVideoPolicy(nativePtr, autoInitiate, autoAccept); @@ -809,7 +848,7 @@ public synchronized boolean getVideoAutoInitiatePolicy() { public synchronized boolean getVideoAutoAcceptPolicy() { return getVideoAutoAcceptPolicy(nativePtr); } - + private native void setStaticPicture(long nativePtr, String path); public synchronized void setStaticPicture(String path) { setStaticPicture(nativePtr, path); @@ -825,11 +864,11 @@ public synchronized void setCpuCount(int count) { setCpuCountNative(count); } - + public synchronized int getMissedCallsCount() { return getMissedCallsCount(nativePtr); } - + public synchronized void removeCallLog(LinphoneCallLog log) { removeCallLog(nativePtr, ((LinphoneCallLogImpl) log).getNativePtr()); } @@ -837,7 +876,7 @@ public synchronized void removeCallLog(LinphoneCallLog log) { public synchronized void resetMissedCallsCount() { resetMissedCallsCount(nativePtr); } - + private native void tunnelSetHttpProxy(long nativePtr, String proxy_host, int port, String username, String password); @Override @@ -845,12 +884,12 @@ public synchronized void tunnelSetHttpProxy(String proxy_host, int port, String username, String password) { tunnelSetHttpProxy(nativePtr, proxy_host, port, username, password); } - + private native void refreshRegisters(long nativePtr); public synchronized void refreshRegisters() { refreshRegisters(nativePtr); } - + @Override public String getVersion() { return getVersion(nativePtr); @@ -867,13 +906,13 @@ public String getVersion() { public synchronized PayloadType findPayloadType(String mime, int clockRate) { return findPayloadType(mime, clockRate, FIND_PAYLOAD_IGNORE_CHANNELS); } - + private native void removeFriend(long ptr, long lf); @Override public synchronized void removeFriend(LinphoneFriend lf) { removeFriend(nativePtr, lf.getNativePtr()); } - + private native long getFriendByAddress(long ptr, String sipUri); @Override public synchronized LinphoneFriend findFriendByAddress(String sipUri) { @@ -883,64 +922,64 @@ public synchronized LinphoneFriend findFriendByAddress(String sipUri) { } return new LinphoneFriendImpl(ptr); } - + public synchronized void setAudioPort(int port) { setAudioPort(nativePtr, port); } - + public synchronized void setVideoPort(int port) { setVideoPort(nativePtr, port); } - + public synchronized void setAudioPortRange(int minPort, int maxPort) { setAudioPortRange(nativePtr, minPort, maxPort); } - + public synchronized void setVideoPortRange(int minPort, int maxPort) { setVideoPortRange(nativePtr, minPort, maxPort); } - + public synchronized void setIncomingTimeout(int timeout) { setIncomingTimeout(nativePtr, timeout); } - + public synchronized void setInCallTimeout(int timeout) { setInCallTimeout(nativePtr, timeout); } - + private native void setMicrophoneGain(long ptr, float gain); public synchronized void setMicrophoneGain(float gain) { setMicrophoneGain(nativePtr, gain); } - + public synchronized void setPrimaryContact(String displayName, String username) { setPrimaryContact(nativePtr, displayName, username); } - + public synchronized String getPrimaryContactUsername() { return getPrimaryContactUsername(nativePtr); } - + public synchronized String getPrimaryContactDisplayName() { return getPrimaryContactDisplayName(nativePtr); } - + private native void setUseSipInfoForDtmfs(long ptr, boolean use); public synchronized void setUseSipInfoForDtmfs(boolean use) { setUseSipInfoForDtmfs(nativePtr, use); } - + private native boolean getUseSipInfoForDtmfs(long ptr); public synchronized boolean getUseSipInfoForDtmfs() { return getUseSipInfoForDtmfs(nativePtr); } - + private native void setUseRfc2833ForDtmfs(long ptr, boolean use); public synchronized void setUseRfc2833ForDtmfs(boolean use) { setUseRfc2833ForDtmfs(nativePtr, use); } - + private native boolean getUseRfc2833ForDtmfs(long ptr); public synchronized boolean getUseRfc2833ForDtmfs() { return getUseRfc2833ForDtmfs(nativePtr); @@ -961,17 +1000,17 @@ public synchronized boolean needsEchoCalibration() { public synchronized void declineCall(LinphoneCall aCall, Reason reason) { declineCall(nativePtr,((LinphoneCallImpl)aCall).nativePtr,reason.mValue); } - + private native boolean upnpAvailable(long ptr); public synchronized boolean upnpAvailable() { return upnpAvailable(nativePtr); - } + } private native int getUpnpState(long ptr); public synchronized UpnpState getUpnpState() { - return UpnpState.fromInt(getUpnpState(nativePtr)); + return UpnpState.fromInt(getUpnpState(nativePtr)); } - + private native String getUpnpExternalIpaddress(long ptr); public synchronized String getUpnpExternalIpaddress() { return getUpnpExternalIpaddress(nativePtr); @@ -981,7 +1020,7 @@ public synchronized String getUpnpExternalIpaddress() { public synchronized void startConferenceRecording(String path) { startConferenceRecording(nativePtr,path); } - + private native int stopConferenceRecording(long nativePtr); @Override public synchronized void stopConferenceRecording() { @@ -991,13 +1030,13 @@ public synchronized void stopConferenceRecording() { public synchronized PayloadType findPayloadType(String mime) { return findPayloadType(mime, FIND_PAYLOAD_IGNORE_RATE); } - + private native void setSipDscp(long nativePtr, int dscp); @Override public synchronized void setSipDscp(int dscp) { setSipDscp(nativePtr,dscp); } - + private native int getSipDscp(long nativePtr); @Override public synchronized int getSipDscp() { @@ -1008,36 +1047,36 @@ public synchronized int getSipDscp() { public synchronized void setAudioDscp(int dscp) { setAudioDscp(nativePtr, dscp); } - + private native int getAudioDscp(long nativePtr); @Override public synchronized int getAudioDscp() { return getAudioDscp(nativePtr); } - + private native void setVideoDscp(long nativePtr, int dscp); @Override public synchronized void setVideoDscp(int dscp) { setVideoDscp(nativePtr,dscp); } - + private native int getVideoDscp(long nativePtr); @Override public synchronized int getVideoDscp() { return getVideoDscp(nativePtr); } - + private native long createInfoMessage(long nativeptr); @Override public synchronized LinphoneInfoMessage createInfoMessage() { return new LinphoneInfoMessageImpl(createInfoMessage(nativePtr)); } - + private native Object subscribe(long coreptr, long addrptr, String eventname, int expires, String type, String subtype, byte data [], String encoding); @Override public synchronized LinphoneEvent subscribe(LinphoneAddress resource, String eventname, int expires, LinphoneContent content) { - return (LinphoneEvent)subscribe(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, + return (LinphoneEvent)subscribe(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getData() : null, content!=null ? content.getEncoding() : null); } @@ -1045,7 +1084,7 @@ public synchronized LinphoneEvent subscribe(LinphoneAddress resource, String eve @Override public synchronized LinphoneEvent publish(LinphoneAddress resource, String eventname, int expires, LinphoneContent content) { - return (LinphoneEvent)publish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, + return (LinphoneEvent)publish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getData() : null, content!=null ? content.getEncoding() : null); } @@ -1062,15 +1101,15 @@ public synchronized LinphoneEvent createPublish(LinphoneAddress resource, String event, int expires) { return (LinphoneEvent)createPublish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, event, expires); } - + public synchronized void setChatDatabasePath(String path) { setChatDatabasePath(nativePtr, path); } - + public synchronized LinphoneChatRoom[] getChatRooms() { long[] typesPtr = getChatRooms(nativePtr); if (typesPtr == null) return null; - + LinphoneChatRoom[] proxies = new LinphoneChatRoom[typesPtr.length]; for (int i=0; i < proxies.length; i++) { @@ -1082,7 +1121,7 @@ public synchronized LinphoneChatRoom[] getChatRooms() { public synchronized LinphoneAuthInfo[] getAuthInfosList() { long[] typesPtr = getAuthInfosList(nativePtr); if (typesPtr == null) return null; - + LinphoneAuthInfo[] authInfos = new LinphoneAuthInfo[typesPtr.length]; for (int i=0; i < authInfos.length; i++) { @@ -1091,12 +1130,12 @@ public synchronized LinphoneAuthInfo[] getAuthInfosList() { return authInfos; } - + public synchronized LinphoneAuthInfo findAuthInfo(String username, String realm, String domain) { long ptr = findAuthInfos(nativePtr, username, realm, domain); if (ptr == 0) return null; - + return new LinphoneAuthInfoImpl(ptr); } private native LinphoneCall startReferedCall(long corePtr, long callptr, long paramsPtr); @@ -1106,7 +1145,7 @@ public synchronized LinphoneCall startReferedCall(LinphoneCall call, long ptrParams =((LinphoneCallParamsImpl)params).nativePtr; return startReferedCall(nativePtr, getCallPtr(call), ptrParams); } - + private native String[] listSupportedVideoResolutions(long ptr); @Override public synchronized String[] getSupportedVideoSizes() { @@ -1117,13 +1156,13 @@ public synchronized String[] getSupportedVideoSizes() { public synchronized int migrateToMultiTransport() { return migrateToMultiTransport(nativePtr); } - + private native boolean acceptEarlyMedia(long lc, long call); @Override public synchronized boolean acceptEarlyMedia(LinphoneCall call) { return acceptEarlyMedia(nativePtr, getCallPtr(call)); } - + private native boolean acceptEarlyMediaWithParams(long lc, long call, long params); @Override public synchronized boolean acceptEarlyMediaWithParams(LinphoneCall call, @@ -1133,7 +1172,16 @@ public synchronized boolean acceptEarlyMediaWithParams(LinphoneCall call, } @Override public synchronized LinphoneProxyConfig createProxyConfig() { - return new LinphoneProxyConfigImpl(this,createProxyConfig(nativePtr)); + return new LinphoneProxyConfigImpl(this); + } + @Override + public synchronized LinphoneProxyConfig createProxyConfig(String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException { + isValid(); + try { + return new LinphoneProxyConfigImpl(this,identity,proxy,route,enableRegister); + } catch(LinphoneCoreException e){ + return null; + } } @Override public synchronized void setCallErrorTone(Reason reason, String path) { @@ -1177,7 +1225,7 @@ public synchronized void enableChat() { public synchronized boolean chatEnabled() { return chatEnabled(nativePtr); } - + @Override public synchronized void stopRinging() { stopRinging(nativePtr); @@ -1193,13 +1241,53 @@ public synchronized int getPayloadTypeBitrate(PayloadType pt) { return getPayloadTypeBitrate(nativePtr, ((PayloadTypeImpl)pt).nativePtr); } @Override - public void enableAdaptiveRateControl(boolean enable) { + public synchronized void enableAdaptiveRateControl(boolean enable) { enableAdaptiveRateControl(nativePtr,enable); - + } @Override - public boolean isAdaptiveRateControlEnabled() { + public synchronized boolean isAdaptiveRateControlEnabled() { return isAdaptiveRateControlEnabled(nativePtr); } + public synchronized AdaptiveRateAlgorithm getAdaptiveRateAlgorithm() { + return AdaptiveRateAlgorithm.fromString(getAdaptiveRateAlgorithm(nativePtr)); + } + public synchronized void setAdaptiveRateAlgorithm(AdaptiveRateAlgorithm alg) { + setAdaptiveRateAlgorithm(nativePtr, alg.toString()); + } + + + private native void setAudioJittcomp(long ptr, int value); + @Override + public synchronized void setAudioJittcomp(int value) { + setAudioJittcomp(nativePtr,value); + } + private native void setVideoJittcomp(long ptr, int value); + @Override + public synchronized void setVideoJittcomp(int value) { + setVideoJittcomp(nativePtr,value); + } + private native void setFileTransferServer(long ptr, String serverUrl); + @Override + public synchronized void setFileTransferServer(String serverUrl) { + setFileTransferServer(nativePtr, serverUrl); + } + + private native String getFileTransferServer(long ptr); + @Override + public synchronized String getFileTransferServer() { + return getFileTransferServer(nativePtr); + } + + private native long createLocalPlayer(long nativePtr, AndroidVideoWindowImpl window); + @Override + public synchronized LinphonePlayer createLocalPlayer(AndroidVideoWindowImpl window) { + long playerPtr = createLocalPlayer(nativePtr, window); + if(playerPtr != 0) { + return new LinphonePlayerImpl(playerPtr); + } else { + return null; + } + } } diff --git a/java/impl/org/linphone/core/LinphoneEventImpl.java b/java/impl/org/linphone/core/LinphoneEventImpl.java index ca9c2151c..c78b5da40 100644 --- a/java/impl/org/linphone/core/LinphoneEventImpl.java +++ b/java/impl/org/linphone/core/LinphoneEventImpl.java @@ -33,7 +33,7 @@ public synchronized void denySubscription(Reason reason) { 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 synchronized void notify(LinphoneContent content) { 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 synchronized void updateSubscribe(LinphoneContent content) { 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 synchronized void updatePublish(LinphoneContent content) { private native int terminate(long nativePtr); @Override - public synchronized void terminate() { + public void terminate() { synchronized(getCore()){ terminate(mNativePtr); } @@ -115,7 +115,7 @@ public synchronized String getCustomHeader(String name) { 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 synchronized void sendSubscribe(LinphoneContent body) { private native void sendPublish(long ptr, String type, String subtype, byte data [], String encoding); @Override - public synchronized void sendPublish(LinphoneContent body) { + public void sendPublish(LinphoneContent body) { synchronized(getCore()){ if (body != null) sendPublish(mNativePtr, body.getType(), body.getSubtype(), body.getData(), body.getEncoding()); diff --git a/java/impl/org/linphone/core/LinphonePlayerImpl.java b/java/impl/org/linphone/core/LinphonePlayerImpl.java new file mode 100644 index 000000000..fe486321e --- /dev/null +++ b/java/impl/org/linphone/core/LinphonePlayerImpl.java @@ -0,0 +1,70 @@ +/** + * + */ +package org.linphone.core; + +/** + * @author François Grisez + * + */ +public class LinphonePlayerImpl implements LinphonePlayer { + private long nativePtr = 0; + + LinphonePlayerImpl(long nativePtr) { + this.nativePtr = nativePtr; + } + + private native int open(long nativePtr, String filename, Listener listener); + @Override + public synchronized int open(String filename, Listener listener) { + return open(nativePtr, filename, listener); + } + + private native int start(long nativePtr); + @Override + public synchronized int start() { + return start(nativePtr); + } + + private native int pause(long nativePtr); + @Override + public synchronized int pause() { + return pause(nativePtr); + } + + private native int seek(long nativePtr, int timeMs); + @Override + public synchronized int seek(int timeMs) { + return seek(nativePtr, timeMs); + } + + private native int getState(long nativePtr); + @Override + public synchronized State getState() { + return LinphonePlayer.State.fromValue(getState(nativePtr)); + } + + private native int getDuration(long nativePtr); + @Override + public synchronized int getDuration() { + return getDuration(nativePtr); + } + + private native int getCurrentPosition(long nativePtr); + @Override + public synchronized int getCurrentPosition() { + return getCurrentPosition(nativePtr); + } + + private native void close(long nativePtr); + @Override + public synchronized void close() { + close(nativePtr); + } + + private native void destroy(long nativePtr); + @Override + protected void finalize() { + destroy(nativePtr); + } +} diff --git a/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java b/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java index 5113f958c..f08980190 100644 --- a/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java +++ b/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java @@ -22,32 +22,33 @@ of the License, or (at your option) any later version. class LinphoneProxyConfigImpl implements LinphoneProxyConfig { - protected long nativePtr; + protected final long nativePtr; protected LinphoneCoreImpl mCore; Object userData; + + private native void finalize(long ptr); private native int getState(long nativePtr); private native void setExpires(long nativePtr, int delay); private native int getExpires(long nativePtr); + private native long createProxyConfig( long nativePtr); - boolean ownPtr = false; - protected LinphoneProxyConfigImpl(String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException { - nativePtr = newLinphoneProxyConfig(); + protected LinphoneProxyConfigImpl(LinphoneCoreImpl core,String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException { + mCore=core; + nativePtr = createProxyConfig(core.nativePtr); setIdentity(identity); setProxy(proxy); setRoute(route); enableRegister(enableRegister); - ownPtr=true; } - protected LinphoneProxyConfigImpl(LinphoneCoreImpl core,long aNativePtr) { + protected LinphoneProxyConfigImpl(LinphoneCoreImpl core) { mCore=core; - nativePtr = aNativePtr; - ownPtr=false; + nativePtr = createProxyConfig(core.nativePtr); } - - protected LinphoneProxyConfigImpl(long aNativePtr) { + /*reserved for JNI */ + protected LinphoneProxyConfigImpl(LinphoneCoreImpl core, long aNativePtr) { + mCore=core; nativePtr = aNativePtr; - ownPtr=false; } private void isValid() { @@ -56,16 +57,13 @@ private void isValid() { } } - public void deleteNativePtr() { - nativePtr=0; - } - protected void finalize() throws Throwable { - //Log.e(LinphoneService.TAG,"fixme, should release underlying proxy config"); - if (ownPtr) delete(nativePtr); + if (nativePtr != 0) { + finalize(nativePtr); + } + super.finalize(); } private native long newLinphoneProxyConfig(); - private native void delete(long ptr); private native void edit(long ptr); private native void done(long ptr); diff --git a/java/impl/org/linphone/core/TunnelConfig.java b/java/impl/org/linphone/core/TunnelConfig.java new file mode 100644 index 000000000..9801f0fbd --- /dev/null +++ b/java/impl/org/linphone/core/TunnelConfig.java @@ -0,0 +1,40 @@ +package org.linphone.core; + +public class TunnelConfig { + private String host = null; + private int port = 443; + private int remoteUdpMirrorPort = 12345; + private int delay = 1000; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public int getRemoteUdpMirrorPort() { + return remoteUdpMirrorPort; + } + + public void setRemoteUdpMirrorPort(int remoteUdpMirrorPort) { + this.remoteUdpMirrorPort = remoteUdpMirrorPort; + } + + public int getDelay() { + return delay; + } + + public void setDelay(int delay) { + this.delay = delay; + } +} diff --git a/mediastreamer2 b/mediastreamer2 index 4064390b4..cefa09edf 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 4064390b48c957dcf3077b0e30e0c082395bbf05 +Subproject commit cefa09edff80c2a1eacbee523979beaa763a21e9 diff --git a/oRTP b/oRTP index fc8d8457e..90a19604d 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit fc8d8457eb630907eff50333ddf5243b448fe733 +Subproject commit 90a19604d061d7f23189feb925847e66d366898e diff --git a/po/cs.po b/po/cs.po index 048bb9624..78c993c32 100644 --- a/po/cs.po +++ b/po/cs.po @@ -18,7 +18,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone-3.5.99.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-05-01 09:55+0200\n" "Last-Translator: Petr Pisar \n" "Language-Team: Czech \n" @@ -28,12 +28,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Volat komu: %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Poslat text komu: %s" @@ -43,23 +43,23 @@ msgstr "Poslat text komu: %s" msgid "Recent calls (%i)" msgstr "Nedávné hovory (%i)" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "–" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "Přerušen" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "Zmeškán" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "Odmítnut" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" @@ -67,7 +67,7 @@ msgstr[0] "%i minuta" msgstr[1] "%i minuty" msgstr[2] "%i minut" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" @@ -75,12 +75,12 @@ msgstr[0] "%i sekunda" msgstr[1] "%i sekundy" msgstr[2] "%i sekund" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "%s\t%s" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" @@ -89,7 +89,7 @@ msgstr "" "%s\tKvalita: %s\n" "%s\t%s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -111,7 +111,7 @@ msgstr "Já" msgid "Couldn't find pixmap file: %s" msgstr "Nelze najít soubor s obrázkem: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Neplatný sipový kontakt!" @@ -162,7 +162,7 @@ msgstr "Průvodce nastavením účtu" msgid "Call with %s" msgstr "Hovor s %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -175,7 +175,7 @@ msgstr "" "do svého adresáře?\n" "Odpovíte-li ne, tato osobo bude dočasně blokována." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -184,59 +184,59 @@ msgstr "" "Prosím, zadejte heslo pro uživatele %s\n" "v doméně %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Chyba hovoru" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Hovor ukončen" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Příchozí hovor" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Odpovědět" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Odmítnout" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Hovor odložen" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "kým: %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "%s navrhuje začít videohovor. Přijímáte?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Odkaz na webovou stránku" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Lipnhone – internetový videofon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Výchozí)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Byly jsme přepojeni na %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -244,7 +244,7 @@ msgstr "" "Na tomto počítači nebyla objevena žádná zvuková karta.\n" "Nebudete moci vytáčet a přijímat a zvukové hovory." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Volný SIP videofon" @@ -256,7 +256,7 @@ msgstr "Přidat do adresáře" msgid "Presence status" msgstr "Stav" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Jméno" @@ -273,142 +273,142 @@ msgstr "Diskuze" msgid "Search in %s directory" msgstr "Hledat v adresáři %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Upravit kontakt „%s“" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Odstranit kontakt „%s“" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "Odstranit historii diskuze u kontaktu „%s“" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Přidat nový kontakt z adresáře %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Kmitočet (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Stav" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min. rychlost (kb/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametry" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Povoleno" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Zakázáno" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Účet" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "angličtina" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "francouzština" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "švédština" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "italština" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "španělština" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "brazilská portugalština" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "polština" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "němčina" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "ruština" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "japonština" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "dánština" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "maďarština" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "čeština" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "čínština" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "tradiční čínština" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "norština" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "hebrejština" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "srbština" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Aby se projevil výběr nového jazyka, je nutné znovu spustit linphone." # Media encryption type: -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Žádné" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "SRTP" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ZRTP" @@ -481,55 +481,59 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "Zadejte uživatelské jméno na linphone.org" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Uživatelské jméno:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Heslo:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "Zadejte údaje o vašem účtu" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Uživatelské jméno*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Heslo*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Doména*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "Proxy" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) Povinné položky" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Uživatelské jméno: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Heslo: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "E-mail: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Potvrďte heslo: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -538,11 +542,11 @@ msgstr "" "není dostupný).\n" "Prosím, vraťte se a zkoste to znovu." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Děkujeme vám. Váš účet je nyní nastaven a připraven k použití." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -552,40 +556,40 @@ msgstr "" "zaslali e-mailem.\n" "Pak se sem vraťte a stiskněte tlačítko Další." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Průvodce nastavením účtu" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Vítejte v průvodci nastavení účtu" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Průvodce nastavením účtu" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "Nastavit účet (krok 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "Zadejte vaše sipové uživatelské jméno (krok 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "Zadejte údaje o účtu (krok 1/2)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "Ověření (krok 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Chyba" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "Ukončuje se" @@ -651,7 +655,7 @@ msgstr "UPnP selhalo" msgid "Direct or through server" msgstr "Přímé nebo skrze server" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" @@ -660,115 +664,115 @@ msgstr "" "příchozí: %f\n" "odchozí: %f (kb/s)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "%.3f sekund" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "Zavěsit" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Volá se…" -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00:00:00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Příchozí hovor" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "dobrá" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "průměrná" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "slabá" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "velmi slabá" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "příliš špatná" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "nedostupná" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Zabezpečeno pomocí SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Zabezpečeno pomocí ZRTP – [ověřovací klíč: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Nastavit na neověřeno" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Nastavit na ověřeno" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "Probíhá konference" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "Probíhá hovor" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Odložený hovor" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i:%02i:%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Hovor skončil." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "Probíhá přepojení" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "Přepojení dokončeno." -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "Přepojení selhalo." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Obnovit" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Odložit" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" @@ -777,7 +781,7 @@ msgstr "" "Nahrává se do\n" "%s %s" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "(Odloženo)" @@ -812,7 +816,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -821,60 +825,60 @@ msgstr "" "Vítejte!\n" "Tento průvodce vám pomůže používat sipový účet při vašich hovorech." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Zařízení pro nahrávání:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Zdroj nahrávání:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Zařízení pro přehrávání:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Průvodce" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Průvodce účtem" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1820,96 +1824,65 @@ msgstr "Připojuje se…" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "přerušen" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "dokončen" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "promeškán" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s v %s\n" -"Od: %s\n" -"Pro: %s\n" -"Stav: %s\n" -"Délka: %i min %i s\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Odchozí hovor" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Připraven." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Potvrzení" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Vyhledává se umístění čísla…" -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Toto číslo nelze vyhledat." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Navazuje se spojení" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Nelze volat" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Je nám líto, ale byl dosažen maximální počet současných hovorů." -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "vás volá" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " a požaduje automatickou zvednutí." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Upravují se parametry hovoru…" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Připojeno." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Hovor přerušen" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Hovor nebylo možné odložit" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Současný hovor se odkládá…" @@ -1974,7 +1947,7 @@ msgstr "Délka" msgid "Unknown-bug" msgstr "Neznámá chyba" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1982,7 +1955,7 @@ msgstr "" "Adresa SIP proxy, kterou jste zadali, není platná. Musí začínat na „sip:“ a " "pak musí následovat jméno stroje." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1990,124 +1963,124 @@ msgstr "" "SIP identita, kterou jste zadali, není platná.\n" "Měla by mít tvar sip:uživatel@proxydoména, například sip:alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Nelze se přihlásit jako %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Vyzvání na druhé straně." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Vyzvání na druhé straně…" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Časná média." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "Hovor s %s je odložen." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Hovor přijat kým: %s – odložen." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Hovor obnoven." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "Hovor přijat kým: %s." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "Není slučitelné. Zkontrolujte nastavení kodeků a zabezpečení…" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "Byli jsme obnoveni." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "Byli jsme odloženi protistranou." -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "Hovor byl aktualizován protistranou." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Hovor ukončen." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Uživatel je zaneprázdněn." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Uživatel je dočasně nedostupný." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Uživatel si nepřeje být rušen." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Volání odmítnuto." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Přesměrováno" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "Neslučitelné parametry médií." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Volání se nezdařilo." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrace na %s byla úspěšná." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Odregistrování z %s hotovo." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "odpověď nedorazila včas" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrace na %s selhala: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Klíč k ověření totožnosti je %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." @@ -2115,6 +2088,31 @@ msgstr[0] "Máte %i zmeškaný hovor." msgstr[1] "Máte %i zmeškané hovory." msgstr[2] "Máte %i zmeškaných hovorů." +#~ msgid "aborted" +#~ msgstr "přerušen" + +#~ msgid "completed" +#~ msgstr "dokončen" + +#~ msgid "missed" +#~ msgstr "promeškán" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s v %s\n" +#~ "Od: %s\n" +#~ "Pro: %s\n" +#~ "Stav: %s\n" +#~ "Délka: %i min %i s\n" + +#~ msgid "Outgoing call" +#~ msgstr "Odchozí hovor" + #~ msgid "No response." #~ msgstr "Žádná odpověď." diff --git a/po/de.po b/po/de.po index baec9ff8d..81e18df10 100644 --- a/po/de.po +++ b/po/de.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 0.7.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2012-11-07 19:27+0100\n" "Last-Translator: Gerhard Stengel \n" "Language-Team: German \n" @@ -17,12 +17,12 @@ msgstr "" "X-Generator: Lokalize 1.5\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "„%s“ anrufen" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Text zu „%s“ schicken" @@ -32,42 +32,42 @@ msgstr "Text zu „%s“ schicken" msgid "Recent calls (%i)" msgstr "Im Gespräch" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "nicht verfügbar" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "Abgebrochen" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "Entgangen" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "Abgewiesen" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i Minute" msgstr[1] "%i Minuten" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "%i Sekunde" msgstr[1] "%i Sekunden" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, fuzzy, c-format msgid "" "%s\tQuality: %s\n" @@ -76,7 +76,7 @@ msgstr "" "%s\t%s\tQualität: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -96,7 +96,7 @@ msgstr "Eigenes Telefon" msgid "Couldn't find pixmap file: %s" msgstr "Pixmapdatei %s kann nicht gefunden werden." -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Ungültiger SIP-Kontakt!" @@ -149,7 +149,7 @@ msgstr "Konto-Einrichtungsassistent" msgid "Call with %s" msgstr "Im Gespräch mit %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -162,7 +162,7 @@ msgstr "" "Ihrer Kontaktliste hinzufügen?\n" "Wenn Sie mit Nein antworten, wird diese Person vorläufig blockiert." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -171,59 +171,59 @@ msgstr "" "Geben Sie bitte Ihr Passwort für den Benutzernamen %s\n" " auf der Domäne %s ein:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Anruf fehlgeschlagen" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Anruf beendet" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Eingehender Anruf" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Annehmen" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Abweisen" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Anruf wird gehalten" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "von %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "%s schlägt vor, eine Videoübertragung zu starten. Nehmen Sie an?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Website-Verknüpfung" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - ein Internet-Video-Telefon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Vorgabe)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Vermittlung nach %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -231,7 +231,7 @@ msgstr "" "Auf diesem Rechner können keine Soundkarten gefunden werden.\n" "Sie können keine Audio-Anrufe tätigen oder entgegennehmen." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Ein freies SIP-Video-Telefon" @@ -243,7 +243,7 @@ msgstr "Zum Adressbuch hinzufügen" msgid "Presence status" msgstr "Anwesenheitsstatus" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Name" @@ -261,143 +261,143 @@ msgstr "Chat Raum" msgid "Search in %s directory" msgstr "Im %s-Verzeichnis suchen" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Kontakt „%s“ bearbeiten" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Kontakt „%s“ löschen" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Kontakt „%s“ löschen" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Einen neuen Kontakt aus dem %s-Verzeichnis hinzufügen" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Rate (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min. Bitrate (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parameter" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Freigegeben" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Gesperrt" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Konto" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Englisch" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Französisch" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Schwedisch" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italienisch" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Spanisch" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Brasilianisches Portugiesisch" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polnisch" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Deutsch" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Russisch" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Japanisch" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Niederländisch" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Ungarisch" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Tschechisch" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Chinesisch" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Traditionelles Chinesisch" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Norwegisch" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" "Linphone muss neu gestartet werden, damit die neue Spracheinstellung wirksam " "wird." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Keinen" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -471,55 +471,59 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "Geben Sie Ihren Benutzernamen bei linphone.org ein." -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Benutzername:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Passwort:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "Geben Sie Ihre Zugangsdaten ein." -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Benutzername*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Passwort*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Domäne*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "Proxy" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) erforderliche Felder" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Benutzername: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Passwort: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "E-Mail: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Bestätigen Sie Ihr Passwort: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -528,12 +532,12 @@ msgstr "" "verwendet oder der Server ist unerreichbar.\n" "Bitte gehen Sie zurück und versuchen Sie es noch einmal." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" "Danke. Ihr Konto ist nun fertig eingerichtet und kann verwendet werden." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -543,40 +547,40 @@ msgstr "" "wir Ihnen soeben per E-Mail geschickt haben.\n" "Danach gehen Sie hierher zurück und drücken auf „Vor“." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Konto-Einrichtungsassistent" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Willkommen zum Konto-Einrichtungsassistenten" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Konto-Einrichtungsassistent" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "Konto einrichten (Schritt 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "Geben Sie Ihren SIP-Benutzernamen ein (Schritt 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "Geben Sie Ihre Zugangsdaten ein (Schritt 1/2)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "Bestätigung (Schritt 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Fehler" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "Fertigstellen" @@ -646,7 +650,7 @@ msgstr "ICE fehlgeschlagen" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" @@ -655,122 +659,122 @@ msgstr "" "Herunterladen: %f\n" "Hochladen: %f (kbit/s)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, fuzzy, c-format msgid "%.3f seconds" msgstr "%i Sekunde" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Verbindungsaufbau..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Eingehender Anruf" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "gut" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "durchschnittlich" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "schlecht" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "sehr schlecht" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "zu schlecht" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "nicht verfügbar" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Gesichert durch SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Gesichert durch ZRTP - [Auth.-Token: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Auf „Ungeprüft“ setzen" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Auf „Geprüft“ setzen" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "In Konferenz" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "Im Gespräch" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Gehaltener Anruf" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Anruf beendet." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "Vermittlung läuft" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "Vermittlung abgeschlossen." -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "Vermittlung fehlgeschlagen." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Fortsetzen" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Halten" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "Halten" @@ -806,7 +810,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -816,60 +820,60 @@ msgstr "" "Dieser Assistent wird Ihnen dabei helfen, ein SIP-Konto für Ihre Anrufe zu " "verwenden." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Aufnahmegerät:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Aufnahmequelle:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Wiedergabegerät:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Konto-Einrichtungsassistent" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Konto-Einrichtungsassistent" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1825,96 +1829,65 @@ msgstr "Verbinden..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "abgebrochen" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "beendet" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "entgangen" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s am %s\n" -"Von: %s\n" -"An: %s\n" -"Status: %s\n" -"Dauer: %i min %i sec\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Abgehender Anruf" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Bereit" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Bestätigung" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Telefonnummernziel wird gesucht..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Diese Nummer kann nicht aufgelöst werden." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Verbindungsaufbau" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Anruf kann nicht getätigt werden." -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Die maximale Anzahl der gleichzeitigen Anrufe ist erreicht." -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "ruft Sie an" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " und fragt nach automatischer Antwort." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Die Anrufparameter werden verändert..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Verbunden." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Anruf abgebrochen" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Anruf kann nicht gehalten werden" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Aktueller Anruf wird gehalten..." @@ -1979,7 +1952,7 @@ msgstr "Dauer" msgid "Unknown-bug" msgstr "Unbekannter Fehler" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1987,7 +1960,7 @@ msgstr "" "Die von Ihnen eingegebene SIP-Proxy-Adresse ist ungültig, sie muss mit " "„sip:“ gefolgt vom Hostnamen beginnen." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1996,131 +1969,156 @@ msgstr "" "Sie sollte wie sip:benutzername@proxydomain aussehen, also z.B. sip:" "alice@beispiel.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Anmeldung als %s fehlgeschlagen" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Klingeln bei der Gegenseite." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Klingeln bei der Gegenseite..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "Anruf mit %s wird gehalten." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Der von %s entgegengenommene Anruf wird gehalten." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Anruf fortgesetzt." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "Anruf wird von %s entgegengenommen." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 #, fuzzy msgid "Incompatible, check codecs or security settings..." msgstr "Inkompatibel, überprüfen Sie die Codecs..." -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "Anruf wird fortgesetzt." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "Anruf wird von der Gegenseite gehalten." -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "Anruf ist von der Gegenseite aktualisiert worden." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Anruf beendet." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Teilnehmer ist besetzt." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Teilnehmer zur Zeit nicht verfügbar." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Teilnehmer möchte nicht gestört werden." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Anruf abgewiesen" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Umgeleitet" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "Inkompatible Medienparameter." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Anruf fehlgeschlagen." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrierung auf %s erfolgreich." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Abmeldung von %s ist erfolgt." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "Zeitüberschreitung bei der Antwort" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrierung auf %s fehlgeschlagen: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Authentifizierungs-Token ist %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Sie haben %i Anruf in Abwesenheit." msgstr[1] "Sie haben %i Anrufe in Abwesenheit." +#~ msgid "aborted" +#~ msgstr "abgebrochen" + +#~ msgid "completed" +#~ msgstr "beendet" + +#~ msgid "missed" +#~ msgstr "entgangen" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s am %s\n" +#~ "Von: %s\n" +#~ "An: %s\n" +#~ "Status: %s\n" +#~ "Dauer: %i min %i sec\n" + +#~ msgid "Outgoing call" +#~ msgstr "Abgehender Anruf" + #~ msgid "No response." #~ msgstr "Keine Antwort." diff --git a/po/es.po b/po/es.po index 37021a332..f58dac100 100644 --- a/po/es.po +++ b/po/es.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone 0.9.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2012-12-06 15:54+0100\n" "Last-Translator: BERAUDO Guillaume \n" "Language-Team: es \n" @@ -15,12 +15,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Llamar a %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Enviar mensaje a %s" @@ -30,47 +30,47 @@ msgstr "Enviar mensaje a %s" msgid "Recent calls (%i)" msgstr "En llamada " -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "n/a" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "abortada" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "perdida" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Rechazar" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i minuto" msgstr[1] "%i minutos" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "%i segundo" msgstr[1] "%i segundos" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, fuzzy, c-format msgid "%s\t%s" msgstr "" "%s\t%s\tCalidad: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, fuzzy, c-format msgid "" "%s\tQuality: %s\n" @@ -79,7 +79,7 @@ msgstr "" "%s\t%s\tCalidad: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, fuzzy, c-format msgid "" "%s\t\n" @@ -101,7 +101,7 @@ msgstr "Yo" msgid "Couldn't find pixmap file: %s" msgstr "No se pudo encontrar el archivo pixmap: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "¡Contacto SIP no válido!" @@ -153,7 +153,7 @@ msgstr "Asistente de configuración de cuenta" msgid "Call with %s" msgstr "Llamar con %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -166,7 +166,7 @@ msgstr "" "contactos?\n" "Si responde no, esta persona será bloqueada temporalmente." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -175,63 +175,63 @@ msgstr "" "Por favor, introduzca la contraseña para el usuario %s\n" " en el dominio %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Error en la llamada." -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 #, fuzzy msgid "Call ended" msgstr "Llamada terminada" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Llamada entrante" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Contestar" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "Rechazar" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "Llamada en pausa" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Puertos" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Enlace a la Web" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - un video-teléfono a través de Internet" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Opción predeterminada)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Somos transferidos a %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -239,7 +239,7 @@ msgstr "" "No se ha encontrado una tarjeta de sonido en este equipo.\n" "No será posible realizar o recibir llamadas de audio." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Un video-teléfono SIP gratuito" @@ -253,7 +253,7 @@ msgstr "Añadir a la agenda" msgid "Presence status" msgstr "Estado de Presencia" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nombre" @@ -271,142 +271,142 @@ msgstr "" msgid "Search in %s directory" msgstr "Buscar en el directorio %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "Editar contacto '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Eliminar contacto '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Eliminar contacto '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Añadir nuevo contacto desde el directorio %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Frecuencia (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Estado" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Bitrate mínimo (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parámetros" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Activado" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Desactivado" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Cuenta" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Inglés" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Francés" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Sueco" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italiano" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Español" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Portugués de Brasil" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polaco" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Alemán" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Ruso" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Japonés" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Holandés" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Húngaro" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Checo" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Chino" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Chino Tradicional" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Noruego" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Deberá reiniciar linphone para aplicar la nueva selección de lenguaje" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 #, fuzzy msgid "None" msgstr "Ninguno." -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "SRTP" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ZRTP" @@ -484,112 +484,116 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "Nombre de usuario:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "Contraseña:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Nombre de usuario" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Contraseña:" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Nombre de usuario:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Contraseña:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Gracias. Su cuenta está configurada y lista para su utilización." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Asistente de configuración de cuenta" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Bienvenido al asistente de configuración de cuenta" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Asistente de configuración de cuenta" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Configurar una cuenta SIP" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -661,136 +665,136 @@ msgstr "La llamada ha fallado." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, fuzzy, c-format msgid "%.3f seconds" msgstr "%i segundo" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr " Llamando..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Llamada entrante" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "buena" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "media" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "mala" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "muy mala" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "demasiado mala" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "no disponible" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Cifrada con SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Cifrada con ZRTP - [token de autenticación: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Set sin verificar" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Set verificado" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "En conferencia" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "En llamada " -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Llamada en pausa" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "Llamada finalizada." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 #, fuzzy msgid "Transfer done." msgstr "Transferir" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Transferir" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Reanudar" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Pausar" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "Pausar" @@ -826,7 +830,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -835,60 +839,60 @@ msgstr "" "¡Bienvenido/a !\n" "Este asistente le ayudará a utilizar una cuenta SIP para sus llamadas." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Dispositivo de captura:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Fuente de grabación:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Dispositivo de reproducción:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Asistente de configuración de cuenta" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Asistente de configuración de cuenta" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1901,101 +1905,70 @@ msgstr "Conectando..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "abortada" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "completada" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "perdida" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s en %s\n" -"De: %s\n" -"Para: %s\n" -"Estado: %s\n" -"Duración: %i min %i seg\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Llamada saliente" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 #, fuzzy msgid "Ready" msgstr "Preparado" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Confirmación" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Buscando el número de teléfono del destinatario…" -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "No se ha podido resolver este número." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 #, fuzzy msgid "Contacting" msgstr "Contactando" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "No se pudo llamar" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Disculpe, se ha alcanzado el máximo número de llamadas simultáneas" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "le está llamando" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "y ha solicitado auto respuesta." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Modificando parámetros de llamada…" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Conectado." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "Llamada abortada" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "No se pudo pausar la llamada" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Pausando la llamada actual..." @@ -2064,7 +2037,7 @@ msgstr "Duración" msgid "Unknown-bug" msgstr "Bug-desconocido" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -2072,7 +2045,7 @@ msgstr "" "La dirección del Proxy SIP que ha introducido no es válida, debe empezar con " "\"sip:\" seguido del hostname." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2081,137 +2054,162 @@ msgstr "" "Debe ser del tipo sip:username@proxydomain, como por ejemplo sip:" "alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "No se pudo iniciar sesión como %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "El destinatario está sonando..." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "El destinatario está sonando..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Medios iniciales." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "La llamada con %s está puesta en pausa." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Llamada respondida por %s - en espera." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Llamada reanudada." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "Llamada respondida por %s." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 #, fuzzy msgid "We have been resumed." msgstr "Nos han reanudado..." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 #, fuzzy msgid "Call is updated by remote." msgstr "La llamada ha sido actualizada por el destinatario..." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 #, fuzzy msgid "Call terminated." msgstr "Llamada finalizada." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "El usuario está ocupado." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "El usuario no está disponible temporalmente." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "El usuario no quiere que le molesten." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Llamada rechazada." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Redigirida" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "La llamada ha fallado." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, fuzzy, c-format msgid "Registration on %s successful." msgstr "Se ha registrado con éxito en %s." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "Cancelación de registro en %s completada." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "timeout sin respuesta" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "El registro en %s ha fallado." -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "El tóken de autenticación es%s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Tiene %i llamada perdida." msgstr[1] "Tiene %i llamadas perdidas." +#~ msgid "aborted" +#~ msgstr "abortada" + +#~ msgid "completed" +#~ msgstr "completada" + +#~ msgid "missed" +#~ msgstr "perdida" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s en %s\n" +#~ "De: %s\n" +#~ "Para: %s\n" +#~ "Estado: %s\n" +#~ "Duración: %i min %i seg\n" + +#~ msgid "Outgoing call" +#~ msgstr "Llamada saliente" + #~ msgid "No response." #~ msgstr "No hay respuesta." diff --git a/po/fr.po b/po/fr.po index 892b7f1c9..a7aac8717 100644 --- a/po/fr.po +++ b/po/fr.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone 0.9.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-04-09 13:57+0100\n" "Last-Translator: Simon Morlat \n" "Language-Team: french \n" @@ -15,12 +15,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Appeler %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Chatter avec %s" @@ -30,42 +30,42 @@ msgstr "Chatter avec %s" msgid "Recent calls (%i)" msgstr "Appels récents (%i)" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "inconnu" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "Abandonné" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "Manqué" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "Refusé" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "%i seconde" msgstr[1] "%i secondes" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" @@ -74,7 +74,7 @@ msgstr "" "%s\tQualité: %s\n" "%s\t%s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -94,7 +94,7 @@ msgstr "Moi" msgid "Couldn't find pixmap file: %s" msgstr "Icone non trouvée: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Contact sip invalide !" @@ -143,7 +143,7 @@ msgstr "Démarre l'assistant audio" msgid "Call with %s" msgstr "Appel avec %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -157,7 +157,7 @@ msgstr "" "Si vous répondez non, cette personne sera mise temporairement sur liste " "noire." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" @@ -166,59 +166,59 @@ msgstr "" "Entrez le mot de passe pour %s\n" " sur le domaine %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Erreur lors de l'appel" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Appel terminé." -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Appel entrant" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Répondre" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Refuser" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Appel en pause" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "b>par %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "%s propose de démarrer la vidéo. Acceptez-vous ?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Lien site web" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - un téléphone video pour l'internet" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (par défaut)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Transfert vers %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -226,7 +226,7 @@ msgstr "" "Aucune carte son n'a été détectée sur cet ordinateur.\n" "Vous ne pourrez pas effectuer d'appels audio." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Un visiophone libre" @@ -238,7 +238,7 @@ msgstr "Ajouter au carnet d'adresse" msgid "Presence status" msgstr "Info de présence" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nom" @@ -255,142 +255,142 @@ msgstr "" msgid "Search in %s directory" msgstr "Rechercher dans l'annuaire de %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Editer le contact '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Supprimer le contact '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "Supprimer l'historique de chat de '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Ajouter un contact depuis l'annuaire %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Fréquence (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Etat" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 msgid "IP Bitrate (kbit/s)" msgstr "Débit IP (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Paramètres" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Activé" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Désactivé" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Compte" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Anglais" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Français" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Suédois" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italien" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Espagnol" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Portugais brésilien" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polonais" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Allemand" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Russe" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日本語" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Néérlandais" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Hongrois" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Tchèque" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "简体中文" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Chinois traditionnel" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Norvégien" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "Hébreu" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "Serbe" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" "La nouvelle selection de langue prendra effet au prochain démarrage de " "linphone." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Aucun" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -463,55 +463,59 @@ msgstr "Je veux spécifier une URI de configuration" msgid "Enter your linphone.org username" msgstr "Entrez votre identifiant linphone.org" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Nom d'utilisateur:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Mot de passe:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "Entrez les informations concernant votre compte" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Nom d'utilisateur*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Mot de passe*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Domaine*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) Champs requis" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Nom d'utilisateur: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Mot de passe: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Confirmez votre mot de passe: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -520,11 +524,11 @@ msgstr "" "serveur n'est pas accessible.\n" "Merci d'essayer à nouveau." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Merci. Votre compte est maintenant configuré et prêt à être utilisé." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -534,39 +538,39 @@ msgstr "" "par email.\n" "Puis appuyez sur suivant." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "Assistant de configuration de compte." -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Bienvenue dans l'assistant de configuration de compte." -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Assistant de configuration de compte." -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "Configurez votre compte (étape 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "Entrez votre identifiant sip (étape 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "Entrez les informations concernant votre compte (étape 1/2)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "Validation (étape 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Erreur" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "En cours d’arrêt." @@ -632,129 +636,129 @@ msgstr "uPnP a échoué." msgid "Direct or through server" msgstr "Directe ou via un serveur" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "Raccrocher" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Tentative d'appel..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Appel entrant" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "bon" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "moyen" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "faible" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "très faible" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "nulle" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "indisponible" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Sécurisé par SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Sécurisé par ZRTP- [jeton: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Marquer comme non vérifié" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Marquer comme vérifié" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "En conférence" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "Appel en cours" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Appel en attente" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Appel terminé." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "Transfert en cours" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "Transfert terminé" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "Transfert échoué" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Reprendre" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Pause" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "(en attente)" @@ -789,63 +793,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" "Bienvenue!\n" -"Cet assistant va vous aider à régler les paramètres audio de votre ordinateur pour une utilisation optimale avec Linphone." +"Cet assistant va vous aider à régler les paramètres audio de votre " +"ordinateur pour une utilisation optimale avec Linphone." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 msgid "Capture device" msgstr "Périphérique de capture" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "Volume enregistré" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "Silencieux" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 msgid "Playback device" msgstr "Périphérique d'écoute" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "Joue trois bips" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "Appuyer sur le bouton enregistrer et dites quelques mots" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "Ecoutez votre voix enregistrée" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "Démarrons Linphone maintenant" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "Assistant audio" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "Assistant audio" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "Calibration du gain du microphone" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "Calibration du volume du haut parleur" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "Enregistrer et joue" @@ -1579,11 +1584,11 @@ msgstr "" #: ../gtk/tunnel_config.ui.h:6 msgid "Configure tunnel" -msgstr "Configuration du tunnel" +msgstr "Configuration du tunnel" #: ../gtk/tunnel_config.ui.h:9 msgid "Configure http proxy (optional)" -msgstr "Configuration d'un proxy http (optionel)" +msgstr "Configuration d'un proxy http (optionel)" #: ../gtk/keypad.ui.h:1 msgid "D" @@ -1748,8 +1753,9 @@ msgid "" msgstr "" "Cette boite de dialogue vous permet de spécifier une addresse http ou https " "où la configuration doit être téléchargée au démarrage.\n" -"Veuillez entrer l'URI http(s) ci dessous. Après avoir validé, Linphone va redémarrer " -"automatiquement pour charger et prendre en compte la nouvelle configuration." +"Veuillez entrer l'URI http(s) ci dessous. Après avoir validé, Linphone va " +"redémarrer automatiquement pour charger et prendre en compte la nouvelle " +"configuration." #: ../gtk/config-uri.ui.h:4 msgid "https://" @@ -1765,95 +1771,64 @@ msgstr "" "Veuillez patenter un instant pendant le chargement de la configuration " "distante..." -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "abandonné" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "terminé" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "manqué" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s le %s\n" -"De: %s\n" -"A destination de: %s\n" -"Etat: %s\n" -"Durée: %i mn %i sec\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Appel sortant" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Prêt." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 msgid "Configuring" msgstr "Configuration en cours" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Recherche de la destination du numéro de téléphone..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "La destination n'a pu être trouvée." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Appel de" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Echec de l'appel" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Désolé, le nombre maximum d'appels simultanés est atteint." -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "vous appelle" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "et sollicite un décrochage automatique." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Modifications des paramètres d'appels..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "En ligne." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Appel abandonné" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "La mise en attente a échoué" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Mise en attente de l'appel..." @@ -1917,7 +1892,7 @@ msgstr "En congé" msgid "Unknown-bug" msgstr "Bug inconnu" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1925,7 +1900,7 @@ msgstr "" "L'adresse SIP du proxy est invalide. Elle doit commencer par \"sip:\" suivie " "par un nom de domaine." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1934,131 +1909,156 @@ msgstr "" "Elle doit être de la forme sip:username@domain, comme par example sip:" "alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Echec de la connexion en tant que %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Sonnerie distante." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Sonnerie distante..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Prise d'appel anticipée." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "%s est maintenant en attente." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Appel répondu par %s - en attente" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Appel repris." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "Appel répondu par %s." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "Appel repris." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "L'appel a été mis en attente." -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 #, fuzzy msgid "Call is updated by remote." msgstr "Mise à jour de l'appel par le correspondant." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Appel terminé." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Occupé..." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "L'usager est temporairement indisponible." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "L'usager ne souhaite pas être dérangé" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Appel décliné." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Redirection" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "Paramètres media incompatibles." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "L'appel a échoué." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Enregistrement sur %s effectué." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Désenregistrement sur %s effectué." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "Pas de réponse" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Echec de l'enregistrement sur %s: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Le jeton d'authentification est %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Vous avez manqué %i appel" msgstr[1] "Vous avez manqué %i appels" +#~ msgid "aborted" +#~ msgstr "abandonné" + +#~ msgid "completed" +#~ msgstr "terminé" + +#~ msgid "missed" +#~ msgstr "manqué" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s le %s\n" +#~ "De: %s\n" +#~ "A destination de: %s\n" +#~ "Etat: %s\n" +#~ "Durée: %i mn %i sec\n" + +#~ msgid "Outgoing call" +#~ msgstr "Appel sortant" + #~ msgid "No response." #~ msgstr "Pas de réponse." diff --git a/po/he.po b/po/he.po index 878ac3e4a..f6dd58f14 100644 --- a/po/he.po +++ b/po/he.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone 3.5.99.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-04-24 21:31+0200\n" "Last-Translator: Isratine Citizen \n" "Language-Team: Rahut Project \n" @@ -20,12 +20,12 @@ msgstr "" "X-Generator: Poedit 1.5.4\n" # צור קשר עם -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "התקשר אל %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "שלח טקסט אל %s" @@ -35,42 +35,42 @@ msgstr "שלח טקסט אל %s" msgid "Recent calls (%i)" msgstr "שיחות אחרונות (%i)" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "לא זמין (n/a)" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "ננטשה" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "הוחמצה" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "נדחתה" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "דקה %i" msgstr[1] "%i דקות" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "שניה %i" msgstr[1] "%i שניות" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" @@ -79,7 +79,7 @@ msgstr "" "%s\tאיכות: %s\n" "%s\t%s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -100,7 +100,7 @@ msgid "Couldn't find pixmap file: %s" msgstr "לא ניתן למצוא קובץ ‫pixmap: ‫%s" # איש־קשר -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "כתובת sip לא תקפה !" @@ -168,7 +168,7 @@ msgstr "התקשרות באמצעות %s" # הקשר שלהם # אם התשובה -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -181,7 +181,7 @@ msgstr "" "שלך ?\n" "היה ותשובתך תהיה לא, אדם זה יהיה מסומן באופן זמני ברשימה השחורה." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -191,65 +191,65 @@ msgstr "" " בתחום %s:" # שיחה -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "שגיאת קריאה" # Conversation ended -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "שיחה הסתיימה" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "קריאה נכנסת" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "לענות" # דחיה -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "לדחות" # Conversation paused -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "שיחה הושהתה" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "על ידי %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "‏%s רוצה להתחיל וידאו. האם אתה מסכים ?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "קישור אתר רשת" # ‫Linphone - וידאופון במרשתת -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "‫Linphone - וידאופון אינטרנטי" # משתמטת -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "‫%s (ברירת מחדל)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "אנחנו מועברים אל %s" # קריאות שמע -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -257,7 +257,7 @@ msgstr "" "לא אותרו כרטיסי קול במחשב זה.\n" "לא תהיה ביכולתך לשלוח או לקבל שיחות אודיו." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "וידאופון SIP חופשי" @@ -269,7 +269,7 @@ msgstr "הוסף אל ספר כתובות" msgid "Presence status" msgstr "מצב נוכחות" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "שם" @@ -287,148 +287,148 @@ msgstr "שיחה" msgid "Search in %s directory" msgstr "חיפוש במדור %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "ערוך איש קשר '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "מחק איש קשר '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "מחק היסטוריית שיחה של '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "הוסף איש קשר חדש מן מדור %s" # קצב תדר תדירות מהירות -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "שיעור (הרץ)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "מצב" # שיעור סיביות מינימלי -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "קצב נתונים מינימלי (קי״ב/שנ׳)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "פרמטרים" # מאופשר -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "מופעל" # מנוטרל -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "לא מופעל" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "חשבון" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "English" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Français" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Svenska" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italiano" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Español" # português do Brasil -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "português brasileiro" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polski" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Deutsch" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Русский" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日本語" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Nederlands" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Magyar" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Česky" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "中文" # 繁体字 -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "繁體字" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "norsk" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "עברית" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "српски srpski" # selected הנבחרת -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "עליך לאתחל את לינפון כדי שהשפה החדשה תיכנס לתוקף." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "ללא" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -502,58 +502,62 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "הזן את שם משתמשך אצל linphone.org" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "שם משתמש:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "סיסמה:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "הזן את מידע חשבונך" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "שם משתמש*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "סיסמה*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "מתחם*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "פרוקסי" # נדרשים -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) שדות חובה" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "שם משתמש: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "סיסמה: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "דוא״ל: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "אימות סיסמתך: (*)" +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + # אינו בר־השגה # לשוב אחורה -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -561,12 +565,12 @@ msgstr "" "שגיאה, חשבון לא אומת, שם משתמש כבר בשימוש או שרת לא ניתן להשגה.\n" "נא לחזור ולנסות שוב." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "תודה לך. חשבונך מוגדר ומוכן לשימוש כעת." # לאחר מכן -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -575,44 +579,44 @@ msgstr "" "נא לאמת את חשבונך באמצעות הקלקה על הקישור ששלחנו לך עתה באמצעות דוא״ל.\n" "אחרי כן נא לחזור לכאן וללחוץ על הלחצן 'קדימה'." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "אשף הגדרת חשבון" # Wizard אשף # סייע -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "ברוך בואך אל אשף הגדרת החשבון" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "אשף הגדרת חשבון" # שלב -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "הגדרת חשבונך (צעד 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "הזנת שם משתמש sip (צעד 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "הזנת מידע חשבון (צעד 1/2)" # תקפות -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "אימות (צעד 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "שגיאה" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "מסיים כעת" @@ -678,7 +682,7 @@ msgstr "‏uPnP נכשלה" msgid "Direct or through server" msgstr "ישיר או דרך שרת" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" @@ -687,122 +691,122 @@ msgstr "" "הורדה: %f\n" "העלאה: %f (קי״ב/שנ׳)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "%.3f שניות" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "נתק" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "מתקשר כעת..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "‭00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "קריאה נכנסת" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "טובה" # רגילה -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "ממוצעת" # weak חלשה חלושה רפויה רופפת -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "דלה" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "דלה מאוד" # רעה -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "גרועה מדי" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "לא זמינה" # באמצעות -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "מאובטחת על ידי SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "מאובטחת על ידי ZRTP - [אות אימות: %s]" # set or unset verification state of ZRTP SAS. -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "הגדר כלא מאומתת" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "הגדר כמאומתת" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "בשיחת ועידה" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "בשיחה כעת" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "שיחה מושהית" # שעות %02i דקות %02i שניות %02i # Force LTR time format (hours::minutes::seconds) with LRO chatacter (U+202D) -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "‭%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "שיחה הסתיימה." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "העברה מצויה כעת בעיצומה" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "העברה הסתיימה." -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "העברה נכשלה." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "חזור" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "השהה" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" @@ -811,7 +815,7 @@ msgstr "" "מקליט אל תוך\n" "%s %s" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "(מושהה)" @@ -846,7 +850,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -855,59 +859,59 @@ msgstr "" "ברוך בואך !\n" "אשף זה יסייע לך לעשות שימוש בחשבון SIP עבור שיחותייך." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "התקן לכידה:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "התקן פס קול:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "אשף חשבון" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "אשף חשבון" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1872,100 +1876,68 @@ msgstr "מתחבר כעת..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "ננטשה" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "הסתיימה" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "הוחמצה" - -# needs to be tested -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s אצל %s\n" -"מאת: %s\n" -"אל: %s\n" -"מצב: %s\n" -"משך: %i mn %i sec\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "קריאה יוצאת" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "מוכן" # וידוא -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "אימות" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "מחפש כעת עבור יעד מספר טלפון..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "לא ניתן לפתור את מספר זה." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "מתקשר כעת" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "לא ניתן להתקשר" # מספר השיחות המקבילות המרבי -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "הגענו אל המספר המרבי של שיחות מקבילות, עמך הסליחה" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "מתקשר/ת אליך" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " ומבקש/ת מענה אוטומטי." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" # פרמטרי קריאה -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "מתאים כעת פרמטרים של שיחה..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "מקושר." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "קריאה בוטלה" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "לא ניתן להשהות את השיחה" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "משהה כעת שיחה נוכחית..." @@ -2036,7 +2008,7 @@ msgstr "משך זמן" msgid "Unknown-bug" msgstr "תקלה לא מוכרת" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -2044,7 +2016,7 @@ msgstr "" "כתובת sip proxy שהזנת הינה שגויה, זו צריכה להתחיל עם‭\"sip:\" ‬ לאחר שם מארח." # כמו למשל -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2053,40 +2025,40 @@ msgstr "" "זו צריכה להיראות כמו sip:username@proxydomain, למשל sip:alice@example.net" # בשם כ־ -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "לא ניתן להתחבר בזהות %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "צלצול מרוחק." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "צלצול מרוחק..." # A SIP state -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "מדיה מוקדמת." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "שיחה עם %s מושהית." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "קריאה נענתה על ידי %s - בהמתנה." # renewed -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "קריאה חודשה." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "קריאה נענתה על ידי %s." @@ -2094,102 +2066,128 @@ msgstr "קריאה נענתה על ידי %s." # לא תואם # אי תאימות # אי התאמה -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "חוסר תאימות, בדוק קודקים או הגדרות אבטחה..." -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "חזרנו." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "אנו מושהים על ידי צד אחר." # באופן מרוחק -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "שיחה עודכנה מרחוק." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "קריאה הסתיימה." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "משתמש עסוק כעת." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "משתמש לא זמין זמנית." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "משתמש לא מעוניין שיפריעו לו." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "קריאה סורבה." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "מכוון מחדש" # לא תואם # אי תאימות # אי התאמה -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "פרמטריי מדיה חסרי תואמים." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "קריאה נכשלה." # הרשמה אצל %s הושלמה בהצלחה. -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "רישום אצל %s הושלם בהצלחה." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "אי רישום אצל %s סוים." # Pas de réponse # no response in defined time -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "אין היענות תוך זמן מוגדר" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "רישום אצל %s נכשל: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "אות האימות הינה %s" # האם כדאי לחקות את הטלפונים הניידים? שיחות של נענו -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "החמצת שיחה %i." msgstr[1] "החמצת %i שיחות." +#~ msgid "aborted" +#~ msgstr "ננטשה" + +#~ msgid "completed" +#~ msgstr "הסתיימה" + +#~ msgid "missed" +#~ msgstr "הוחמצה" + +# needs to be tested +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s אצל %s\n" +#~ "מאת: %s\n" +#~ "אל: %s\n" +#~ "מצב: %s\n" +#~ "משך: %i mn %i sec\n" + +#~ msgid "Outgoing call" +#~ msgstr "קריאה יוצאת" + #~ msgid "No response." #~ msgstr "אין תגובה." diff --git a/po/hu.po b/po/hu.po index d69f7e8bc..86c3032b5 100644 --- a/po/hu.po +++ b/po/hu.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-03-26 19:00+0100\n" "Last-Translator: Viktor \n" "Language-Team: \n" @@ -17,12 +17,12 @@ msgstr "" "X-Generator: Poedit 1.5.4\n" "Plural-Forms: nplurals=1; plural=1 == 1 ? 0 : 1;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "%s hívása" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Szöveg küldése a következőnek: %s" @@ -32,42 +32,42 @@ msgstr "Szöveg küldése a következőnek: %s" msgid "Recent calls (%i)" msgstr "vonalban" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "-" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "Megszakítva" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "Nem fogadott" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "Elutasítva" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i perc" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "%i másodperc" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, fuzzy, c-format msgid "%s\t%s" msgstr "" "%s\t%s\t\n" "%s\t%s" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, fuzzy, c-format msgid "" "%s\tQuality: %s\n" @@ -76,7 +76,7 @@ msgstr "" "%s\t%s\tMinőség: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, fuzzy, c-format msgid "" "%s\t\n" @@ -98,7 +98,7 @@ msgstr "én" msgid "Couldn't find pixmap file: %s" msgstr "Nemtalálható a pixmap fájl: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Érvénytelen sip partner !" @@ -149,7 +149,7 @@ msgstr "Fiók beállítása varázsló" msgid "Call with %s" msgstr "Hívás %s -el" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -162,7 +162,7 @@ msgstr "" "szeretné adni a partnerlistához?\n" "Ha nemmel válaszol, ez a személy átmenetileg tiltólistára kerül." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -171,59 +171,59 @@ msgstr "" "Kérem, adja meg jelszavát a következő felhasználónévhez: %s\n" "tartomány %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Hiba a hívás közben" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Hívás vége" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Beérkező hívás" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Hívás fogadása" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Elutasítás" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Hívás várakoztatva" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "a következő által: %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "%s szerené elidítani a videót. Elfogadja?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Internetes oldal" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - internetes videó telefon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Alapértelmezett)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Át vagyunk irányítva ide: %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -231,7 +231,7 @@ msgstr "" "Hangkártya nincs érzékelve ezen a számítógépen.\n" "Nem fog tudni hang hívásokat küldeni vagy fogadni." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Egy ingyenes SIP video-telefon" @@ -243,7 +243,7 @@ msgstr "Hozzáadás címjegyzékhez" msgid "Presence status" msgstr "Jelenlét státusz" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Név" @@ -260,143 +260,143 @@ msgstr "Csevegés" msgid "Search in %s directory" msgstr "Keresés ebben a könyvtárban: %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Kapcsolatinformációk szerkesztése: '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "'%s' partner törlése" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "'%s' partner törlése" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Új partner hozzáadása ebből a könyvtárból: %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Érték (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Állapot" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min bitrate (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Paraméterek" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Engedélyezve" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Tiltva" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Hozzáférés" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "angol" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "francia" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "svéd" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "olasz" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "spanyol" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "brazil-portugál" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "lengyel" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "német" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "orosz" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "japán" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "holland" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "magyar" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "cseh" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "egyszerúsített kínai" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "tradícionális kínai" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "norvég" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "héber" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" "Újra kell indítania a linphone-t, hogy az új nyelv kiválasztása érvényre " "jusson. " -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Nincs" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "SRTP" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ZRTP" @@ -467,55 +467,59 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "Adja meg linphone.org felhasználónevét" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Felhasználónév:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Jelszó:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "Írja be fiókinformációit" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Felhasználónév*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Jelszó*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Tartomány" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "Proxy" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) Mező kitöltése szükséges" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Felhasználónév: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Jelszó: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "E-mail: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Jelszó megerősítése: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -524,11 +528,11 @@ msgstr "" "vagy a kiszolgáló nem elérhető.\n" "Kérjük, lépjen vissza és próbálja újra." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Köszönjük! Az Ön fiókját beállítottuk és használatra kész." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -538,40 +542,40 @@ msgstr "" "hivatkozásra kattintva.\n" "Azután térjen vissza ide és kattintson a Következő gombra." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Fiók beállítása varázsló" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "A fiók beállítása varázsló üdvözli Önt" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Fiók beállítása varázsló" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "Az Ön fiókjának beállítása (1/1 lépés)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "Adja meg sip felhasználónevét (1/2 lépés)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "Adja meg a fiókinformációt (1/2 lépés)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "Érvényesítés (2/2 lépés)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Hiba" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "Befejezés" @@ -637,7 +641,7 @@ msgstr "uPnP nem sikerült" msgid "Direct or through server" msgstr "közvetlen vagy kiszolgálón keresztül" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" @@ -646,115 +650,115 @@ msgstr "" "letöltés: %f\n" "feltöltés: %f (kbit/mp)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "%.3f másodperc" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "Befejezés" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Hívás folyamatban..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Beérkező hívás" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "jó" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "közepes" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "gyenge" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "nagyon gyenge" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "rossz" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "nem elérhető" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "SRTP-vel titkosítva" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "ZRTP-vel titkosítva - [hitelesítési jel: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Beállítás ellenőrizetlenként" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Beállítás ellenőrzöttként" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "Konferencián" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "vonalban" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Várakoztatott hívás" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Hívás vége." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "Átvitel folyamatban" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "Átvitel befejezve." -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "Az átvitel sikertelen." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Visszatérés" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Várakoztatás" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" @@ -763,7 +767,7 @@ msgstr "" "Felvétel a következőbe\n" "%s %s" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "(Várakoztatva)" @@ -798,7 +802,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -807,60 +811,60 @@ msgstr "" "Üdvözöljük !\n" "Ez a varázsló segít Önnek, hogy sip fiókot használjon hívásaihoz." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Felvevő hang eszköz:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Felvételi forrás:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Lejátszó hang eszköz:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Fiók varázsló" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Fiók varázsló" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1806,96 +1810,65 @@ msgstr "Kapcsolódás..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "megszakítva" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "befejezve" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "elhibázva" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s nél %s\n" -"Tól: %s\n" -"Ig: %s\n" -"Állapot: %s\n" -"Időtartam: %i perc %i másodperc\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Kimenő hívás" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Kész" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Információk" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Telefonszám-cél keresése..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Nem sikkerült értelmezni a számot." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Kapcsolódás" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Nem sikerült hívni" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Elnézést, elértük a egyidejű hívások maximális számát" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "kapcsolatba lépett veled." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "és automatikus választ kért." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "A hívási jellemzők módosítása..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Kapcsolódva." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Hívás megszakítva" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Nem sikerült várakoztatni a hívást" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Jelenlegi hívás várakoztatásának aktiválása..." @@ -1960,7 +1933,7 @@ msgstr "Időtartam" msgid "Unknown-bug" msgstr "Ismeretlen programhiba" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1968,7 +1941,7 @@ msgstr "" "Az Ön által megadott SIP proxy cím érvénytelen. \"sip:\"-tal kell kezdődnie, " "ezt egy hosztnév követi." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1977,130 +1950,155 @@ msgstr "" "Így kéne kinéznie: sip:felhasznalonev@proxytartomany, például sip:" "aladar@pelda.hu" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Nem sikerült belépni ezzel: %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Távoli csengés." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Távoli csengés..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Korai médiák." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "A hívás a következővel: %s várakoztatva" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "%s fogadta a hívást - várakoztatva." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Hívás visszatért" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "%s válaszolt a hívásra." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" "Nem kompatibilis, ellenőrizze a kódek- vagy a biztonsági beállításokat..." -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "Visszatértünk." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "Megállítva a másik fél által." -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "A hívás távolról frissítve." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "A hívás befejezve." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "A felhasználó foglalt." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "A felhasználó ideiglenesen nem elérhető" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "A felhasználó nem akarja, hogy zavarják." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Hívás elutasítva" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Átirányítva" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "Nem kompatibilis médiajellemzők." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Nem sikerült a hívás." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "A regisztáció a %s -n sikerült." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "A kiregisztrálás kész a következőn: %s ." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "időtúllépés után nincs válasz" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "A regisztáció a %s -n nem sikerült: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Hitelesítési jel: %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Van %i nem fogadott hivás." +#~ msgid "aborted" +#~ msgstr "megszakítva" + +#~ msgid "completed" +#~ msgstr "befejezve" + +#~ msgid "missed" +#~ msgstr "elhibázva" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s nél %s\n" +#~ "Tól: %s\n" +#~ "Ig: %s\n" +#~ "Állapot: %s\n" +#~ "Időtartam: %i perc %i másodperc\n" + +#~ msgid "Outgoing call" +#~ msgstr "Kimenő hívás" + #~ msgid "No response." #~ msgstr "Nincs válasz." diff --git a/po/it.po b/po/it.po index a04f95573..980db056b 100644 --- a/po/it.po +++ b/po/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone 3.2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2002-10-15 HO:MI+ZONE\n" "Last-Translator: Matteo Piazza \n" "Language-Team: it \n" @@ -15,12 +15,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Chiamata %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Invia testo a %s" @@ -30,52 +30,52 @@ msgstr "Invia testo a %s" msgid "Recent calls (%i)" msgstr "In chiamata con" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "annullato" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "mancante" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Rifiuta" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -98,7 +98,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Contatto SIP non valido" @@ -147,7 +147,7 @@ msgstr "Configuratore di account" msgid "Call with %s" msgstr "Chat con %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -159,74 +159,74 @@ msgstr "" "veda il tuo stato o aggiungerlo alla tua lista dei contatti Se rispondi no " "questo utente sarà momentaneamente bloccato." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "Prego inserire la password per username %s e dominio %s" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Cronologia" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Chiamata terminata" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Chimata in entrata" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Rifiuta" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "annullato" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Porte" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Default)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "" @@ -238,7 +238,7 @@ msgstr "" msgid "Presence status" msgstr "Presenza" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nome" @@ -256,141 +256,141 @@ msgstr "" msgid "Search in %s directory" msgstr "Cerca contatti nella directory %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Modifica contatto %s" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Elimina contatto %s" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Elimina contatto %s" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Aggiungi nuovo contatto dalla directory %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Stato" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Bitrate Min (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametri" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Attivato" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Disattivato" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Account" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Inglese" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Francese" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Svedese" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italiano" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Spagnolo" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polacco" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Tedesco" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Russo" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Giapponese" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Olandese" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Ungherese" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Ceco" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Riavviare il software per utilizzare la nuova lingua selezionata" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -465,110 +465,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Manuale utente" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Password:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Username" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Password" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Manuale utente" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Password:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Grazie. Il tuo account è configurato e pronto all'uso" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Configuratore di account" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Benvenuto nel configuratore di account" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Configuratore di account" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Configurazione SIP account" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 #, fuzzy msgid "Terminating" msgstr "Termina chiamata" @@ -639,134 +643,134 @@ msgstr "Filtro ICE" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "Linguaggio" -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Chimata in entrata" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "In chiamata con" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Termina chiamata" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Chiamata terminata." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Chiamata rifiutata" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -801,7 +805,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -810,59 +814,59 @@ msgstr "" "Benvenuti !\n" "La procedura vi aiutera a configurare un account SIP." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Dispositivo microfono:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Dispositivo uscita audio:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Configuratore" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Configuratore di account" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1830,100 +1834,69 @@ msgstr "In connessione..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "annullato" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "comletato" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "mancante" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s at %s\n" -"Da: %s\n" -"Verso: %s\n" -"Stato: %s\n" -"Durata: %i mn %i sec\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Chiamata in uscita" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Pronto" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Informazioni" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Ricerca numero destinazione..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Impossibile risolvere il numero." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "In connessione" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "chiamata fallita" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "ti sta conttatando." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Connessione" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "annullato" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 #, fuzzy msgid "Could not pause the call" msgstr "chiamata fallita" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 #, fuzzy msgid "Pausing the current call..." msgstr "Mostra chiamata corrente" @@ -1989,7 +1962,7 @@ msgstr "Durata" msgid "Unknown-bug" msgstr "Bug-sconosciuto" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1997,7 +1970,7 @@ msgstr "" "L'indirizzo sip proxy utilizzato è invalido, deve iniziare con \"sip:\" " "seguito dall' hostaname." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2005,133 +1978,158 @@ msgstr "" "L'identità sip utilizza è invalida.\n" "Dovrebbre essere sip:username@proxydomain, esempio: sip:alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "impossibile login come %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "Chat con %s" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Chiamata terminata" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Chiamata terminata." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Utente occupato" -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Utente non disponibile" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "L'utente non vuole essere disturbato" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Chiamata rifiutata" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 #, fuzzy msgid "Redirected" msgstr "Rediretto verso %s..." -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Chiamata rifiutata" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrazione su %s attiva" -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Unregistrazione su %s" -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "timeout no risposta" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrazione su %s fallita: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Linphone - Autenticazione richiesta" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "" msgstr[1] "" +#~ msgid "aborted" +#~ msgstr "annullato" + +#~ msgid "completed" +#~ msgstr "comletato" + +#~ msgid "missed" +#~ msgstr "mancante" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s at %s\n" +#~ "Da: %s\n" +#~ "Verso: %s\n" +#~ "Stato: %s\n" +#~ "Durata: %i mn %i sec\n" + +#~ msgid "Outgoing call" +#~ msgstr "Chiamata in uscita" + #, fuzzy #~ msgid "No response." #~ msgstr "timeout no risposta" diff --git a/po/ja.po b/po/ja.po index 3cb7d0a36..6a5e37625 100644 --- a/po/ja.po +++ b/po/ja.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 0.10\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2003-01-21 00:05+9000\n" "Last-Translator: YAMAGUCHI YOSHIYA \n" "Language-Team: \n" @@ -17,12 +17,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "" @@ -32,51 +32,51 @@ msgstr "" msgid "Recent calls (%i)" msgstr "接続中" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "通話はキャンセルされました。" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "ライン入力" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -96,7 +96,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "pixmapファイルが見つかりません %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "" @@ -144,7 +144,7 @@ msgstr "" msgid "Call with %s" msgstr "" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -153,76 +153,76 @@ msgid "" "If you answer no, this person will be temporarily blacklisted." msgstr "" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "通話はキャンセルされました。" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 #, fuzzy msgid "Call ended" msgstr "通話は拒否されました。" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "ライン入力" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "通話はキャンセルされました。" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "接続中" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "" @@ -236,7 +236,7 @@ msgstr "電話帳" msgid "Presence status" msgstr "状態" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "名前" @@ -254,142 +254,142 @@ msgstr "" msgid "Search in %s directory" msgstr "" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "(接続するための情報がありません!)" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "状態" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "最低限のビットレート (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "パラメーター" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "使用する" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "使用しない" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Français" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日本語" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Magyar" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "čeština" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "简体中文" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 #, fuzzy msgid "None" msgstr "ありません。" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -459,110 +459,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "ユーザーマニュアル" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "パスワード" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "ユーザーマニュアル" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "パスワード" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "ユーザーマニュアル" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "パスワード" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -631,135 +635,135 @@ msgstr "通話はキャンセルされました。" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "接続中" -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "接続中" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "接続中" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "接続中" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "通話は拒否されました。" -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "通話はキャンセルされました。" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -794,64 +798,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "使用するサウンドデバイス" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "録音する音源" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "使用するサウンドデバイス" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1834,96 +1838,70 @@ msgstr "コネクション" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 #, fuzzy msgid "Ready" msgstr "準備完了。" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "情報" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "" -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "" #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 #, fuzzy msgid "Contacting" msgstr "接続中" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "pixmapファイルが見つかりません %s" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "から電話です。" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "接続しました。" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "通話はキャンセルされました。" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "" @@ -1992,143 +1970,143 @@ msgstr "情報" msgid "Unknown-bug" msgstr "" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "pixmapファイルが見つかりません %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "登録中……" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "登録中……" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "通話は拒否されました。" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "" "電話をかける\n" "電話に出る" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 #, fuzzy msgid "Call terminated." msgstr "通話は拒否されました。" -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "ユーザーはビジーです" -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "ユーザーは、今出られません。" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "ユーザーは手が離せないようです。" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "通話は拒否されました。" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "通話はキャンセルされました。" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, fuzzy, c-format msgid "Registration on %s successful." msgstr "登録しました。" -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "登録しました。" -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "登録しました。" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "コーデックの情報" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." diff --git a/po/nb_NO.po b/po/nb_NO.po index d135aecc6..6170997da 100644 --- a/po/nb_NO.po +++ b/po/nb_NO.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2011-04-05 01:56+0200\n" "Last-Translator: Øyvind Sæther \n" "Language-Team: Norwegian Bokmål \n" @@ -17,12 +17,12 @@ msgstr "" "X-Generator: Lokalize 1.2\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Ring %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Send tekst til %s" @@ -32,52 +32,52 @@ msgstr "Send tekst til %s" msgid "Recent calls (%i)" msgstr "I samtale med" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "avbrutt" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "ubesvart" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Avvis" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -98,7 +98,7 @@ msgstr "Skru mikrofonen av" msgid "Couldn't find pixmap file: %s" msgstr "Fant ikke pixmap fli: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Ugyldig SIP kontakt !" @@ -149,7 +149,7 @@ msgstr "Brukerkontoveiviser" msgid "Call with %s" msgstr "Ring med %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -162,7 +162,7 @@ msgstr "" "din kontaktliste?\n" "Hvis du svarer nei vil personen bli svartelyst midlertidig." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -171,61 +171,61 @@ msgstr "" "Skriv inn ditt passord for brukernavn %s\n" " på domene %s:i>:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Samtalehistorikk" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Samtale avsluttet" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Innkommende samtale" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Svarer" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Avvis" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "Samtale avbrutt" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Porter" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Peker til nettsted" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - en video Internet telefon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Standard)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Vi er overført til %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -233,7 +233,7 @@ msgstr "" "Klarte ikke å finne noe lydkort på denne datamaskinen.\n" "Du vil ikke kunne sende eller motta lydsamtaler." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "En gratis SIP video-telefon" @@ -245,7 +245,7 @@ msgstr "" msgid "Presence status" msgstr "Tilstedestatus" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Navn" @@ -263,141 +263,141 @@ msgstr "" msgid "Search in %s directory" msgstr "Søk i %s katalogen" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Rediger kontakt '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Slett kontakt '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Slett kontakt '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Legg til kontakt fra %s katalogen" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Frekvens (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min. datahastighet (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametere" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "På" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Av" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Konto" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Engelsk" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Fransk" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Svensk" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italisensk" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Spansk" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Portugisisk" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polsk" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Tysk" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Russisk" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Japansk" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Nederlandsk" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Ungarsk" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Tjekkisk" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Kinesisk" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Du må restarte linphone for at det nye språkvalget skal iverksettes." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -472,110 +472,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Brukernavn:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Passord:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Brukernavn" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Passord" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Brukernavn:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Passord:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Takk. Ditt konto er nå satt opp og klart til bruk." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Brukerkontoveiviser" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Velkommen til brukerkontoveiviseren" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Brukerkontoveiviser" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Konfigurer en SIP konto" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 #, fuzzy msgid "Terminating" msgstr "Lägg på" @@ -647,131 +651,131 @@ msgstr "ICE filter" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Ringer..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00:00:00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Innkommende samtale" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "I samtale med" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Pauset samtale" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i:%02i:%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Samtale avsluttet." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 #, fuzzy msgid "Transfer done." msgstr "Overfører" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Overfører" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Fortsett" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Pause" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "Pause" @@ -807,7 +811,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -816,59 +820,59 @@ msgstr "" "Velkommen\n" "Denne veiviseren vil hjelpe deg sette opp en SIP-konto for dine samtaler." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Mikrofonenhet:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Avspillingsenhet:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Assistent" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Brukerkontoveiviser" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1824,96 +1828,65 @@ msgstr "Tilknytter..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "avbrutt" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "Fullført" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "ubesvart" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s på %s\n" -"Fra: %s\n" -"Til: %s\n" -"Status: %s\n" -"Lengde: %i min %i sek\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Utgående samtale" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Klar" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Bekreftelse" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Ser etter telefonnummer for destinasjonen..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Kan ikke tilkoble dette nummeret." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Tilknytter" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Kunne ikke ringe" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Beklager, du har nådd maksimalt antall samtidige samtaler" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "Kontakter deg." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " og ba om autosvar." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Endrer ringeparametre..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Tilkoblet" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Samtale avbrutt" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Kunne ikke pause samtalen" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Pauser nåværende samtale" @@ -1978,7 +1951,7 @@ msgstr "Varighet" msgid "Unknown-bug" msgstr "Ukjent feil" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1986,7 +1959,7 @@ msgstr "" "SIP proxy adressen du har angitt er ugyldig, den må begynne med \"sip:\" " "etterfult av vertsnavn." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1994,132 +1967,157 @@ msgstr "" "SIP adressen du har angitt er feil. Adressen bør se ut som sip: " "brukernavn@domenenavn, f.eks sip:ola@eksempel.no" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Ikke ikke logge inn som %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Ringer hos motparten." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Ringer hos motparten." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Tidlig media" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "Samtalen med %s er pauset." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Samtale besvart av %s - på vent." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Samtale gjenopptatt." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "Samtale besvart av %s." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 #, fuzzy msgid "We have been resumed." msgstr "Vi har blitt gjenopptatt..." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Samtale avsluttet." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Brukeren er opptatt." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Brukeren er midlertidig ikke tilgjengelig." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Brukeren vil ikke bli forstyrret." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Samtale avvist." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Omdirigert" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Samtale feilet." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrering hos %s lykkes." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Avregistrering hos %s lykkes." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "ingen svar innen angitt tid" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrering hos %s mislykkes: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Autorisering kreves" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Du har %i ubesvarte anrop." msgstr[1] "Du har %i missade samtal" +#~ msgid "aborted" +#~ msgstr "avbrutt" + +#~ msgid "completed" +#~ msgstr "Fullført" + +#~ msgid "missed" +#~ msgstr "ubesvart" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s på %s\n" +#~ "Fra: %s\n" +#~ "Til: %s\n" +#~ "Status: %s\n" +#~ "Lengde: %i min %i sek\n" + +#~ msgid "Outgoing call" +#~ msgstr "Utgående samtale" + #~ msgid "No response." #~ msgstr "Ikke noe svar." diff --git a/po/nl.po b/po/nl.po index 21a4523cd..b650efb95 100644 --- a/po/nl.po +++ b/po/nl.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: nl\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2007-09-05 10:40+0200\n" "Last-Translator: Hendrik-Jan Heins \n" "Language-Team: Nederlands \n" @@ -19,12 +19,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, fuzzy, c-format msgid "Call %s" msgstr "Oproepgeschiedenis" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "" @@ -34,52 +34,52 @@ msgstr "" msgid "Recent calls (%i)" msgstr "Contactlijst" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "afgebroken" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "gemist" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "lijn" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -99,7 +99,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "Kon pixmap bestand %s niet vinden" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "" @@ -147,7 +147,7 @@ msgstr "" msgid "Call with %s" msgstr "Chat met %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -156,75 +156,75 @@ msgid "" "If you answer no, this person will be temporarily blacklisted." msgstr "" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Linphone - Oproepgeschiedenis" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Oproep beeindigd" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Inkomende oproep" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "lijn" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "afgebroken" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Contactlijst" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Een Vrije SIP video-telefoon" @@ -237,7 +237,7 @@ msgstr "Adresboek" msgid "Presence status" msgstr "Aanwezigheidsstatus" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Naam" @@ -256,141 +256,141 @@ msgstr "Chat box" msgid "Search in %s directory" msgstr "" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "Bewerk contactgegevens" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Frequentie (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Minimale bitrate (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parameters" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Aan" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Uit" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Account" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Geen" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -460,110 +460,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "gebruikersnaam:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "wachtwoord:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "gebruikersnaam:" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "wachtwoord:" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "gebruikersnaam:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "wachtwoord:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -634,135 +638,135 @@ msgstr "Oproep geannuleerd." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "Contactlijst" -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Inkomende oproep" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "Contactlijst" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Contactlijst" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "Oproep beeindigd" -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Oproep geannuleerd." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -797,64 +801,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Geluidsapparaat gebruiken:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Bron voor opname:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Geluidsapparaat gebruiken:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1847,100 +1851,69 @@ msgstr "Verbinden" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "afgebroken" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "voltooid" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "gemist" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s op %s\n" -"Van: %s\n" -"Aan: %s\n" -"Status: %s\n" -"Tijdsduur: %i mins %i secs\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Uitgaande oproep" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Gereed." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Informatie" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Zoekt de lokatie van het telefoonnummer..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Kon dit nummer niet vinden." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Verbinden" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "Kon niet oproepen" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "belt u." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Verbonden." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "afgebroken" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 #, fuzzy msgid "Could not pause the call" msgstr "Kon niet oproepen" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 #, fuzzy msgid "Pausing the current call..." msgstr "Kon niet oproepen" @@ -2011,149 +1984,174 @@ msgstr "Informatie" msgid "Unknown-bug" msgstr "" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "Kon pixmap bestand %s niet vinden" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "Externe diensten" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Externe diensten" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "Chat met %s" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Oproep beeindigd" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "" "Oproepen of\n" "beantwoorden" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Oproep beeindigd." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Gebruiker is bezet." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Gebruiker is tijdelijk niet beschikbaar." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "De gebruiker wenst niet gestoord te worden." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Oproep geweigerd." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 #, fuzzy msgid "Redirected" msgstr "Doorgeschakeld naar %s..." -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Oproep geannuleerd." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registratie op %s gelukt." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "Registratie op %s gelukt." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "Registratie op %s mislukt (time-out)." -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Authorisatie gegevens" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, fuzzy, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "U heeft %i oproep(en) gemist." msgstr[1] "U heeft %i oproep(en) gemist." +#~ msgid "aborted" +#~ msgstr "afgebroken" + +#~ msgid "completed" +#~ msgstr "voltooid" + +#~ msgid "missed" +#~ msgstr "gemist" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s op %s\n" +#~ "Van: %s\n" +#~ "Aan: %s\n" +#~ "Status: %s\n" +#~ "Tijdsduur: %i mins %i secs\n" + +#~ msgid "Outgoing call" +#~ msgstr "Uitgaande oproep" + #~ msgid "" #~ "Could not parse given sip address. A sip url usually looks like sip:" #~ "user@domain" diff --git a/po/pl.po b/po/pl.po index 819c7ab7e..62e06d793 100644 --- a/po/pl.po +++ b/po/pl.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 0.7.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2003-08-22 12:50+0200\n" "Last-Translator: Robert Nasiadek \n" "Language-Team: Polski \n" @@ -15,12 +15,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "" @@ -30,51 +30,51 @@ msgstr "" msgid "Recent calls (%i)" msgstr "Dzwonie do " -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "Połączenie odwołane." -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "linia" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -94,7 +94,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "Nie można znaleźć pixmapy: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "" @@ -142,7 +142,7 @@ msgstr "" msgid "Call with %s" msgstr "" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -151,76 +151,76 @@ msgid "" "If you answer no, this person will be temporarily blacklisted." msgstr "" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Połączenie odwołane." -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 #, fuzzy msgid "Call ended" msgstr "Rozmowa odrzucona." -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "linia" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "Połączenie odwołane." -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Dzwonie do " -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "" @@ -234,7 +234,7 @@ msgstr "Książka adresowa" msgid "Presence status" msgstr "Obecność" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nazwa" @@ -252,142 +252,142 @@ msgstr "" msgid "Search in %s directory" msgstr "" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "(Brak informacji kontaktowych !)" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Jakość (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min przepustowość (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametr" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Włączone" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Wyłączone" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 #, fuzzy msgid "None" msgstr "Brak." -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -457,110 +457,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "Podręcznik" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "Twoje hasło:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Podręcznik" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Twoje hasło:" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Podręcznik" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Twoje hasło:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -629,135 +633,135 @@ msgstr "Połączenie odwołane." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "Dzwonie do " -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Dzwonie do " -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "Dzwonie do " -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Dzwonie do " -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "Rozmowa odrzucona." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Połączenie odwołane." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -792,64 +796,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Użyj tego urządzenia dźwięku:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Źródło nagrywania:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Użyj tego urządzenia dźwięku:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1833,96 +1837,70 @@ msgstr "Lącze" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 #, fuzzy msgid "Ready" msgstr "Gotowy." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Informacja" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "" -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "" #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 #, fuzzy msgid "Contacting" msgstr "Dzwonie do " -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "Nie można znaleźć pixmapy: %s" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "dzwoni do Ciebie." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Połączony" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "Połączenie odwołane." -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "" @@ -1991,143 +1969,143 @@ msgstr "Informacja" msgid "Unknown-bug" msgstr "" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "Nie można znaleźć pixmapy: %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "Rejestruje..." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Rejestruje..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Rozmowa odrzucona." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "" "Zadzwoń lub\n" "Odpowiedz" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 #, fuzzy msgid "Call terminated." msgstr "Rozmowa odrzucona." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Osoba jest zajęta." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Osoba jest tymczasowo niedostępna." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Osoba nie chce, aby jej przeszkadzać." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Rozmowa odrzucona." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Połączenie odwołane." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, fuzzy, c-format msgid "Registration on %s successful." msgstr "Rejestracja powiodła się." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "Rejestracja powiodła się." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "Rejestracja powiodła się." -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Informacje o kodeku" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." diff --git a/po/pt_BR.po b/po/pt_BR.po index 21b309da3..c30d3787a 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone-1.1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2006-07-11 23:30+0200\n" "Last-Translator: Rafael Caesar Lenzi \n" "Language-Team: pt_BR \n" @@ -17,12 +17,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, fuzzy, c-format msgid "Call %s" msgstr "Histórico de chamadas" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "" @@ -32,52 +32,52 @@ msgstr "" msgid "Recent calls (%i)" msgstr "Contatando " -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "Abortado" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "Perdido" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "linha" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -97,7 +97,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "Não é possível achar arquivo pixmap: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "" @@ -145,7 +145,7 @@ msgstr "" msgid "Call with %s" msgstr "Bate-papo com %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -154,76 +154,76 @@ msgid "" "If you answer no, this person will be temporarily blacklisted." msgstr "" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Linphone - Histórico de chamadas" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 #, fuzzy msgid "Call ended" msgstr "Chamada cancelada." -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Camadas recebidas" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "linha" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "Abortado" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Contatando " -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "" @@ -236,7 +236,7 @@ msgstr "Catálogo de endereços" msgid "Presence status" msgstr "Status de presença" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nome" @@ -255,142 +255,142 @@ msgstr "Sala de bate-papo" msgid "Search in %s directory" msgstr "" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "Edicar informação de contato" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Taxa (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Bitrate mínimo (kbits/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parâmetros" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Ativado" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Desativado" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 #, fuzzy msgid "Account" msgstr "Aceitar" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Nenhum" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -460,110 +460,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "Usuário" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "Senha:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Usuário" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Senha:" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Usuário" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Senha:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -633,135 +637,135 @@ msgstr "Histórico de chamadas" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "Contatando " -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Camadas recebidas" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "Contatando " -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Contatando " -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "Chamada cancelada." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Histórico de chamadas" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -796,64 +800,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Dispositivo de captura de som:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Origem de gravação:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Dispositivo de som:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1839,100 +1843,70 @@ msgstr "Contatando " msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "Abortado" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "Competado" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "Perdido" - -#: ../coreapi/linphonecore.c:253 -#, fuzzy, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s em %sDe: %s\n" -"Para: %s\n" -"Status: %s\n" -"Duração: %i min %i seg\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Chamadas efetuadas" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 #, fuzzy msgid "Ready" msgstr "Pronto." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Informações" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Procurando por telefone de destino..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Não foi possível encontrar este número." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 #, fuzzy msgid "Contacting" msgstr "Contatando " -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "Não é possível achar arquivo pixmap: %s" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "está chamado você." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Conectado." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "Abortado" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "" @@ -1999,149 +1973,174 @@ msgstr "Informações" msgid "Unknown-bug" msgstr "" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "Não é possível achar arquivo pixmap: %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "Serviços remotos" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Serviços remotos" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "Bate-papo com %s" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Chamada cancelada." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "" "Ligar ou\n" "atender" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "" -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Usuário está ocupado." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Usuário está temporáriamente indisponível." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 #, fuzzy msgid "Redirected" msgstr "Redirecionado para %s..." -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Histórico de chamadas" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, fuzzy, c-format msgid "Registration on %s successful." msgstr "Registro em %s efetuado." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "Registro em %s efetuado." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "Registro falhou (tempo esgotado)." -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Informações de autenticação" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, fuzzy, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Você perdeu %i ligação(ões)." msgstr[1] "Você perdeu %i ligação(ões)." +#~ msgid "aborted" +#~ msgstr "Abortado" + +#~ msgid "completed" +#~ msgstr "Competado" + +#~ msgid "missed" +#~ msgstr "Perdido" + +#, fuzzy +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s em %sDe: %s\n" +#~ "Para: %s\n" +#~ "Status: %s\n" +#~ "Duração: %i min %i seg\n" + +#~ msgid "Outgoing call" +#~ msgstr "Chamadas efetuadas" + #~ msgid "Chat with %s" #~ msgstr "Bate-papo com %s" diff --git a/po/ru.po b/po/ru.po index d2a440a31..6e916a63c 100644 --- a/po/ru.po +++ b/po/ru.po @@ -1,57 +1,56 @@ # SIP Telephony Application. -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # Simon Morlat , 2001. +# Maxim Prokopyev , 2010. +# Alexey Loginov , 2014. # msgid "" msgstr "" -"Project-Id-Version: linphone 0.7.1\n" +"Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" -"PO-Revision-Date: 2010-01-22 18:43+0300\n" -"Last-Translator: Maxim Prokopyev \n" -"Language-Team: Russian \n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" +"PO-Revision-Date: 2014-09-10 01:32+0300\n" +"Last-Translator: AlexL \n" +"Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" -msgstr "Набрать %s" +msgstr "Звонок %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" -msgstr "Послать текст к %s" +msgstr "Послать текст для %s" #: ../gtk/calllogs.c:232 -#, fuzzy, c-format +#, c-format msgid "Recent calls (%i)" -msgstr "Соединен с" +msgstr "Последние вызовы (%i)" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" -msgstr "н/д" +msgstr "—" -#: ../gtk/calllogs.c:315 -#, fuzzy +#: ../gtk/calllogs.c:317 msgid "Aborted" -msgstr "отмененный" +msgstr "Прервано" -#: ../gtk/calllogs.c:318 -#, fuzzy +#: ../gtk/calllogs.c:320 msgid "Missed" -msgstr "пропущенный" +msgstr "Пропущено" -#: ../gtk/calllogs.c:321 -#, fuzzy +#: ../gtk/calllogs.c:323 msgid "Declined" -msgstr "Отклонить" +msgstr "Отклонено" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" @@ -59,7 +58,7 @@ msgstr[0] "%i минута" msgstr[1] "%i минуты" msgstr[2] "%i минут" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" @@ -67,30 +66,28 @@ msgstr[0] "%i секунда" msgstr[1] "%i секунды" msgstr[2] "%i секунд" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 -#, fuzzy, c-format +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 +#, c-format msgid "%s\t%s" -msgstr "" -"%s\t%s\tКачество: %s\n" -"%s\t%s %s\t" +msgstr "%s\t%s" -#: ../gtk/calllogs.c:335 -#, fuzzy, c-format +#: ../gtk/calllogs.c:337 +#, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -"%s\t%s\tКачество: %s\n" -"%s\t%s %s\t" +"%s\tКачество: %s\n" +"%s\t%s\t" -#: ../gtk/calllogs.c:341 -#, fuzzy, c-format +#: ../gtk/calllogs.c:343 +#, c-format msgid "" "%s\t\n" "%s" msgstr "" -"%s\t%s\tКачество: %s\n" -"%s\t%s %s\t" +"%s\t\n" +"%s" #: ../gtk/conference.c:38 ../gtk/main.ui.h:13 msgid "Conference" @@ -98,67 +95,65 @@ msgstr "Конференция" #: ../gtk/conference.c:46 msgid "Me" -msgstr "Я" +msgstr "Мне" #: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 #, c-format msgid "Couldn't find pixmap file: %s" msgstr "Невозможно найти графический файл: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" -msgstr "Неверный sip-контакт!" +msgstr "Неверный sip контакт!" #: ../gtk/main.c:107 msgid "log to stdout some debug information while running." msgstr "" "Вывод некоторой отладочной информации на устройство стандартного вывода во " -"время работы" +"время работы." #: ../gtk/main.c:114 msgid "path to a file to write logs into." -msgstr "путь к файлу для записи журнала работы." +msgstr "Путь к файлу для записи логов." #: ../gtk/main.c:121 msgid "Start linphone with video disabled." -msgstr "" +msgstr "Запуск linphone с видео отключен." #: ../gtk/main.c:128 msgid "Start only in the system tray, do not show the main interface." -msgstr "Запускать только в системном лотке, не показывая главное окно" +msgstr "Показывать только в системном лотке, не запуская главное окно." #: ../gtk/main.c:135 msgid "address to call right now" -msgstr "адрес для звонка" +msgstr "Адрес для звонка прямо сейчас." #: ../gtk/main.c:142 msgid "if set automatically answer incoming calls" -msgstr "автоматически принимать входящие вызовы, если включено" +msgstr "Если установлено, то автоматический приём входящих звонков." #: ../gtk/main.c:149 msgid "" "Specifiy a working directory (should be the base of the installation, eg: c:" "\\Program Files\\Linphone)" msgstr "" -"Укажите рабочий каталог (должен содержать установленные файлы приложения, " -"например: c:\\Program Files\\Linphone)" +"Определить рабочий каталог (относительно каталога установки, например: c:" +"\\Program Files\\Linphone)" #: ../gtk/main.c:156 -#, fuzzy msgid "Configuration file" -msgstr "Подтверждение" +msgstr "Файл конфигурации" #: ../gtk/main.c:163 -#, fuzzy msgid "Run the audio assistant" -msgstr "Помощник настройки учётной записи" +msgstr "Запустить помощника аудио" #: ../gtk/main.c:590 #, c-format msgid "Call with %s" -msgstr "Чат с %s" +msgstr "Звонок с %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -166,81 +161,81 @@ msgid "" "list ?\n" "If you answer no, this person will be temporarily blacklisted." msgstr "" -"%s хочет добавить вас в свой контакт-лист.\n" -"Вы разрешаете ему(ей) видеть статус вашего присутствия или хотите добавить " -"его(её) в свой контактный лист?\n" -"Если вы ответите Нет, этот человек будет временно заблокирован." +"%s вы бы хотели быть добавленным в этот контактный лист.\n" +"Вы разрешаете ему(ей) видеть ваш статус присутствия или добавить в " +"контактный лист?\n" +"Если вы ответите Нет, эта персона будет временно в чёрном списке." -#: ../gtk/main.c:1248 -#, fuzzy, c-format +#: ../gtk/main.c:1260 +#, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" "Пожалуйста, введите пароль для пользователя %s\n" -" в домене %s:" +" для реалм (рилм) %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" -msgstr "Ошибка вызова" +msgstr "Ошибка звонка" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" -msgstr "Разговор окончен" +msgstr "Звонок окончен" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" -msgstr "Входящий вызов" +msgstr "Входящий звонок" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" -msgstr "Ответить" +msgstr "Ответ" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Отклонить" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" -msgstr "Вызов приостановлен" +msgstr "Звонок приостановлен" -#: ../gtk/main.c:1380 -#, fuzzy, c-format +#: ../gtk/main.c:1392 +#, c-format msgid "by %s" -msgstr "Порты" +msgstr "%s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" -msgstr "" +msgstr "%s предложил запустить видео. Вы принимаете?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" -msgstr "Ссылка на сайт" +msgstr "Домашняя страница" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" -msgstr "Linphone - видео-телефон для интернета" +msgstr "Linphone - интернет видео телефон" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" -msgstr "%s (По умолчанию)" +msgstr "%s (по умолчанию)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" -msgstr "Мы переведены на %s" +msgstr "Мы передали в %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -"На этом компьютере не обнаружено ни одной звуковой карты.\n" -"Вы не сможете совершать или принимать аудио-вызовы." +"Звуковые карты не были обнаружены на этом компьютере.\n" +"Вы не сможете отправлять или получать аудио звонки." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Свободный SIP видео-телефон" @@ -252,161 +247,159 @@ msgstr "Добавить в адресную книгу" msgid "Presence status" msgstr "Статус присутствия" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Имя" #: ../gtk/friendlist.c:721 msgid "Call" -msgstr "Вызов" +msgstr "Звонок" #: ../gtk/friendlist.c:726 -#, fuzzy msgid "Chat" -msgstr "Комната чата" +msgstr "Чат" #: ../gtk/friendlist.c:756 #, c-format msgid "Search in %s directory" msgstr "Поиск в директории %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Редактировать контакт '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Удалить контакт '%s'" -#: ../gtk/friendlist.c:977 -#, fuzzy, c-format +#: ../gtk/friendlist.c:978 +#, c-format msgid "Delete chat history of '%s'" -msgstr "Удалить контакт '%s'" +msgstr "Удалить историю чата для '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Добавить новый контакт из директории '%s'" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Частота (Гц)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Статус" -#: ../gtk/propertybox.c:568 -#, fuzzy +#: ../gtk/propertybox.c:570 msgid "IP Bitrate (kbit/s)" -msgstr "Минимальный битрейт (кбит/с)" +msgstr "IP битрейт (КБит/сек)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Параметры" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" -msgstr "Включен" +msgstr "Разрешён" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" -msgstr "Отключен" +msgstr "Не разрешён" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" -msgstr "Учетная запись" +msgstr "Учётная запись" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Английский" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Французский" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Шведский" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Итальянский" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Испанский" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Бразильский португальский" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Польский" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Немецкий" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Русский" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Японский" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" -msgstr "Нидерландский" +msgstr "Датский" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Венгерский" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Чешский" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Китайский" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Традиционный китайский" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Норвежский" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" -msgstr "" +msgstr "Иврит" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" -msgstr "" +msgstr "Сербский" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -"Вы должны перезапустить Linphone для того, чтобы языковые настройки вступили " +"Вы должны перезагрузить linphone для того, чтобы языковые настройки вступили " "в силу." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Нет" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "SRTP" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ZRTP" @@ -416,12 +409,12 @@ msgid "" "A more recent version is availalble from %s.\n" "Would you like to open a browser to download it ?" msgstr "" -"Доступна более новая версия с %s\n" +"Доступна новая версия с %s.\n" "Открыть браузер для загрузки?" #: ../gtk/update.c:91 msgid "You are running the lastest version." -msgstr "Вы используете самую последнюю версию." +msgstr "Вы работаете с последней версией." #: ../gtk/buddylookup.c:85 msgid "Firstname, Lastname" @@ -466,454 +459,446 @@ msgstr "Создать учётную запись на linphone.org" #: ../gtk/setupwizard.c:44 msgid "I have already a linphone.org account and I just want to use it" msgstr "" -"У меня уже есть учётная запись на linphone.org и я хочу использовать её" +"Я уже имею учётную запись на linphone.org и только хочу использовать её" #: ../gtk/setupwizard.c:45 msgid "I have already a sip account and I just want to use it" -msgstr "У меня уже есть учётная запись SIP и я хочу использовать её" +msgstr "Я уже имею учётную запись sip и только хочу использовать её" #: ../gtk/setupwizard.c:46 msgid "I want to specify a remote configuration URI" -msgstr "" +msgstr "Я хочу указать удалённую конфигурацию URI" #: ../gtk/setupwizard.c:89 msgid "Enter your linphone.org username" -msgstr "Введите ваше имя пользователя на linphone.org" +msgstr "Введите ваше имя пользователя для linphone.org" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Имя пользователя:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Пароль:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" -msgstr "Введите информацию о вашей учётной записи" +msgstr "Введите вашу информацию об учётной записи" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Имя пользователя*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Пароль*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Домен*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "Прокси" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) Обязательные поля" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Имя пользователя: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Пароль: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" -msgstr "Email: (*)" +msgstr "Электронная почта: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Подтвердите ваш пароль: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "Информировать об обновлениях linphone" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -"Ошибка, непроверенная учётная запись, имя пользователя уже существует или " -"сервер недоступен.\n" -"Вернитесь и попробуйте ещё раз." +"Ошибка, учётная запись не подтверждена, имя пользователя уже используется " +"или\n" +"сервер недоступен. Пожалуйста, зайдите снова и попробуйте ещё раз." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." -msgstr "Спасибо! Учетная запись успешно настроена и готова к использованию." +msgstr "Спасибо! Учётная запись успешно настроена и готова к использованию." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -"Пожалуйста, подтвердите свою учётную запись, пройдя по ссылке, которую мы " -"только что выслали вам на электронную почту.\n" -"Затем вернитесь и нажмите на кнопку Далее." +"Пожалуйста, подтвердите вашу учётную запись, щёлкнув на ссылку, которую вы " +"только\n" +"что получили по электронной почте. Затем вернитесь сюда и нажмите кнопку " +"Далее." -#: ../gtk/setupwizard.c:564 -#, fuzzy +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" -msgstr "Помощник настройки учётной записи" +msgstr "Помощник настройки учётной записи SIP" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Добро пожаловать в помощник настройки учётной записи" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Помощник настройки учётной записи" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" -msgstr "Настройте свою учётную запись (шаг 1/1)" +msgstr "Настроить вашу учётную запись (шаг 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" -msgstr "Введите ваше имя пользователя SIP (шаг 1/1)" +msgstr "Введите ваше sip имя пользователя (шаг 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" -msgstr "Введи информация об учётной записи (шаг 1/2)" +msgstr "Введите информацию об учётной записи (шаг 1/2)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" -msgstr "Проверка (шаг 2/2)" +msgstr "Подтверждение (шаг 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Ошибка" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" -msgstr "Завершение" +msgstr "Прерывание" #: ../gtk/incall_view.c:70 ../gtk/incall_view.c:94 #, c-format msgid "Call #%i" -msgstr "Вызов #%i" +msgstr "Звонок #%i" #: ../gtk/incall_view.c:155 #, c-format msgid "Transfer to call #%i with %s" -msgstr "Перевести на #%i с %s" +msgstr "Передача позвонить #%i с %s" #: ../gtk/incall_view.c:211 ../gtk/incall_view.c:214 -#, fuzzy msgid "Not used" -msgstr "Не найден" +msgstr "Не используется" #: ../gtk/incall_view.c:221 msgid "ICE not activated" -msgstr "" +msgstr "ICE не активировано" #: ../gtk/incall_view.c:223 -#, fuzzy msgid "ICE failed" -msgstr "ICE фильтр" +msgstr "Неудача ICE" #: ../gtk/incall_view.c:225 msgid "ICE in progress" -msgstr "" +msgstr "ICE в прогрессе" #: ../gtk/incall_view.c:227 msgid "Going through one or more NATs" -msgstr "" +msgstr "Пройти через один или несколько NAT" #: ../gtk/incall_view.c:229 -#, fuzzy msgid "Direct" -msgstr "Переадресован" +msgstr "Напрямую" #: ../gtk/incall_view.c:231 msgid "Through a relay server" -msgstr "" +msgstr "Через сервер ретрансляции" #: ../gtk/incall_view.c:239 msgid "uPnP not activated" -msgstr "" +msgstr "uPnP не активировано" #: ../gtk/incall_view.c:241 -#, fuzzy msgid "uPnP in progress" -msgstr "Идет поиск Stun..." +msgstr "uPnP в прогрессе" #: ../gtk/incall_view.c:243 -#, fuzzy msgid "uPnp not available" -msgstr "недоступно" +msgstr "uPnp недоступен" #: ../gtk/incall_view.c:245 msgid "uPnP is running" -msgstr "" +msgstr "uPnP выполняется" #: ../gtk/incall_view.c:247 -#, fuzzy msgid "uPnP failed" -msgstr "ICE фильтр" +msgstr "Неудача uPnP" #: ../gtk/incall_view.c:257 ../gtk/incall_view.c:258 msgid "Direct or through server" -msgstr "" +msgstr "Напрямую или через сервер" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" +"загрузка: %f\n" +"отдача: %f (КБит/сек)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" -msgstr "" +msgid "%ix%i @ %f fps" +msgstr "%ix%i @ %f кадр/сек" -#: ../gtk/incall_view.c:301 -#, fuzzy, c-format +#: ../gtk/incall_view.c:304 +#, c-format msgid "%.3f seconds" -msgstr "%i секунда" +msgstr "%.3f секунд" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" -msgstr "" +msgstr "Повесить трубку" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." -msgstr "Вызов..." +msgstr "Звоним..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" -msgstr "Входящий вызов" +msgstr "Входящий звонок" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" -msgstr "хорошее" +msgstr "хороший" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" -msgstr "среднее" +msgstr "средний" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" -msgstr "плохое" +msgstr "плохой" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" -msgstr "очень плохое" +msgstr "очень плохой" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" -msgstr "слишком плохое" +msgstr "совсем плохой" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" -msgstr "недоступно" +msgstr "недоступен" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" -msgstr "Защищено SRTP" +msgstr "Защищённые с помощью SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Защищено ZRTP - [токен: %s]" +msgstr "Защищённые с помощью ZRTP - [знак аутентификации: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" -msgstr "Не проверен" +msgstr "Установить непроверенный" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" -msgstr "Проверен" +msgstr "Установить проверенный" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "В конференции" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" -msgstr "Соединен с" +msgstr "Звоним" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" -msgstr "Приостановленный вызов" +msgstr "Звонок приостановлен" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Звонок закончен." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" -msgstr "" +msgstr "Передача в прогрессе" -#: ../gtk/incall_view.c:794 -#, fuzzy +#: ../gtk/incall_view.c:806 msgid "Transfer done." -msgstr "Перевести" +msgstr "Передача завершена." -#: ../gtk/incall_view.c:797 -#, fuzzy +#: ../gtk/incall_view.c:809 msgid "Transfer failed." -msgstr "Перевести" +msgstr "Передача неудачна." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Продолжить" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Пауза" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" +"Записывается в\n" +"%s %s" -#: ../gtk/incall_view.c:913 -#, fuzzy +#: ../gtk/incall_view.c:926 msgid "(Paused)" -msgstr "Пауза" +msgstr "(Пауза)" #: ../gtk/loginframe.c:88 #, c-format msgid "Please enter login information for %s" -msgstr "Введите информацию для входа %s" +msgstr "Пожалуйста, введите информацию для входа %s:" #: ../gtk/config-fetching.c:57 -#, fuzzy, c-format +#, c-format msgid "fetching from %s" -msgstr "Входящий звонок от %s" +msgstr "получение от %s" #: ../gtk/config-fetching.c:73 #, c-format msgid "Downloading of remote configuration from %s failed." -msgstr "" +msgstr "Загрузка удалённой конфигурации из %s неудачна." #: ../gtk/audio_assistant.c:98 msgid "No voice detected" -msgstr "" +msgstr "Голос не обнаружен" #: ../gtk/audio_assistant.c:99 msgid "Too low" -msgstr "" +msgstr "Слишком тихо" #: ../gtk/audio_assistant.c:100 msgid "Good" -msgstr "" +msgstr "Хорошо" #: ../gtk/audio_assistant.c:101 msgid "Too loud" -msgstr "" +msgstr "Слишком громко" -#: ../gtk/audio_assistant.c:316 -#, fuzzy +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" "Добро пожаловать!\n" -"Этот помощник поможет вам использовать учётную запись SIP для ваших звонков." +"Этот помощник поможет вам сконфигурировать настройки аудио для linphone" -#: ../gtk/audio_assistant.c:326 -#, fuzzy +#: ../gtk/audio_assistant.c:328 msgid "Capture device" -msgstr "Устройство захвата:" +msgstr "Устройство захвата" -#: ../gtk/audio_assistant.c:327 -#, fuzzy +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" -msgstr "Источник записи:" +msgstr "Уровень записи" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" -msgstr "" +msgstr "Нет голоса" -#: ../gtk/audio_assistant.c:367 -#, fuzzy +#: ../gtk/audio_assistant.c:369 msgid "Playback device" -msgstr "Устройство воспроизведения:" +msgstr "Устройство воспроизведения" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" -msgstr "" +msgstr "Проиграть три сигнала" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" -msgstr "" +msgstr "Нажмите кнопку записи и скажите несколько слов" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" -msgstr "" +msgstr "Прослушайте ваш записанный голос" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" -msgstr "" +msgstr "Давайте сейчас запустим linphone" -#: ../gtk/audio_assistant.c:488 -#, fuzzy +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" -msgstr "Помощник" +msgstr "Помощник аудио" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 -#, fuzzy +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" -msgstr "Помощник настройки учётной записи" +msgstr "Помощник аудио" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" -msgstr "" +msgstr "Калибровка усиления микрофона" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" -msgstr "" +msgstr "Калибровка громкости динамика" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" -msgstr "" +msgstr "Записать и проиграть" #: ../gtk/main.ui.h:1 msgid "Callee name" -msgstr "Имя вызываемого абонента" +msgstr "Имя вызываемого" #: ../gtk/main.ui.h:2 msgid "Send" msgstr "Отправить" #: ../gtk/main.ui.h:3 -#, fuzzy msgid "End conference" -msgstr "В конференции" +msgstr "Конец конференции" #: ../gtk/main.ui.h:7 msgid "Record this call to an audio file" -msgstr "" +msgstr "Записать этот вызов в аудио файл" #: ../gtk/main.ui.h:8 msgid "Video" -msgstr "" +msgstr "Видео" #: ../gtk/main.ui.h:10 msgid "Mute" -msgstr "" +msgstr "Без звука" #: ../gtk/main.ui.h:11 msgid "Transfer" -msgstr "Перевести" +msgstr "Передача" #: ../gtk/main.ui.h:14 msgid "In call" -msgstr "Вызов" +msgstr "Входящий звонок" #: ../gtk/main.ui.h:15 msgid "Duration" @@ -921,7 +906,7 @@ msgstr "Продолжительность" #: ../gtk/main.ui.h:16 msgid "Call quality rating" -msgstr "Уровень качества звонка" +msgstr "Вызвать рейтинг качества" #: ../gtk/main.ui.h:17 msgid "All users" @@ -937,7 +922,7 @@ msgstr "ADSL" #: ../gtk/main.ui.h:20 msgid "Fiber Channel" -msgstr "Оптоволокно" +msgstr "Оптоволоконный канал" #: ../gtk/main.ui.h:21 msgid "Default" @@ -945,20 +930,19 @@ msgstr "По умолчанию" #: ../gtk/main.ui.h:22 msgid "_Options" -msgstr "_Настройки" +msgstr "_Опции" #: ../gtk/main.ui.h:23 -#, fuzzy msgid "Set configuration URI" -msgstr "Прокси/Регистратор конфигуратор" +msgstr "Установить конфигурацию URI" #: ../gtk/main.ui.h:24 msgid "Always start video" -msgstr "" +msgstr "Всегда запускать видео" #: ../gtk/main.ui.h:25 msgid "Enable self-view" -msgstr "Включить своё видео" +msgstr "Показать окно видео" #: ../gtk/main.ui.h:26 msgid "_Help" @@ -974,11 +958,11 @@ msgstr "_Домашняя страница" #: ../gtk/main.ui.h:29 msgid "Check _Updates" -msgstr "Проверить _Обновления" +msgstr "Проверить _обновления" #: ../gtk/main.ui.h:30 msgid "Account assistant" -msgstr "Помощник настройки учётной записи" +msgstr "Помощник учётной записи" #: ../gtk/main.ui.h:32 msgid "SIP address or phone number:" @@ -986,7 +970,7 @@ msgstr "SIP-адрес или номер телефона:" #: ../gtk/main.ui.h:33 msgid "Initiate a new call" -msgstr "Совершить новый вызов" +msgstr "Начать новый звонок" #: ../gtk/main.ui.h:34 msgid "Contacts" @@ -1006,7 +990,7 @@ msgstr "Добавить контакт" #: ../gtk/main.ui.h:38 msgid "Recent calls" -msgstr "Недавние вызовы" +msgstr "Последние звонки" #: ../gtk/main.ui.h:39 msgid "My current identity:" @@ -1030,7 +1014,7 @@ msgstr "Входить автоматически" #: ../gtk/main.ui.h:44 ../gtk/password.ui.h:3 msgid "UserID" -msgstr "UserID" +msgstr "Идентификатор пользователя" #: ../gtk/main.ui.h:45 msgid "Login information" @@ -1042,7 +1026,7 @@ msgstr "Добро пожаловать!" #: ../gtk/main.ui.h:47 msgid "Delete" -msgstr "" +msgstr "Удалить" #: ../gtk/about.ui.h:1 msgid "About linphone" @@ -1054,11 +1038,9 @@ msgstr "(C) Belledonne Communications,2010\n" #: ../gtk/about.ui.h:4 msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "" -"Видео-телефон для интернета, использующий стандартный протокол SIP (rfc3261)." +msgstr "Интернет видео телефон, использующий стандарт протокола SIP (rfc3261)." #: ../gtk/about.ui.h:5 -#, fuzzy msgid "" "fr: Simon Morlat\n" "en: Simon Morlat and Delphine Perreau\n" @@ -1084,18 +1066,19 @@ msgstr "" "pl: Robert Nasiadek \n" "cs: Petr Pisar \n" "hu: anonymous\n" +"he: Eli Zaretskii \n" #: ../gtk/contact.ui.h:2 msgid "SIP Address" -msgstr "SIP-адрес" +msgstr "SIP адрес" #: ../gtk/contact.ui.h:3 msgid "Show this contact presence status" -msgstr "Показывать статус присутствия этого контакта" +msgstr "Показывать этому контакту статус присутствия" #: ../gtk/contact.ui.h:4 msgid "Allow this contact to see my presence status" -msgstr "Разрешить этому контакту видеть статус моего присутствия" +msgstr "Разрешить этому контакту видеть мой статус присутствия" #: ../gtk/contact.ui.h:5 msgid "Contact information" @@ -1107,15 +1090,15 @@ msgstr "Окно отладки linphone" #: ../gtk/log.ui.h:2 msgid "Scroll to end" -msgstr "Прокрутите до конца" +msgstr "Прокрутка в конец" #: ../gtk/password.ui.h:1 msgid "Linphone - Authentication required" -msgstr "Linphone - Необходима аутентификация" +msgstr "Linphone - необходима регистрация" #: ../gtk/password.ui.h:2 msgid "Please enter the domain password" -msgstr "Введите пароль" +msgstr "Введите пароль для домена" #: ../gtk/call_logs.ui.h:1 msgid "Call history" @@ -1127,19 +1110,19 @@ msgstr "Очистить всё" #: ../gtk/call_logs.ui.h:3 msgid "Call back" -msgstr "Перезвонить" +msgstr "Позвонить повторно" #: ../gtk/sip_account.ui.h:1 msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Настроить учётную запись SIP" +msgstr "Linphone - настроить учётную запись SIP" #: ../gtk/sip_account.ui.h:2 msgid "Your SIP identity:" -msgstr "Идентификатор SIP:" +msgstr "Ваш идентификатор SIP:" #: ../gtk/sip_account.ui.h:3 msgid "Looks like sip:@" -msgstr "Похоже на sip:@" +msgstr "Выглядит как sip:<имя_пользователя>@<домен>" #: ../gtk/sip_account.ui.h:4 msgid "sip:" @@ -1147,46 +1130,43 @@ msgstr "sip:" #: ../gtk/sip_account.ui.h:5 msgid "SIP Proxy address:" -msgstr "Адрес SIP-прокси:" +msgstr "Адрес SIP прокси:" #: ../gtk/sip_account.ui.h:6 msgid "Looks like sip:" -msgstr "Похоже на sip:" +msgstr "Выглядит как sip:<прокси имя_хоста>" #: ../gtk/sip_account.ui.h:7 msgid "Registration duration (sec):" msgstr "Продолжительность регистрации (сек):" #: ../gtk/sip_account.ui.h:8 -#, fuzzy msgid "Contact params (optional):" -msgstr "Маршрут (необязательно):" +msgstr "Параметры контакта (опционально):" #: ../gtk/sip_account.ui.h:9 msgid "AVPF regular RTCP interval (sec):" -msgstr "" +msgstr "AVPF постоянный интервал RTCP (сек):" #: ../gtk/sip_account.ui.h:10 msgid "Route (optional):" -msgstr "Маршрут (необязательно):" +msgstr "Маршрут (опционально):" #: ../gtk/sip_account.ui.h:11 -#, fuzzy msgid "Transport" -msgstr "Транспорт" +msgstr "Транспорт" #: ../gtk/sip_account.ui.h:12 msgid "Register" -msgstr "Зарегистрироваться" +msgstr "Регистрация" #: ../gtk/sip_account.ui.h:13 msgid "Publish presence information" -msgstr "Опубликовывать статус присутствия" +msgstr "Опубликовать статус присутствия" #: ../gtk/sip_account.ui.h:14 -#, fuzzy msgid "Enable AVPF" -msgstr "Включить" +msgstr "Разрешить AVPF" #: ../gtk/sip_account.ui.h:15 msgid "Configure a SIP account" @@ -1194,15 +1174,15 @@ msgstr "Настроить учётную запись SIP" #: ../gtk/parameters.ui.h:1 msgid "anonymous" -msgstr "" +msgstr "аноним" #: ../gtk/parameters.ui.h:2 msgid "GSSAPI" -msgstr "" +msgstr "GSSAPI" #: ../gtk/parameters.ui.h:3 msgid "SASL" -msgstr "" +msgstr "SASL" #: ../gtk/parameters.ui.h:4 msgid "default soundcard" @@ -1214,7 +1194,7 @@ msgstr "звуковая карта" #: ../gtk/parameters.ui.h:6 msgid "default camera" -msgstr "камера по умолчаию" +msgstr "камера по умолчанию" #: ../gtk/parameters.ui.h:7 msgid "CIF" @@ -1250,11 +1230,11 @@ msgstr "Настройки" #: ../gtk/parameters.ui.h:15 msgid "Set Maximum Transmission Unit:" -msgstr "Установить MTU:" +msgstr "Установить MTU (максимально передаваемый блок):" #: ../gtk/parameters.ui.h:16 msgid "Send DTMFs as SIP info" -msgstr "Отправлять DTFM как SIP Info" +msgstr "Отправлять DTFM как SIP-информацию" #: ../gtk/parameters.ui.h:17 msgid "Use IPv6 instead of IPv4" @@ -1266,7 +1246,7 @@ msgstr "Транспорт" #: ../gtk/parameters.ui.h:19 msgid "Media encryption type" -msgstr "Тип шифрования потока" +msgstr "Тип медиа-шифрования" #: ../gtk/parameters.ui.h:20 msgid "Video RTP/UDP:" @@ -1278,65 +1258,59 @@ msgstr "Аудио RTP/UDP:" #: ../gtk/parameters.ui.h:22 msgid "Fixed" -msgstr "" +msgstr "Фиксированный" #: ../gtk/parameters.ui.h:23 -#, fuzzy msgid "Media encryption is mandatory" -msgstr "Тип шифрования потока" +msgstr "Медиа-шифрование обязательно" #: ../gtk/parameters.ui.h:24 msgid "Tunnel" -msgstr "Туннель" +msgstr "Тунель" #: ../gtk/parameters.ui.h:25 msgid "DSCP fields" -msgstr "" +msgstr "Поля DSCP" #: ../gtk/parameters.ui.h:26 -#, fuzzy msgid "SIP/TCP port" -msgstr "SIP порт" +msgstr "Порт SIP/TCP" #: ../gtk/parameters.ui.h:27 -#, fuzzy msgid "SIP/UDP port" -msgstr "SIP порт" +msgstr "Порт SIP/UDP" #: ../gtk/parameters.ui.h:28 msgid "Network protocol and ports" -msgstr "Протокол и порты" +msgstr "Сетевые протоколы и порты" #: ../gtk/parameters.ui.h:29 msgid "Direct connection to the Internet" -msgstr "Прямое подключение к Интернету" +msgstr "Прямое подключение к интернет" #: ../gtk/parameters.ui.h:30 -#, fuzzy msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "За NAT / брандмауэром (укажите IP-адрес шлюза ниже)" +msgstr "За NAT / брандмауэром (указать IP шлюза)" #: ../gtk/parameters.ui.h:31 msgid "Behind NAT / Firewall (use STUN to resolve)" msgstr "За NAT / брандмауэром (использовать STUN)" #: ../gtk/parameters.ui.h:32 -#, fuzzy msgid "Behind NAT / Firewall (use ICE)" -msgstr "За NAT / брандмауэром (использовать STUN)" +msgstr "За NAT / брандмауэром (использовать ICE)" #: ../gtk/parameters.ui.h:33 -#, fuzzy msgid "Behind NAT / Firewall (use uPnP)" -msgstr "За NAT / брандмауэром (использовать STUN)" +msgstr "За NAT / брандмауэром (использовать uPnP)" #: ../gtk/parameters.ui.h:34 msgid "Public IP address:" -msgstr "Внешний IP-адрес:" +msgstr "Выделенный (публичный) IP-адрес:" #: ../gtk/parameters.ui.h:35 msgid "Stun server:" -msgstr "Сервер STUN:" +msgstr "STUN сервер:" #: ../gtk/parameters.ui.h:36 msgid "NAT and Firewall" @@ -1348,11 +1322,11 @@ msgstr "Настройки сети" #: ../gtk/parameters.ui.h:38 msgid "Ring sound:" -msgstr "Звук звонка:" +msgstr "Мелодия звонка:" #: ../gtk/parameters.ui.h:39 msgid "ALSA special device (optional):" -msgstr "Специальное устройство ALSA (необязательно):" +msgstr "Специальное устройство ALSA (опционально)" #: ../gtk/parameters.ui.h:40 msgid "Capture device:" @@ -1368,24 +1342,23 @@ msgstr "Устройство воспроизведения:" #: ../gtk/parameters.ui.h:43 msgid "Enable echo cancellation" -msgstr "Включить подавление эхо" +msgstr "Разрешить подавление эха" #: ../gtk/parameters.ui.h:44 msgid "Audio" -msgstr "Звук" +msgstr "Аудио" #: ../gtk/parameters.ui.h:45 msgid "Video input device:" -msgstr "Устройство захвата видео:" +msgstr "Устройство для вывода видео:" #: ../gtk/parameters.ui.h:46 msgid "Prefered video resolution:" msgstr "Предпочтительное разрешение видео:" #: ../gtk/parameters.ui.h:47 -#, fuzzy msgid "Video output method:" -msgstr "Устройство захвата видео:" +msgstr "Метод вывода видео:" #: ../gtk/parameters.ui.h:48 msgid "Video" @@ -1398,19 +1371,20 @@ msgstr "Настройки мультимедиа" #: ../gtk/parameters.ui.h:50 msgid "This section defines your SIP address when not using a SIP account" msgstr "" -"Эта секция устанавливает ваш SIP-адрес, когда вы не используете SIP-аккаунт" +"Эта секция определяет ваш SIP адрес, когда вы не используете учётную запись " +"SIP" #: ../gtk/parameters.ui.h:51 msgid "Your display name (eg: John Doe):" -msgstr "Отображаемое имя (напр.: Иван Сидоров):" +msgstr "Отображаемое имя (например: Иван Сидоров):" #: ../gtk/parameters.ui.h:52 msgid "Your username:" -msgstr "Имя пользователя:" +msgstr "Ваше имя пользователя:" #: ../gtk/parameters.ui.h:53 msgid "Your resulting SIP address:" -msgstr "Результирующий SIP-адрес:" +msgstr "Ваш результирующий SIP адрес:" #: ../gtk/parameters.ui.h:54 msgid "Default identity" @@ -1434,7 +1408,7 @@ msgstr "Удалить" #: ../gtk/parameters.ui.h:59 msgid "Proxy accounts" -msgstr "Учетные записи прокси" +msgstr "Учётные записи" #: ../gtk/parameters.ui.h:60 msgid "Erase all passwords" @@ -1442,7 +1416,7 @@ msgstr "Стереть все пароли" #: ../gtk/parameters.ui.h:61 msgid "Privacy" -msgstr "Конфеденциальность" +msgstr "Секретность" #: ../gtk/parameters.ui.h:62 msgid "Manage SIP Accounts" @@ -1450,7 +1424,7 @@ msgstr "Управление учётными записями SIP" #: ../gtk/parameters.ui.h:63 ../gtk/tunnel_config.ui.h:4 msgid "Enable" -msgstr "Включить" +msgstr "Разрешить" #: ../gtk/parameters.ui.h:64 ../gtk/tunnel_config.ui.h:5 msgid "Disable" @@ -1466,27 +1440,27 @@ msgstr "0 означает \"безлимитный\"" #: ../gtk/parameters.ui.h:67 msgid "Upload speed limit in Kbit/sec:" -msgstr "Ограничение исходящего потока в кбит/сек:" +msgstr "Ограничение исходящего потока КБит/сек:" #: ../gtk/parameters.ui.h:68 msgid "Download speed limit in Kbit/sec:" -msgstr "Ограничение скорости входящего потока в кбит/сек" +msgstr "Ограничение скорости входящего потока КБит/сек:" #: ../gtk/parameters.ui.h:69 msgid "Enable adaptive rate control" -msgstr "Включить адаптивный контроль скорости" +msgstr "Разрешить адаптивное управление скоростью" #: ../gtk/parameters.ui.h:70 msgid "" "Adaptive rate control is a technique to dynamically guess the available " "bandwidth during a call." msgstr "" -"Адаптивное управление скоростью - это техника, позволяющая динамически " -"определять доступную пропускную способность сети во время звонка." +"Адаптивное управление скоростью - это технология динамического угадывания " +"доступной пропускной способности во время звонка." #: ../gtk/parameters.ui.h:71 msgid "Bandwidth control" -msgstr "Управление скоростью сети" +msgstr "Пропускная способность" #: ../gtk/parameters.ui.h:72 msgid "Codecs" @@ -1498,7 +1472,7 @@ msgstr "Язык" #: ../gtk/parameters.ui.h:74 msgid "Show advanced settings" -msgstr "Показывать расширенные настройки" +msgstr "Показать дополнительные настройки" #: ../gtk/parameters.ui.h:75 msgid "Level" @@ -1506,30 +1480,27 @@ msgstr "Уровень" #: ../gtk/parameters.ui.h:76 msgid "User interface" -msgstr "Интерфейс пользователя" +msgstr "Пользовательский интерфейс" #: ../gtk/parameters.ui.h:77 ../gtk/ldap.ui.h:2 -#, fuzzy msgid "Server address:" -msgstr "Server-Adresse:" +msgstr "Адрес сервера:" #: ../gtk/parameters.ui.h:78 ../gtk/ldap.ui.h:3 -#, fuzzy msgid "Authentication method:" -msgstr "Ошибка аутентификации" +msgstr "Метод аутентификации:" #: ../gtk/parameters.ui.h:80 msgid "label" msgstr "метка" #: ../gtk/parameters.ui.h:81 -#, fuzzy msgid "LDAP Account setup" -msgstr "Учетные записи прокси" +msgstr "Установка учётной записи LDAP" #: ../gtk/parameters.ui.h:82 msgid "LDAP" -msgstr "" +msgstr "LDAP" #: ../gtk/parameters.ui.h:83 msgid "Done" @@ -1537,7 +1508,7 @@ msgstr "Готово" #: ../gtk/buddylookup.ui.h:1 msgid "Search contacts in directory" -msgstr "Искать контакты в директории" +msgstr "Поиск контактов в директории" #: ../gtk/buddylookup.ui.h:2 msgid "Add to my list" @@ -1545,7 +1516,7 @@ msgstr "Добавить в мой список" #: ../gtk/buddylookup.ui.h:3 msgid "Search somebody" -msgstr "Найти кого-нибудь" +msgstr "Поиск кого-нибудь" #: ../gtk/waiting.ui.h:1 msgid "Linphone" @@ -1553,108 +1524,95 @@ msgstr "Linphone" #: ../gtk/waiting.ui.h:2 msgid "Please wait" -msgstr "Подождите" +msgstr "Пожалуйста, подождите" #: ../gtk/dscp_settings.ui.h:1 -#, fuzzy msgid "DSCP settings" -msgstr "Настройки" +msgstr "Настройки DSCP" #: ../gtk/dscp_settings.ui.h:2 msgid "SIP" msgstr "SIP" #: ../gtk/dscp_settings.ui.h:3 -#, fuzzy msgid "Audio RTP stream" -msgstr "Аудио RTP/UDP:" +msgstr "Аудио поток RTP" #: ../gtk/dscp_settings.ui.h:4 -#, fuzzy msgid "Video RTP stream" -msgstr "Видео RTP/UDP:" +msgstr "Видео поток RTP" #: ../gtk/dscp_settings.ui.h:5 msgid "Set DSCP values (in hexadecimal)" -msgstr "" +msgstr "Установить значения DSCP (в шестнадцатеричном формате)" #: ../gtk/call_statistics.ui.h:1 -#, fuzzy msgid "Call statistics" -msgstr "Звонк %s" +msgstr "Вызов статистики" #: ../gtk/call_statistics.ui.h:2 -#, fuzzy msgid "Audio codec" -msgstr "Аудио кодеки" +msgstr "Аудио кодек" #: ../gtk/call_statistics.ui.h:3 -#, fuzzy msgid "Video codec" -msgstr "Видео кодеки" +msgstr "Видео кодек" #: ../gtk/call_statistics.ui.h:4 msgid "Audio IP bandwidth usage" -msgstr "" +msgstr "Использование пропускной способности аудио IP" #: ../gtk/call_statistics.ui.h:5 -#, fuzzy msgid "Audio Media connectivity" -msgstr "Тип шифрования потока" +msgstr "Подключение медиа-аудио" #: ../gtk/call_statistics.ui.h:6 msgid "Video IP bandwidth usage" -msgstr "" +msgstr "Использование пропускной способности видео IP" #: ../gtk/call_statistics.ui.h:7 -#, fuzzy msgid "Video Media connectivity" -msgstr "Тип шифрования потока" +msgstr "Подключение медиа-видео" #: ../gtk/call_statistics.ui.h:8 -#, fuzzy msgid "Round trip time" -msgstr "Настройки звука" +msgstr "Округлять время в действии" #: ../gtk/call_statistics.ui.h:9 msgid "Video resolution received" -msgstr "" +msgstr "Получено разрешение видео" #: ../gtk/call_statistics.ui.h:10 -#, fuzzy msgid "Video resolution sent" -msgstr "Предпочтительное разрешение видео:" +msgstr "Разрешение видео отправлено" #: ../gtk/call_statistics.ui.h:11 -#, fuzzy msgid "RTP profile" -msgstr "RTP свойства" +msgstr "Профиль RTP" #: ../gtk/call_statistics.ui.h:12 -#, fuzzy msgid "Call statistics and information" -msgstr "Контактная информация" +msgstr "Вызов статистики и информации" #: ../gtk/tunnel_config.ui.h:1 -#, fuzzy msgid "Configure VoIP tunnel" -msgstr "Настроить учётную запись SIP" +msgstr "Настроить тунель VoIP" #: ../gtk/tunnel_config.ui.h:2 msgid "Host" -msgstr "" +msgstr "Хост" #: ../gtk/tunnel_config.ui.h:3 msgid "Port" -msgstr "" +msgstr "Порт" #: ../gtk/tunnel_config.ui.h:6 msgid "Configure tunnel" -msgstr "" +msgstr "Конфигурировать тунель" #: ../gtk/tunnel_config.ui.h:9 msgid "Configure http proxy (optional)" -msgstr "" +msgstr "Конфигурировать http прокси (опционально)" #: ../gtk/keypad.ui.h:1 msgid "D" @@ -1717,105 +1675,97 @@ msgid "1" msgstr "1" #: ../gtk/ldap.ui.h:1 -#, fuzzy msgid "LDAP Settings" -msgstr "Настройки" +msgstr "Настройки LDAP" #: ../gtk/ldap.ui.h:6 msgid "Use TLS Connection" -msgstr "" +msgstr "Использовать соединение TLS" #: ../gtk/ldap.ui.h:7 -#, fuzzy msgid "Not yet available" -msgstr "недоступно" +msgstr "Ещё недоступно" #: ../gtk/ldap.ui.h:8 -#, fuzzy msgid "Connection" -msgstr "Кодеки" +msgstr "Соединение" #: ../gtk/ldap.ui.h:9 msgid "Bind DN" -msgstr "" +msgstr "Привязать DN" #: ../gtk/ldap.ui.h:10 msgid "Authname" -msgstr "" +msgstr "Имя для аутентификации" #: ../gtk/ldap.ui.h:11 -#, fuzzy msgid "Realm" -msgstr "Название:" +msgstr "Реалм (рилм)" #: ../gtk/ldap.ui.h:12 -#, fuzzy msgid "SASL" -msgstr "Звук" +msgstr "SASL" #: ../gtk/ldap.ui.h:13 msgid "Base object:" -msgstr "" +msgstr "Базовый объект:" #: ../gtk/ldap.ui.h:15 #, no-c-format msgid "Filter (%s for name):" -msgstr "" +msgstr "Фильтр (%s для имени):" #: ../gtk/ldap.ui.h:16 msgid "Name Attribute:" -msgstr "" +msgstr "Атрибут имени:" #: ../gtk/ldap.ui.h:17 -#, fuzzy msgid "SIP address attribute:" -msgstr "SIP-адрес" +msgstr "Атрибут SIP-адреса:" #: ../gtk/ldap.ui.h:18 msgid "Attributes to query:" -msgstr "" +msgstr "Атрибуты для запроса:" #: ../gtk/ldap.ui.h:19 -#, fuzzy msgid "Search" -msgstr "Найти кого-нибудь" +msgstr "Поиск" #: ../gtk/ldap.ui.h:20 msgid "Timeout for search:" -msgstr "" +msgstr "Таймаут для поиска:" #: ../gtk/ldap.ui.h:21 msgid "Max results:" -msgstr "" +msgstr "Максимум результатов:" #: ../gtk/ldap.ui.h:22 msgid "Follow Aliases" -msgstr "" +msgstr "Следовать алиасам" #: ../gtk/ldap.ui.h:23 -#, fuzzy msgid "Miscellaneous" msgstr "Разное" #: ../gtk/ldap.ui.h:24 msgid "ANONYMOUS" -msgstr "" +msgstr "АНОНИМ" #: ../gtk/ldap.ui.h:25 msgid "SIMPLE" -msgstr "" +msgstr "ПРОСТОЙ" #: ../gtk/ldap.ui.h:26 msgid "DIGEST-MD5" -msgstr "" +msgstr "ДАЙДЖЕСТ-MD5" #: ../gtk/ldap.ui.h:27 msgid "NTLM" -msgstr "" +msgstr "NTLM" #: ../gtk/config-uri.ui.h:1 msgid "Specifying a remote configuration URI" -msgstr "" +msgstr "Указание удалённой конфигурации URI" #: ../gtk/config-uri.ui.h:2 msgid "" @@ -1825,120 +1775,93 @@ msgid "" "Linphone will restart automatically in order to fetch and take into account " "the new configuration. " msgstr "" +"Этот диалог позволяет установить HTTP или HTTPS адрес, когда конфигурация " +"будет получена при запуске.\n" +"Пожалуйста, введите или измените настройки URI ниже. После нажатия OK " +"linphone автоматически перезагрузится чтобы получить и учесть новую " +"конфигурацию в учётной записи." #: ../gtk/config-uri.ui.h:4 msgid "https://" -msgstr "" +msgstr "https://" #: ../gtk/provisioning-fetch.ui.h:1 -#, fuzzy msgid "Configuring..." -msgstr "Подключение..." +msgstr "Конфигурирование..." #: ../gtk/provisioning-fetch.ui.h:2 msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "отмененный" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "завершённый" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "пропущенный" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s в %s\n" -"От: %s\n" -"Кому: %s\n" -"Статус: %s\n" -"Длительность: %i мин %i сек\n" +msgstr "Пожалуйста, подождите пока получается конфигурация с сервера..." -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Исходящий звонок" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Готов" -#: ../coreapi/linphonecore.c:2248 -#, fuzzy +#: ../coreapi/linphonecore.c:1967 msgid "Configuring" -msgstr "Подтверждение" +msgstr "Конфигурирование" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." -msgstr "Поиск адреса для телефонного номера..." +msgstr "Поиск назначения для телефонного номера.." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." -msgstr "Не могу найти этот номер." +msgstr "Не получилось принять решение по этому номеру." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Соединение" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" -msgstr "Не удалось позвонить" +msgstr "Невозможно позвонить" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "Извините, мы превысили максимальное количество одновременных вызовов" +msgstr "" +"К сожалению, мы достигли максимального количества одновременных звонков" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" -msgstr "пытается связаться с вами" +msgstr "контактирует с вами" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." -msgstr " и ответил автоответчик." +msgstr "и спросил автоматический ответ." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." -msgstr "Изменение параметров вызова..." +msgstr "Изменение параметров звонка..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Соединён." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" -msgstr "Вызов отменён" +msgstr "Звонок отменён" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" -msgstr "Не удалось приостановить вызов" +msgstr "Невозможно приостановить звонок" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." -msgstr "Приостановление текущего вызова..." +msgstr "Приостановка текущего звонка..." #: ../coreapi/misc.c:425 msgid "Stun lookup in progress..." -msgstr "Идет поиск Stun..." +msgstr "Идет поиск STUN..." #: ../coreapi/misc.c:607 msgid "ICE local candidates gathering in progress..." -msgstr "" +msgstr "Сбор локальных кандидатов ICE в прогрессе..." #: ../coreapi/friend.c:33 msgid "Online" @@ -1970,7 +1893,7 @@ msgstr "Не беспокоить" #: ../coreapi/friend.c:54 msgid "Moved" -msgstr "Отошел" +msgstr "Отошёл" #: ../coreapi/friend.c:57 msgid "Using another messaging service" @@ -1985,211 +1908,183 @@ msgid "Pending" msgstr "В ожидании" #: ../coreapi/friend.c:66 -#, fuzzy msgid "Vacation" -msgstr "Продолжительность" +msgstr "Отдых" #: ../coreapi/friend.c:68 msgid "Unknown-bug" msgstr "Неизвестная ошибка" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -"Введеный адрес SIP-прокси является недействительным, он должен выглядеть как " +"Введённый SIP-адрес прокси является недействительным, он должен начинаться с " "\"sip:имя_хоста\"" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -"Неверные параметры идентификации SIP.\n" -"Они должны выглядеть как sip:username@proxydomain, например such as sip:" +"Неверные параметры для sip идентификации\n" +"Должно выглядеть как sip:имя_пользователя@домен_прокси, как например, sip:" "alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" -msgstr "Невозможно зайти как %s" +msgstr "Невозможно зайти как: %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." -msgstr "Абонент вызывается." +msgstr "Дистанционный звонок." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." -msgstr "Абонент вызывается..." +msgstr "Дистанционный звонок..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." -msgstr "Гудки." +msgstr "Предответное проключение." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." -msgstr "Вызов %s приостановлен." +msgstr "Звонок с %s приостановлен." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." -msgstr "Вызов отвечен %s - в ожидании." +msgstr "На звонок ответил %s - на удержании." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." -msgstr "Разговор продолжен." +msgstr "Звонок возобновлён." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." -msgstr "Вызов отвечен %s." +msgstr "На звонок ответил %s." -#: ../coreapi/callbacks.c:480 -#, fuzzy +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." -msgstr "Несовместимо, проверьте кодеки..." +msgstr "Несовместимость, проверьте кодеки или параметры безопасности..." -#: ../coreapi/callbacks.c:531 -#, fuzzy +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." -msgstr "Наш вызов продолжен..." +msgstr "Мы возобновили." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." -msgstr "" +msgstr "Мы приостановлены другой стороной." -#: ../coreapi/callbacks.c:558 -#, fuzzy +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." -msgstr "Вызов обновлён вызываемым абонентом..." +msgstr "Звонок был дистанционно обновлён." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Звонок прерван." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Пользователь занят." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Пользователь временно недоступен." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." -msgstr "Абонент не хочет отвечать." +msgstr "Пользователь не хочет чтобы его беспокоили." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Звонок отклонён." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." -msgstr "" +msgstr "Таймаут запроса." -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Переадресован" -#: ../coreapi/callbacks.c:766 -#, fuzzy +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." -msgstr "Несовместимо, проверьте кодеки..." +msgstr "Несовместимость медиа-параметров." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." -msgstr "Не удалось совершить вызов." +msgstr "Звонок не удался." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Регистрация на %s прошла успешно." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Отмена регистрации на %s завершена." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "время ожидания истекло" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Регистрация на %s не удалась: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" -msgstr "" +msgstr "Сервис недоступен, повтор" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" -msgstr "Аутентификационный токен: %s" +msgstr "Маркер проверки подлинности: %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." -msgstr[0] "У вас пропущен %i звонок." -msgstr[1] "У вас пропущено %i звонка." -msgstr[2] "У вас пропущено %i звонков." - -#~ msgid "No response." -#~ msgstr "Нет ответа." - -#~ msgid "Protocol error." -#~ msgstr "Ошибка протокола." +msgstr[0] "У вас %i пропущенный вызов." +msgstr[1] "У вас %i пропущенных вызова." +msgstr[2] "У вас %i пропущенных вызов." #~ msgid "" -#~ "Could not parse given sip address. A sip url usually looks like sip:" -#~ "user@domain" +#~ "%s\t%s\tQuality: %s\n" +#~ "%s\t%s %s\t" #~ msgstr "" -#~ "Не могу опознать sip адрес. SIP-URL обычно выглядит как sip:" -#~ "username@domainname" +#~ "%s\t%s\tКачество: %s\n" +#~ "%s\t%s %s\t" -#~ msgid "" -#~ "Your computer appears to be using ALSA sound drivers.\n" -#~ "This is the best choice. However the pcm oss emulation module\n" -#~ "is missing and linphone needs it. Please execute\n" -#~ "'modprobe snd-pcm-oss' as root to load it." -#~ msgstr "" -#~ "Ваш компьютер использует звуковой драйвер ALSA.\n" -#~ "Это лучший выбор. Однако, модуль эмуляции PCM OSS\n" -#~ "не найден, а он нужен для linphone.\n" -#~ "Пожалуйста, выполните от имени пользователя root команду 'modprobe snd-" -#~ "pcm-oss', чтобы загрузить его." +#~ msgid "Chat with %s" +#~ msgstr "Чат с %s" #~ msgid "" -#~ "Your computer appears to be using ALSA sound drivers.\n" -#~ "This is the best choice. However the mixer oss emulation module\n" -#~ "is missing and linphone needs it. Please execute\n" -#~ " 'modprobe snd-mixer-oss' as root to load it." +#~ "Please enter your password for username %s\n" +#~ " at domain %s:" #~ msgstr "" -#~ "Ваш компьютер использует звуковой драйвер ALSA.\n" -#~ "Это лучший выбор. Однако, модуль микшера OSS\n" -#~ "не найден, а он нужен для linphone.\n" -#~ "Пожалуйста, выполните от имени пользователя root команду 'modprobe snd-" -#~ "pcm-oss' чтобы загрузить его." +#~ "Пожалуйста, введите пароль для пользователя %s\n" +#~ " для домена %s:" #~ msgid "by %s" -#~ msgstr "со стороны: %s" - -#~ msgid "Keypad" -#~ msgstr "Номеронабиратель" +#~ msgstr "by %s" -#~ msgid "Chat with %s" -#~ msgstr "Чат с %s" +#~ msgid "Min bitrate (kbit/s)" +#~ msgstr "Минимальный битрейт (КБит/сек)" #~ msgid "Enable video" -#~ msgstr "Включить видео" +#~ msgstr "Разрешить видео" #~ msgid "Enter username, phone number, or full sip address" -#~ msgstr "Введите имя пользователя, номер телефона или полный SIP-адрес" +#~ msgstr "Введите имя пользователя, номер телефона или полный sip адрес" #~ msgid "Lookup:" #~ msgstr "Поиск:" @@ -2197,880 +2092,155 @@ msgstr[2] "У вас пропущено %i звонков." #~ msgid "in" #~ msgstr "в" -#~ msgid "edit" -#~ msgstr "редактировать" - -#~ msgid "" -#~ "Register to FONICS\n" -#~ "virtual network !" -#~ msgstr "" -#~ "Регистрация в \n" -#~ "виртуальной сети FONICS!" - -#~ msgid "We are being paused..." -#~ msgstr "Мы на паузе..." - -#~ msgid "No common codecs" -#~ msgstr "Нет общих кодеков" - -#~ msgid "Please choose a username:" -#~ msgstr "Выберите имя пользователя:" - -#~ msgid "Checking if '%s' is available..." -#~ msgstr "Проверка доступности '%s'..." - -#~ msgid "Please wait..." -#~ msgstr "Ждите..." - -#~ msgid "Sorry this username already exists. Please try a new one." -#~ msgstr "Такое имя пользователя уже существует. Попробуйте выбрать другое." - -#~ msgid "Ok !" -#~ msgstr "Ок!" - -#~ msgid "Communication problem, please try again later." -#~ msgstr "Проблемы со связью, повторите попытку позже." - -#~ msgid "Choosing a username" -#~ msgstr "Имя пользователя:" - -#~ msgid "Verifying" -#~ msgstr "Проверка" - -#~ msgid "Creating your account" -#~ msgstr "Создание аккаунта" - -#~ msgid "Now ready !" -#~ msgstr "Готово !" - -#, fuzzy -#~ msgid "Unmute" -#~ msgstr "Безлимитный" - -#~ msgid "Contact list" -#~ msgstr "Список контактов" - -#, fuzzy -#~ msgid "Audio & video" -#~ msgstr "Аудио и Видео" - -#~ msgid "Audio only" -#~ msgstr "Только Аудио" - -#~ msgid "Duration:" -#~ msgstr "Продолжительность:" - -#, fuzzy -#~ msgid "_Call history" -#~ msgstr "История звонков" - -#~ msgid "_Linphone" -#~ msgstr "_Linphone" - -#~ msgid "gtk-cancel" -#~ msgstr "Отмена" - -#~ msgid "gtk-ok" -#~ msgstr "Ок" - -#~ msgid "Register at startup" -#~ msgstr "Регистрация при запуске" - -#~ msgid "gtk-close" -#~ msgstr "Закрыть" - -#~ msgid "ITU-G.711 alaw encoder" -#~ msgstr "ITU-G.711 alaw кодировщик" - -#~ msgid "ITU-G.711 alaw decoder" -#~ msgstr "ITU-G.711 alaw декодер" - -#~ msgid "Alsa sound source" -#~ msgstr "Источник ALSA" - -#~ msgid "DTMF generator" -#~ msgstr "Генератор DTMF" - -#~ msgid "The GSM full-rate codec" -#~ msgstr "Кодек GSM full-rate" - -#~ msgid "The GSM codec" -#~ msgstr "Кодек GSM" - -#~ msgid "A filter to make conferencing" -#~ msgstr "Фильтр конференций" - -#, fuzzy -#~ msgid "Echo canceller using speex library" -#~ msgstr "Подавление эхо с использование библиотеки speex" - -#~ msgid "A filter that reads from input and copy to its multiple outputs." -#~ msgstr "Фильтр, перенаправляющий входящий поток в несколько потоков вывода." - -#~ msgid "The theora video encoder from xiph.org" -#~ msgstr "Theora видео декодер с xiph.org" - -#~ msgid "The theora video decoder from xiph.org" -#~ msgstr "Theora видео декодер с xiph.org" - -#~ msgid "ITU-G.711 ulaw encoder" -#~ msgstr "ITU-G.711 ulaw кодировщик" - -#~ msgid "ITU-G.711 ulaw decoder" -#~ msgstr "ITU-G.711 ulaw декодер" - -#~ msgid "A H.263 decoder using ffmpeg library" -#~ msgstr "H.263 декодер ( использует ffmpeg )" - -#~ msgid "A MPEG4 decoder using ffmpeg library" -#~ msgstr "MPEG4 декодер ( использует ffmpeg )" - -#, fuzzy -#~ msgid "A RTP/JPEG decoder using ffmpeg library" -#~ msgstr "MJPEG декодер ( использует ffmpeg )" - -#~ msgid "A MJPEG decoder using ffmpeg library" -#~ msgstr "MJPEG декодер ( использует ffmpeg )" - -#~ msgid "A snow decoder using ffmpeg library" -#~ msgstr "snow декодер ( использует ffmpeg )" - -#~ msgid "A video H.263 encoder using ffmpeg library." -#~ msgstr "H.263 видео-кодировщик ( использует ffmpeg )" - -#~ msgid "" -#~ "A video H.263 encoder using ffmpeg library. It is compliant with old " -#~ "RFC2190 spec." -#~ msgstr "H.263 видео-кодировщик ( использует ffmpeg ). Совместим с RFC2190" - -#~ msgid "A video MPEG4 encoder using ffmpeg library." -#~ msgstr "MPEG4 видео-кодировщик ( использует ffmpeg )." - -#~ msgid "A video snow encoder using ffmpeg library." -#~ msgstr "snow видео-кодировщик ( использует ffmpeg )." - -#, fuzzy -#~ msgid "A RTP/MJPEG encoder using ffmpeg library." -#~ msgstr "MJPEG декодер ( использует ffmpeg )" - -#~ msgid "" -#~ "A video H.263 encoder using ffmpeg library, compliant with old RFC2190 " -#~ "spec." -#~ msgstr "H.263 видео-кодировщик ( использует ffmpeg ). Совместим с RFC2190" - -#, fuzzy -#~ msgid "A MJPEG encoder using ffmpeg library." -#~ msgstr "MJPEG декодер ( использует ffmpeg )" - -#, fuzzy -#~ msgid "Inter ticker communication filter." -#~ msgstr "Ошибка связи с сервером" - -#~ msgid "" -#~ "Your machine appears to be connected to an IPv6 network. By default " -#~ "linphone always uses IPv4. Please update your configuration if you want " -#~ "to use IPv6" -#~ msgstr "" -#~ "Ваш компьютер подключен по IPv6. Linphone по умолчанию использует IPv4. " -#~ "Пожалуйста, обновите настройки если хотите использовать IPv6." - -#, fuzzy -#~ msgid "Show debug messages" -#~ msgstr "Показать окно ошибок" - -#~ msgid "Start call" -#~ msgstr "Вызов" - -#~ msgid "_Modes" -#~ msgstr "_Режимы" - -#~ msgid "Created by Simon Morlat\n" -#~ msgstr "Создан Simon Morlat\n" - -#~ msgid "Accept" -#~ msgstr "Принять" - -#~ msgid "Incoming call from" -#~ msgstr "Входящий вызов от" - -#~ msgid "Linphone - Incoming call" -#~ msgstr "Linphone - Входящий вызов" - -#~ msgid "default soundcard\n" -#~ msgstr "звуковая карта по умолчанию\n" - -#~ msgid "" -#~ "Remote end seems to have disconnected, the call is going to be closed." -#~ msgstr "Удалённый узел отключился, звонок завершён." - -#~ msgid "Sorry, having multiple simultaneous calls is not supported yet !" -#~ msgstr "Одновременные вызовы пока не поддерживается!" - -#~ msgid "gtk-go-down" -#~ msgstr "Вниз" - -#~ msgid "gtk-go-up" -#~ msgstr "Вверх" - -#~ msgid "gtk-media-play" -#~ msgstr "Проиграть" - -#~ msgid "Could not reach destination." -#~ msgstr "Невозможно соединиться." - -#~ msgid "Request Cancelled." -#~ msgstr "Запрос отменён." - -#~ msgid "Bad request" -#~ msgstr "Неверный запрос" - -#~ msgid "User cannot be found at given address." -#~ msgstr "Пользователь не может быть найден." - -#~ msgid "Remote user cannot support any of proposed codecs." -#~ msgstr "" -#~ "Удалённый пользователь не поддерживает ни одного из предложенных кодеков." - -#~ msgid "Timeout." -#~ msgstr "Таймаут." - -#~ msgid "Remote host was found but refused connection." -#~ msgstr "Удалённый узел был найден, но отказал в соединении." - -#~ msgid "" -#~ "User is not reachable at the moment but he invites you\n" -#~ "to contact him using the following alternate resource:" -#~ msgstr "" -#~ "Пользователь не доступен в данный момент, но\n" -#~ "приглашает Вас пообщаться на альтернативном ресурсе:" - -#~ msgid "Digits" -#~ msgstr "Цифры" - -#~ msgid "Main view" -#~ msgstr "Главное окно" - -#~ msgid "No nat/firewall address supplied !" -#~ msgstr "NAT/firewall адрес не установлен !" - -#~ msgid "Invalid nat address '%s' : %s" -#~ msgstr "Неверный NAT адрес '%s' : '%s'" - -#~ msgid "Gone" -#~ msgstr "Ушёл" - -#~ msgid "Waiting for Approval" -#~ msgstr "Ожидание утверждения" - -#~ msgid "Be Right Back" -#~ msgstr "Скоро вернусь" - -#~ msgid "On The Phone" -#~ msgstr "На телефоне" - -#~ msgid "Out To Lunch" -#~ msgstr "На обеде" - -#~ msgid "Closed" -#~ msgstr "Закрыто" - -#~ msgid "Unknown" -#~ msgstr "Неизвестно" - -#~ msgid "gtk-connect" -#~ msgstr "Соединить" - -#~ msgid "gtk-find" -#~ msgstr "Найти" - -#~ msgid "_View" -#~ msgstr "_Вид" - -#~ msgid "gtk-about" -#~ msgstr "О программе" - -#~ msgid "gtk-help" -#~ msgstr "Помощь" - -#~ msgid "gtk-preferences" -#~ msgstr "Параметры" - -#~ msgid "" -#~ "Show All\n" -#~ "Show Online" -#~ msgstr "" -#~ "Показать все\n" -#~ "Показать Online" - -#~ msgid "Display filters" -#~ msgstr "Показать фильтры" - -#~ msgid "I'm not behing a firewall" -#~ msgstr "Я не за firewall" - -#~ msgid "I'm behind a firewall, use supplied public IP address" -#~ msgstr "Я за firewall, использовать доступный IP адрес" - -#~ msgid "Use the supplied stun server above and do as best as possible" -#~ msgstr "Использовать доступный Stun сервер и делать так хорошо как возможно" - -#~ msgid "Go" -#~ msgstr "Старт" - -#~ msgid "Address book" -#~ msgstr "Адресная книга" - -#~ msgid "Shows calls" -#~ msgstr "Показать звонки" - -#~ msgid "Exit" -#~ msgstr "Выход" - -#~ msgid "Shows the address book" -#~ msgstr "Показать адресную книгу" - -#~ msgid "..." -#~ msgstr "..." - -#~ msgid "Proxy to use:" -#~ msgstr "Какой узел использовать:" - -#~ msgid "" -#~ "Hangup\n" -#~ "or refuse" -#~ msgstr "" -#~ "Прервать\n" -#~ "или отказать" - -#~ msgid "Or chat !" -#~ msgstr "Или Чат ! " - -#~ msgid "Show more..." -#~ msgstr "Показать больше..." - -#~ msgid "Playback level:" -#~ msgstr "Уровень воспроизведения:" - -#~ msgid "Recording level:" -#~ msgstr "Уровень записи:" - -#~ msgid "Ring level:" -#~ msgstr "Уровень звонка:" - -#~ msgid "Controls" -#~ msgstr "Управление" - -#~ msgid "Reachable" -#~ msgstr "Доступен" - -#~ msgid "Busy, I'll be back in " -#~ msgstr "Занят, я вернусь через " - -#~ msgid "The other party will be informed that you'll be back in X minutes" -#~ msgstr "Другая часть информирует, что Вы вернётесь через X минут" - -#~ msgid "mn" -#~ msgstr "мн" - -#~ msgid "Moved temporarily" -#~ msgstr "Временно переехал" - -#~ msgid "Alternative service" -#~ msgstr "Альтернативный сервис" - -#~ msgid "URL:" -#~ msgstr "URL:" - -#~ msgid "Presence" -#~ msgstr "Статус" - -#~ msgid "Press digits to send DTMFs." -#~ msgstr "Введите цифры, чтоб отправить DTMF." - -#~ msgid "" -#~ " 3\n" -#~ "def" -#~ msgstr "" -#~ " 3\n" -#~ "где" - -#~ msgid "" -#~ " 2\n" -#~ "abc" -#~ msgstr "" -#~ " 2\n" -#~ "абв" - -#~ msgid "" -#~ " 4\n" -#~ "ghi" -#~ msgstr "" -#~ " 4\n" -#~ "жзи" - -#~ msgid "" -#~ " 5\n" -#~ "jkl" -#~ msgstr "" -#~ " 5\n" -#~ "клм" - -#~ msgid "" -#~ " 6\n" -#~ "mno" -#~ msgstr "" -#~ " 6\n" -#~ "ноп" - -#~ msgid "" -#~ " 7\n" -#~ "pqrs" -#~ msgstr "" -#~ " 7\n" -#~ "рст" - -#~ msgid "" -#~ " 8\n" -#~ "tuv" -#~ msgstr "" -#~ " 8\n" -#~ "уфх" - -#~ msgid "" -#~ " 9\n" -#~ "wxyz" -#~ msgstr "" -#~ " 9\n" -#~ "шюя" - -#~ msgid "DTMF" -#~ msgstr "DTMF" - -#~ msgid "My online friends" -#~ msgstr "Мои друзья онлайн:" - -#~ msgid "" -#~ "C: 2001\n" -#~ "Made in Old Europe" -#~ msgstr "" -#~ "C: 2001\n" -#~ "Сделано в старой Европе" - -#~ msgid "" -#~ "Linphone is a web-phone.\n" -#~ "It is compatible with SIP and RTP protocols." -#~ msgstr "" -#~ "Linphone - это интернет телефон.\n" -#~ "Он совместим с SIP и RTP протоколами." - -#~ msgid "http://www.linphone.org" -#~ msgstr "http://www.linphone.org/" - -#~ msgid "Use IPv6 network (if available)" -#~ msgstr "Использовать IPv6 сеть (если доступно)" - -# msgstr "Teilnehmer zur Zeit nicht ansprechbar." -#~ msgid "" -#~ "Toggle this if you are on an ipv6 network and you wish linphone to use it." -#~ msgstr "Отметьте, если Вы в сети с ipv6 и будите использовать linphone." - -#~ msgid "Global" -#~ msgstr "Основные" - -#~ msgid "" -#~ "These options is only for users in a private network, behind a gateway. " -#~ "If you are not in this situation, then leave this empty." -#~ msgstr "" -#~ "Эта опция используется в частных сетях, за шлюзом. Если вы не в этой " -#~ "ситуации, просто оставьте пустой." - -#~ msgid "No firewall" -#~ msgstr "Нет firewall'a" - -#~ msgid "Use this STUN server to guess firewall address :" -#~ msgstr "Используйте этот STUN сервер чтоб определить адрес firewall :" - -#~ msgid "Specify firewall address manually:" -#~ msgstr "Определить адрес Firewall вручную:" - -#~ msgid "NAT traversal options (experimental)" -#~ msgstr "NAT опции (экспериментально)" - -#~ msgid "Number of buffered miliseconds (jitter compensation):" -#~ msgstr "Число милисекунд для буферизации (компенсация дрожания):" - -#~ msgid "RTP port used for audio:" -#~ msgstr "RTP порт для аудио:" - -#~ msgid "Use SIP INFO message instead of RTP rfc2833 for DTMF transmitting" -#~ msgstr "" -#~ "Используйте SIP INFO сообщения вместо RTP rfc2833 для DTMF препровождения" - -#~ msgid "RTP-RFC2833 is the recommended way." -#~ msgstr "RTP-RFC2833 рекомендуемый." - -#~ msgid "Other" -#~ msgstr "Другое" - -#~ msgid "micro" -#~ msgstr "Микрофон" - -#~ msgid "Enable echo-canceler (cancels the echo heard by the remote party)" -#~ msgstr "" -#~ "Включить подавление эхо (подавляет эхо слышимое с удалённого устройства)" - -#~ msgid "Choose file" -#~ msgstr "Выберите файл" - -#~ msgid "Listen" -#~ msgstr "Слушать" - -#~ msgid "Sound device" -#~ msgstr "Устройство звука" - -#~ msgid "Run sip user agent on port:" -#~ msgstr "Запустить \"user agent\" на порту:" - -#~ msgid "It is strongly recommended to use port 5060." -#~ msgstr "Рекомендуется использовать порт 5060." - -#~ msgid "@" -#~ msgstr "@" - -#~ msgid "Identity" -#~ msgstr "Личность" - -#~ msgid "Add proxy/registrar" -#~ msgstr "Добавить прокси/регистратора" - -#~ msgid "Remote services" -#~ msgstr "Удалённые сервисы" - -#~ msgid "Clear all stored authentication information (username,password...)" -#~ msgstr "Удалить всю информацию аунтефикации (логин, пароль...)" - -#~ msgid "List of audio codecs, in order of preference:" -#~ msgstr "Список аудио кодеков в приоритетном порядке:" - -#~ msgid "" -#~ "Note: Codecs in red are not usable regarding to your connection type to " -#~ "the internet." -#~ msgstr "" -#~ "Заметка: Кодеки отмеченные красным не подходят для вашего соединения в " -#~ "Internet." - -#~ msgid "No information availlable" -#~ msgstr "Информация недоступна" - -#~ msgid "Codec information" -#~ msgstr "Информация о кодеке" - -#~ msgid "Address Book" -#~ msgstr "Адресная книга" - -#~ msgid "Select" -#~ msgstr "Выбор" - -#~ msgid "" -#~ "User is not reachable at the moment but he invites you to contact him " -#~ "using the following alternate ressource:" -#~ msgstr "" -#~ "Пользователь не доступен в данный момент, но приглашает пообщаться на " -#~ "альтернативном ресурсе:" - -#~ msgid "None." -#~ msgstr "Нет." - -#~ msgid "Send registration:" -#~ msgstr "Отправить регистрацию:" - -#~ msgid "Name:" -#~ msgstr "Имя:" - -#~ msgid "Subscribe policy:" -#~ msgstr "Правило подписки:" - -#~ msgid "Send subscription (see person's online status)" -#~ msgstr "Отправить подписку (смотреть статус персоны в сети)" - -#~ msgid "New incoming subscription" -#~ msgstr "Подтверждение новой подписки" - -#~ msgid "You have received a new subscription..." -#~ msgstr "Вы получили новое подтверждение..." - -#~ msgid "Refuse" -#~ msgstr "Отказать" - -#~ msgid "Authentication required for realm" -#~ msgstr "Регистрация для" - -#~ msgid "userid:" -#~ msgstr "ID пользователя:" - -#~ msgid "Linphone - Call history" -#~ msgstr "Linphone - История звонков" - -#~ msgid "Text:" -#~ msgstr "Текст" - -#~ msgid "The caller asks for resource reservation. Do you agree ?" -#~ msgstr "" -#~ "Вызывающий абонент спрашивает о резервировании ресурса. Вы согласны ?" - -#~ msgid "" -#~ "The caller doesn't use resource reservation. \t\t\t\t\tDo you wish to " -#~ "continue anyway ?" -#~ msgstr "" -#~ "Вызывающий не использует резервирование ресурса. \t\t\t\t\tВы всё равно " -#~ "желаете продолжить?" - -#~ msgid "linphone - receiving call from %s" -#~ msgstr "Linphone - принял звонок от %s" +#~ msgid "Keypad" +#~ msgstr "Клавиатура" #~ msgid "" -#~ "You have received a subscription from %s.This means that this person " -#~ "wishes to be notified of your presence information (online, busy, " -#~ "away...).\n" -#~ "Do you agree ?" +#~ "fr: Simon Morlat\n" +#~ "en: Simon Morlat and Delphine Perreau\n" +#~ "it: Alberto Zanoni \n" +#~ "de: Jean-Jacques Sarton \n" +#~ "sv: Daniel Nylander \n" +#~ "es: Jesus Benitez \n" +#~ "ja: YAMAGUCHI YOSHIYA \n" +#~ "pt_BR: Rafael Caesar Lenzi \n" +#~ "pl: Robert Nasiadek \n" +#~ "cs: Petr Pisar \n" +#~ "hu: anonymous\n" #~ msgstr "" -#~ "Вы получили запрос на подключение от %s. Это значит что этот человек " -#~ "хочет знать ваш статус (онлайн, занят, отошёл...).\n" -#~ "Вы согласны ?" - -#~ msgid "Authentication required for realm %s" -#~ msgstr "Регистрация для %s" - -#~ msgid "Wait" -#~ msgstr "Подождать" - -#~ msgid "Deny" -#~ msgstr "Отказать" - -#~ msgid "Bad sip address: a sip address looks like sip:user@domain" -#~ msgstr "Неправильный sip адрес, он выглядит как: " - -#~ msgid "Stun lookup done..." -#~ msgstr "Поиск Stun завершён..." - -#~ msgid "enter sip uri here" -#~ msgstr "Sip URI eingeben" - -#~ msgid "User manual" -#~ msgstr "Anwender-Handbuch" - -#~ msgid "Ring sound selection" -#~ msgstr "Klingelton ausw�len" - -#~ msgid "Communication ended." -#~ msgstr "Kommunikation beendet." - -#, fuzzy -#~ msgid "Firewall 's external ip address (in dot notations):" -#~ msgstr "IP-Adresse des Firewall (in Punktnotation)" - -#~ msgid "28k modem" -#~ msgstr "28K Modem" - -#~ msgid "56k modem" -#~ msgstr "56K Modem" - -#~ msgid "64k modem (numeris)" -#~ msgstr "64K Modem (ISDN)" - -#~ msgid "ADSL or Cable modem" -#~ msgstr "ADSL oder Kabel-Modem" +#~ "fr: Simon Morlat\n" +#~ "en: Simon Morlat and Delphine Perreau\n" +#~ "it: Alberto Zanoni \n" +#~ "de: Jean-Jacques Sarton \n" +#~ "sv: Daniel Nylander \n" +#~ "es: Jesus Benitez \n" +#~ "ja: YAMAGUCHI YOSHIYA \n" +#~ "pt_BR: Rafael Caesar Lenzi \n" +#~ "pl: Robert Nasiadek \n" +#~ "cs: Petr Pisar \n" +#~ "hu: anonymous\n" -#~ msgid "Ethernet or equivalent" -#~ msgstr "Ethernet oder �uivalent" - -#~ msgid "Connection type:" -#~ msgstr "Verbindungstyp:" - -#, fuzzy -#~ msgid "" -#~ "Linphone could not open audio device %s. Check if your sound card is " -#~ "fully configured and working." -#~ msgstr "" -#~ "Linphone kann das Soundger� nicht �fnen. Prfen Sie nach, ob dieSoundkarte " -#~ "vollst�dig konfiguriert und funktionsf�ig ist." +#~ msgid "edit" +#~ msgstr "править" -#~ msgid "Type here the sip address of the person you want to call." -#~ msgstr "" -#~ "Geben Sie die Sip-Adresse des Anwenders, den Sie anrufen m�hten, hier ein." +#~ msgid "Behind NAT / Firewall (specify gateway IP below)" +#~ msgstr "За NAT / брандмауэром (указать IP шлюза ниже)" #~ msgid "" -#~ "Release or\n" -#~ "Refuse" +#~ "Register to FONICS\n" +#~ "virtual network !" #~ msgstr "" -#~ "Auflegen oder\n" -#~ "Abweisen" - -#~ msgid "%s. Retry after %i minute(s)." -#~ msgstr "%s. In %i Minuten wieder versuchen." +#~ "Регистрация в \n" +#~ "виртуальной сети FONICS!" -#~ msgid "Timeout..." -#~ msgstr "Zeitberschreitung..." +#~ msgid "aborted" +#~ msgstr "прервано" -#~ msgid "Toggle this if you want to be registered on a remote server." -#~ msgstr "" -#~ "Bitte ankreuzen, wenn Sie auf einem Sip-Server registriert werden wollen." +#~ msgid "completed" +#~ msgstr "завершён" -#~ msgid "Address of record:" -#~ msgstr "Adresse des Eintrags:" +#~ msgid "missed" +#~ msgstr "пропущено" #~ msgid "" -#~ "The password used for registration. On some servers it is not necessary" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" #~ msgstr "" -#~ "Passwort fr die Registrierung. Bei manchen Servern nicht erforderlich." +#~ "%s в %s\n" +#~ "От: %s\n" +#~ "Кому: %s\n" +#~ "Статус: %s\n" +#~ "Длительность: %i мин. %i сек.\n" -#~ msgid "Use this registrar server as outbound proxy." -#~ msgstr "Verwenden Sie diesen Registrarserver als externen proxy." - -#~ msgid "sip address:" -#~ msgstr "SIP-Adresse:" - -#~ msgid "Modify" -#~ msgstr "�dern" +#~ msgid "Outgoing call" +#~ msgstr "Исходящий звонок" #~ msgid "" -#~ "You are currently using the i810_audio driver.\n" -#~ "This driver is buggy and so does not work with Linphone.\n" -#~ "We suggest that you replace it by its equivalent ALSA driver,\n" -#~ "either with packages from your distribution, or by downloading\n" -#~ "ALSA drivers at http://www.alsa-project.org." -#~ msgstr "" -#~ "Sie verwenden zur Zeit den i810_audio Treiber.\n" -#~ "Diese Treiber ist fehlerhaft und funktioniert nicht mit Linphone\n" -#~ "Wir empfehlen, den Treiber entweder durch das ALSA-Treiber-Paket von " -#~ "ihrer Distribution\n" -#~ "zu ersetzen oder die gewnschten ALSA-Treiber von http://www.alsa-project." -#~ "org\n" -#~ "zu beziehen und zu installieren" - -#~ msgid "Unregistration successfull." -#~ msgstr "Abmeldung erfolgreich." - -#~ msgid "Select network interface to use:" -#~ msgstr "Netzwerkschnittstelle w�len:" - -#~ msgid "Network interface properties" -#~ msgstr "Eigenschaften der Netzwerkschnittstelle" - -#~ msgid "RTP" -#~ msgstr "RTP" - -#~ msgid "C: 2001" -#~ msgstr "April 2001" - -#~ msgid "Threads not supported by glib. Upgrade your glib.\n" +#~ "Could not parse given sip address. A sip url usually looks like sip:" +#~ "user@domain" #~ msgstr "" -#~ "Threads werden von glib nicht untersttzt. Bitte aktualisieren Sie Ihre " -#~ "glib.\n" - -#~ msgid "Run linphone as a gnome-applet." -#~ msgstr "Linphone als gnome-Applet ausfhren." - -#~ msgid "Run linphone as a daemon (for use without gnome)." -#~ msgstr "Linphone als daemon ausfhren (Verwendung ohne Gnome)." +#~ "Не могу опознать sip адрес. Url для sip обычно выглядит как sip:" +#~ "пользователь@домен" #~ msgid "" -#~ "Cannot find network previously used interface %s.\n" -#~ "If your computer is temporary connected to the internet, please connect " -#~ "and then run linphone.\n" -#~ "If you want to change your default network interface, go to the " -#~ "parameters 'box." +#~ "Your computer appears to be using ALSA sound drivers.\n" +#~ "This is the best choice. However the pcm oss emulation module\n" +#~ "is missing and linphone needs it. Please execute\n" +#~ "'modprobe snd-pcm-oss' as root to load it." #~ msgstr "" -#~ "Linphone konnte die zuvor verwendete Netzwerkschnittstelle %s nicht " -#~ "finden.\n" -#~ "Wenn linphone nur tempor� am Internet angeschlossen ist, stellen Sie eine " -#~ "Verbindung her und rufen Sie linphone erneut auf.\n" -#~ "Wenn Sie die vorgegebene Netzwerkschnittstelle �dern wollen, w�len Sie " -#~ "bitte \"Einstellungen\"." +#~ "Ваш компьютер использует ALSA звуковые драйвера.\n" +#~ "Это лучший выбор. Однако, pcm oss модуль эмуляции\n" +#~ "не найден, а он нужен для linphone.\n" +#~ "Пожалуйста, выполните от пользователя root команду 'modprobe snd-pcm-oss' " +#~ "чтобы загрузить его." #~ msgid "" -#~ "Linphone cannot open the audio device.\n" -#~ "It may be caused by other programs using it.\n" -#~ "Do you want linphone to kill these programs (esd or artsd) ?" +#~ "Your computer appears to be using ALSA sound drivers.\n" +#~ "This is the best choice. However the mixer oss emulation module\n" +#~ "is missing and linphone needs it. Please execute\n" +#~ " 'modprobe snd-mixer-oss' as root to load it." #~ msgstr "" -#~ "Linphone kann die Soundschnittstelle nicht �fnen.\n" -#~ "Dies kann durch andere Applikationen verursacht sein.\n" -#~ "M�hten sie diese Programme (esd oder artsd) beenden?" +#~ "Ваш компьютер использует ALSA звуковые драйвера.\n" +#~ "Это лучший выбор. Однако, mixer oss модуль эмуляции\n" +#~ "не найден, а он нужен для linphone.\n" +#~ "Пожалуйста, выполните от пользователя root команду 'modprobe snd-pcm-oss' " +#~ "чтобы загрузить его." -#~ msgid "Use it as a:" -#~ msgstr "Verwenden als:" +#~ msgid "Incompatible, check codecs..." +#~ msgstr "Несовместимость, проверьте кодеки..." -#~ msgid "Outbound proxy" -#~ msgstr "Ausgehender Proxy-Server" +#~ msgid "We are being paused..." +#~ msgstr "Мы приостанавливаемся..." -#~ msgid "" -#~ "Toggle this button if the registrar must be used to proxy calls through a " -#~ "firewall." -#~ msgstr "" -#~ "Verwenden Sie diesen Knopf, falls der Registrar zum Tunneln durch einen " -#~ "Firewall verwendet werden mu�" +#~ msgid "We have been resumed..." +#~ msgstr "Мы возобновили..." -#~ msgid "kbit/s" -#~ msgstr "Kbits/s" +#~ msgid "Call has been updated by remote..." +#~ msgstr "Звонок был дистанционно обновлён..." -#~ msgid "OSS" -#~ msgstr "OSS" +#~ msgid "No response." +#~ msgstr "Нет ответа." -#~ msgid "ALSA" -#~ msgstr "ALSA" +#~ msgid "Protocol error." +#~ msgstr "Ошибка протокола." -#~ msgid "Automatically kill applications using soundcard when needed" -#~ msgstr "Applikationen die die Soundkarte verwenden, automatisch beenden." +#~ msgid "No common codecs" +#~ msgstr "Нет общих кодеков" -#~ msgid "" -#~ "Your computer is connected to several networks. Check in the global " -#~ "parameters if Linphone uses the one that you want." -#~ msgstr "" -#~ "Ihr Rechner ist an mehere Netze angeschlossen. Stellen Sie sicher, da�in " -#~ "den Globalen Parametern die richtige Schnittstelle selektiert ist." +#~ msgid "Authentication failure" +#~ msgstr "Неудача аутентификации" -#~ msgid "" -#~ "Linphone failed to open the sound device. See the README file included in " -#~ "the distribution for details." -#~ msgstr "" -#~ "Linphone konnte die Soundschnittstelle nicht �fnen. Weitere Informationen " -#~ "finden Sie in der README-Datei (enthalten in der Distribution)." +#~ msgid "Please choose a username:" +#~ msgstr "Пожалуйста, выберите имя пользователя:" -#~ msgid "Interface not found." -#~ msgstr "Schnittstelle nicht gefunden." +#~ msgid "Checking if '%s' is available..." +#~ msgstr "Проверка доступности для '%s'" -#~ msgid "Warning" -#~ msgstr "Warnung" +#~ msgid "Please wait..." +#~ msgstr "Пожалуйста, подождите..." -#~ msgid "" -#~ "Linphone cannot open the sound device. It may be caused by other programs " -#~ "using it. Do you want linphone to kill these programs (esd or artsd) ?" +#~ msgid "Sorry this username already exists. Please try a new one." #~ msgstr "" -#~ "Linphone kann die Soundschnittstelle nicht �fnen. Dies kann durch andere " -#~ "Applikationen verursacht sein. M�hten sie diese Programme (esd oder " -#~ "artsd) beenden?" +#~ "Такое имя пользователя уже существует. Пожалуйста, попробуйте с другим " +#~ "именем." -#~ msgid "Linphone shutdowns..." -#~ msgstr "Linphone Ende..." +#~ msgid "Ok !" +#~ msgstr "ОК!" -#~ msgid "" -#~ "Please, wait a few seconds untils linphone unregisters your sip addess " -#~ "from registrar server..." -#~ msgstr "Bitte einige Sekunden warten, bis Sip-Adresse ausgetragen ist." +#~ msgid "Communication problem, please try again later." +#~ msgstr "Проблемы со связью, пожалуйста, повторите попытку позже." -#~ msgid "Bad formuled sip address." -#~ msgstr "SIP-Adresse fehlerhaft." +#~ msgid "Choosing a username" +#~ msgstr "Выбор имени пользователя" -#~ msgid "Couldn't create pixmap from file: %s" -#~ msgstr "Konnte Pixmap nicht aus Datei %s erzeugen." +#~ msgid "Verifying" +#~ msgstr "Проверка" -#~ msgid "" -#~ "Linphone did not detect any valid network interface. If you use a " -#~ "temporary internet connection, please connect and then run linphone again." -#~ msgstr "" -#~ "Linphone konnte keine Netzwerkschnittstelle finden. Wenn Sie nur eine " -#~ "tempor�e Internetverbindung haben, bitte erneut eine Internetverbindung " -#~ "herstellen und linphone nochmals starten." +#~ msgid "Creating your account" +#~ msgstr "Создание вашей учётной записи" -#~ msgid "List of network interfaces on your system." -#~ msgstr "Vorhandene Netzwerkschnittstellen ihres Systems" +#~ msgid "Now ready !" +#~ msgstr "Готово!" diff --git a/po/sr.po b/po/sr.po index ed088ef14..2ec83343c 100644 --- a/po/sr.po +++ b/po/sr.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 0.7.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-02-11 19:03+0200\n" "Last-Translator: Мирослав Николић \n" "Language-Team: Serbian \n" @@ -16,12 +16,12 @@ msgstr "" "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n" "%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Позови „%s“" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Пошаљи текст за %s" @@ -31,26 +31,26 @@ msgstr "Пошаљи текст за %s" msgid "Recent calls (%i)" msgstr "У позиву" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "н/д" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "прекинути" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "пропуштени" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Одбиј" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" @@ -59,7 +59,7 @@ msgstr[1] "%i минута" msgstr[2] "%i минута" msgstr[3] "Један минут" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" @@ -68,14 +68,14 @@ msgstr[1] "%i секунде" msgstr[2] "%i секунде" msgstr[3] "Једна секунда" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, fuzzy, c-format msgid "%s\t%s" msgstr "" "%s\t%s\tКвалитет: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, fuzzy, c-format msgid "" "%s\tQuality: %s\n" @@ -84,7 +84,7 @@ msgstr "" "%s\t%s\tКвалитет: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, fuzzy, c-format msgid "" "%s\t\n" @@ -106,7 +106,7 @@ msgstr "Ја" msgid "Couldn't find pixmap file: %s" msgstr "Не могу да пронађем датотеку сличице: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Неисправан сип контакт !" @@ -157,7 +157,7 @@ msgstr "Помоћник подешавања налога" msgid "Call with %s" msgstr "Позив са корисником %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -170,7 +170,7 @@ msgstr "" "на ваш списак пријатеља ?\n" "Ако одговорите са не, ова особа ће привремено бити стављена на црни списак." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -179,59 +179,59 @@ msgstr "" "Унесите вашу лозинку за корисничко име %s\n" " на домену %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Грешка позива" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Позив је завршен" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Долазни позив" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Јави се" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Одбиј" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Позив је заустављен" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Кодеци" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Веза веб сајта" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Линфон — интернет телефон са снимком" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (основно)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Преселили смо се на %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -239,7 +239,7 @@ msgstr "" "Ниједна звучна картица није откривен ана овом рачунару.\n" "Нећете бити у могућности да шаљете или да примате звучне позиве." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Слободан СИП телефон са снимком" @@ -251,7 +251,7 @@ msgstr "Додајте у адресар" msgid "Presence status" msgstr "Стање присуства" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Име" @@ -268,142 +268,142 @@ msgstr "" msgid "Search in %s directory" msgstr "Тражи у директоријуму „%s“" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Уредите контакт „%s“" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Обришите контакт „%s“" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Обришите контакт „%s“" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Додајте нови контакт из директоријума „%s“" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Проток (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Стање" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Најмањи проток бита (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Параметри" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Укључено" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Искључено" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Налог" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Енглески" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Француски" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Шведски" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Италијански" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Шпански" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Бразилски португалски" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Пољски" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Немачки" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Руски" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Јапански" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Холандски" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Мађарски" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Чешки" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Кинески" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Традиционални кинески" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Норвешки" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" "Трба поново да покренете линфон да би нови изабрани језик ступио на снагу." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Ништа" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "СРТП" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ЗРТП" @@ -480,110 +480,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Корисничко име:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Лозинка:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Корисничко име" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Лозинка" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Корисничко име:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Лозинка:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Хвала вам. Ваш налог је сада подешен и спреман за употребу." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Помоћник подешавања налога" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Добродошли у помоћника подешавања налога" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Помоћник подешавања налога" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Подесите СИП налог" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -655,131 +659,131 @@ msgstr "Позив није успео." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, fuzzy, c-format msgid "%.3f seconds" msgstr "%i секунда" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Позивам..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Долазни позив" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "добро" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "просечно" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "оскудно" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "јадно" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "много лоше" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "недоступно" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Осигурано СРТП-ом" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Осигурано ЗРТП-ом [потврђивање идентитета: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Непроверено подешавање" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Проверено подешавање" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "На конференцији" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "У позиву" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Заустављен позив" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Позив је завршен." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 #, fuzzy msgid "Transfer done." msgstr "Пребаци" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Пребаци" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Настави" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Застани" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "Застани" @@ -815,7 +819,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -824,59 +828,59 @@ msgstr "" "Добродошли !\n" "Овај помоћник ће вам помоћи да користите СИП налог за ваше позиве." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Уређај за снимање:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Уређај за пуштање:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Помоћник подешавања налога" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Помоћник подешавања налога" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1829,96 +1833,65 @@ msgstr "Повезујем се..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "прекинути" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "завршени" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "пропуштени" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s у %s\n" -"Позива: %s\n" -"Прима: %s\n" -"Стање: %s\n" -"Трајање: %i мин %i сек\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Одлазни позив" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Спреман" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Потврђујем" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Тражим одредиште телефонског броја..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Не могу да решим овај број." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Ступам у везу" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Не могу да позовем" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Извините, достигли смо највећи број истовремених позива" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "вам се обраћа" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " и затражени само-одговор." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Мењам параметре позива..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Повезан сам." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Позив је прекинут" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Не могу да зауставим позив" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Заустављам тренутни позив..." @@ -1983,7 +1956,7 @@ msgstr "Трајање" msgid "Unknown-bug" msgstr "Непозната грешка" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1991,7 +1964,7 @@ msgstr "" "Адреса сип посредника коју сте унели је неисправна, мора почети на „sip:“ за " "којим следи назив домаћина." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2000,126 +1973,126 @@ msgstr "" "Треба да изгледа као „sip:корисник@домен-посредника, као што је „sip:" "alice@example.net“" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Не могу да се пријавим као %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Удаљено звоњење." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Удаљено звоњење..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Ранији медиј." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "Позив са „%s“ је заустављен." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Позив на који је одговорио „%s“ — на чекању." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Позив је настављен." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "На позив је одговорио „%s“." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 #, fuzzy msgid "We have been resumed." msgstr "Позив нам је настављен..." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 #, fuzzy msgid "Call is updated by remote." msgstr "Позив је ажуриран удаљеним..." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Позив је завршен." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Корисник је заузет." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Корисник је привремено недоступан." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Корисник не жели да буде узнемираван." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Позив је одбијен." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Преусмерен" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Позив није успео." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Уписивање на „%s“ је успело." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Исписивање са „%s“ је обављено." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "нема ограничења одговора" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Уписивање на „%s“ није успело: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Симбол потврђивања идентитета је „%s“" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." @@ -2128,6 +2101,31 @@ msgstr[1] "Пропустили сте %i позива." msgstr[2] "Пропустили сте %i позива." msgstr[3] "Пропустили сте један позив." +#~ msgid "aborted" +#~ msgstr "прекинути" + +#~ msgid "completed" +#~ msgstr "завршени" + +#~ msgid "missed" +#~ msgstr "пропуштени" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s у %s\n" +#~ "Позива: %s\n" +#~ "Прима: %s\n" +#~ "Стање: %s\n" +#~ "Трајање: %i мин %i сек\n" + +#~ msgid "Outgoing call" +#~ msgstr "Одлазни позив" + #~ msgid "No response." #~ msgstr "Нема одговора." diff --git a/po/sv.po b/po/sv.po index 67e07eab8..59b307d05 100644 --- a/po/sv.po +++ b/po/sv.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2009-02-17 15:22+0100\n" "Last-Translator: Emmanuel Frécon \n" "Language-Team: SWEDISH \n" @@ -16,12 +16,12 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Ringer %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Skicka text till %s" @@ -31,52 +31,52 @@ msgstr "Skicka text till %s" msgid "Recent calls (%i)" msgstr "I samtal med" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "avbrytade" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "missade" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Avböj" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -97,7 +97,7 @@ msgstr "Mikrofon av" msgid "Couldn't find pixmap file: %s" msgstr "Kunde inte hitta pixmap filen: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "ogiltig SIP kontakt!" @@ -148,7 +148,7 @@ msgstr "Kontoinstallationsassistenten" msgid "Call with %s" msgstr "Samtal med %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -161,7 +161,7 @@ msgstr "" "henne till din kontaktlista?\n" "Om du svarar nej, personen kommer att vara bannlyst." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -170,67 +170,67 @@ msgstr "" "Mata in ditt lösenord för användaren %s\n" "vid domänen %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Samtalshistorik" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Samtalet slut" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Inkommande samtal" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Avböj" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "avbrytade" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Portar" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Webbsajt" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - en video Internet telefon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Default)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "En gratis SIP video-telefon" @@ -242,7 +242,7 @@ msgstr "" msgid "Presence status" msgstr "Närvarostatus" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Namn" @@ -260,141 +260,141 @@ msgstr "" msgid "Search in %s directory" msgstr "Sök i %s katalogen" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Ändra kontakt '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Ta bort kontakt '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Ta bort kontakt '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Lägg till kontakt ifrån %s katalogen" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Frekvens (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min. datahastighet (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametrar" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "På" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Av" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Konto" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Engelska" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Fransk" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Svenska" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italiensk" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Spanska" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Portugisiska" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polska" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Tyska" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Ryska" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Japanska" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Nederländksa" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Hungerska" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Tjekiska" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Kinesiska" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Du behöver starta om programmet för att det nya språket ska synas." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -469,110 +469,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Användarnamn:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Lösenord:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Användarnamn" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Lösenord" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Användarnamn:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Lösenord:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Tack. Ditt konto är nu konfigurerad och färdig att användas." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Kontoinstallationsassistenten" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Välkommen till kontoinstallationsassistenten" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Kontoinstallationsassistenten" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Konfigurera ett SIP konto" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 #, fuzzy msgid "Terminating" msgstr "Lägg på" @@ -643,133 +647,133 @@ msgstr "Samtalet avböjdes." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Ringer..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00:00:00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Inkommande samtal" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "I samtal med" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Lägg på" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i:%02i:%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Samtalet slut." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Samtalet avböjdes." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -804,7 +808,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -813,59 +817,59 @@ msgstr "" "Välkommen!\n" "Assistenten kommer att hjälpa dig använda ett SIP konto för dina samtal:" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Mikrofon enhet:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Uppspelningsenhet:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Assistent" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Kontoinstallationsassistenten" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1827,100 +1831,69 @@ msgstr "Kontaktar" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "avbrytade" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "avslutade" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "missade" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s på %s\n" -"Från: %s\n" -"Till: %s\n" -"Status: %s\n" -"Längd: %i min %i sek\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Utgående samtal" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Redo" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Bekräftelse" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Leta efter telefonnummer för destinationen..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Kan inte nå dett nummer." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Kontaktar" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "Kunde inte ringa" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "kontaktar dig." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Kopplad" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "avbrytade" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 #, fuzzy msgid "Could not pause the call" msgstr "Kunde inte ringa" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 #, fuzzy msgid "Pausing the current call..." msgstr "Nuvarande samtal" @@ -1986,7 +1959,7 @@ msgstr "Förlopp" msgid "Unknown-bug" msgstr "Okänd bug" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1994,7 +1967,7 @@ msgstr "" "SIP proxy adressen som du matade in är inte rätt, adressen måste starta med " "\"sip:\", följd av ett hostnamn" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2002,134 +1975,159 @@ msgstr "" "SIP adressen som du matade in är inte rätt. Adressen borde se ut som sip:" "namn@domän, såsom sip:peter@exempel.se" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Kunde inte logga in som %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Ringer hos motparten." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Ringer hos motparten." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Tidig media" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "Samtal med %s" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Samtalet slut" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Samtalet slut." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Användare upptagen." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Användaren temporärt inte tillgänglig." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Användaren vill inte bli störd." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Samtalet avböjdes." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 #, fuzzy msgid "Redirected" msgstr "Omdirigerat till %s..." -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Samtalet avböjdes." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrering hos %s lyckades." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Avregistrering hos %s lyckades." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "Inget svar inom angiven tid" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrering hos %s mislyckades: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Linphone - Autentisering krävs" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Du har %i missat samtal" msgstr[1] "Du har %i missade samtal" +#~ msgid "aborted" +#~ msgstr "avbrytade" + +#~ msgid "completed" +#~ msgstr "avslutade" + +#~ msgid "missed" +#~ msgstr "missade" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s på %s\n" +#~ "Från: %s\n" +#~ "Till: %s\n" +#~ "Status: %s\n" +#~ "Längd: %i min %i sek\n" + +#~ msgid "Outgoing call" +#~ msgstr "Utgående samtal" + #, fuzzy #~ msgid "No response." #~ msgstr "Inget svar inom angiven tid" diff --git a/po/zh_CN.po b/po/zh_CN.po index af5a7d776..c0eab3db4 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 3.3.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2011-01-08 23:51+0800\n" "Last-Translator: Aron Xu \n" "Language-Team: Chinese (simplified) \n" @@ -18,12 +18,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "呼叫 %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "发送消息给 %s" @@ -33,50 +33,50 @@ msgstr "发送消息给 %s" msgid "Recent calls (%i)" msgstr "正在呼叫" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "中断" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "丢失" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "拒绝" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -97,7 +97,7 @@ msgstr "静音" msgid "Couldn't find pixmap file: %s" msgstr "无法打开位图文件:%s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "无效的 SIP 联系人!" @@ -146,7 +146,7 @@ msgstr "帐户设置向导" msgid "Call with %s" msgstr "与 %s 通话" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -158,68 +158,68 @@ msgstr "" "您是否允许他看到您的在线状态或者将它加为您的联系人允许?\n" "如果您回答否,则会将该人临时性的放入黑名单" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "请输入 %s@%s 的密码:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "呼叫历史" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "呼叫结束" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "呼入" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "拒绝" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "中断" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "端口" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "网站" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - 互联网视频电话" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (默认)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -227,7 +227,7 @@ msgstr "" "未在此计算机上检测到声卡。\n" "您无法发送或接收音频呼叫。" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "免费的 SIP 视频电话" @@ -239,7 +239,7 @@ msgstr "" msgid "Presence status" msgstr "在线状态" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "名称" @@ -257,141 +257,141 @@ msgstr "" msgid "Search in %s directory" msgstr "在 %s 目录中查找 " -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "编辑联系人 %s" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "删除联系人 %s" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "删除联系人 %s" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "从 %s 目录增加联系人 " -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "采样率(Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "状态" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "最小比特率(kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "参数" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "启用" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "禁用" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "帐户" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "英语" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "法语" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "瑞典语" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "意大利语" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "西班牙语" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "巴西葡萄牙语" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "波兰语" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "德语" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "俄语" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日语" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "荷兰语" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "匈牙利语" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "捷克语" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "中文" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "您需要重启 linphone 以使语言选择生效。" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -465,110 +465,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "用户名:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "密码:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "用户名" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "密码" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "用户名:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "密码:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "谢谢,您的帐户已经配置完毕,可以使用。" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "帐户设置向导" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "欢迎使用帐户设置向导" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "帐户设置向导" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "配置 SIP 帐户" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 #, fuzzy msgid "Terminating" msgstr "终止呼叫" @@ -640,133 +644,133 @@ msgstr "ICE 过滤器" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "正在呼叫..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "呼入" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "正在呼叫" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "正在呼叫" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "通话结束。" -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "呼叫失败。" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -801,7 +805,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -810,59 +814,59 @@ msgstr "" "欢迎使用 Linphone!\n" "设置向导将帮助您配置打网络电话的 SIP 帐户。" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "录音设备:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "回放设备:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "配置向导" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "帐户设置向导" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1840,99 +1844,68 @@ msgstr "正在连接..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "中断" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "完成" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "丢失" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s @ %s\n" -"主叫:%s\n" -"被叫: %s\n" -"状态:%s\n" -"状态:%i 分 %i 秒\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "呼出" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "就绪" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "确认" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "查询电话号码目的地..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "该号码无法解析。" #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "联系中" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "无法呼叫" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "正在联系您" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " 并询问了自动回答。" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "已连接。" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "中断" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 #, fuzzy msgid "Could not pause the call" msgstr "无法呼叫" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "" @@ -1997,13 +1970,13 @@ msgstr "通话时间" msgid "Unknown-bug" msgstr "未知错误" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "您输入的 SIP 代理地址无效,它必须是以“sip:”开头,并紧随一个主机名。" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2011,131 +1984,156 @@ msgstr "" "您输入的地址无效。\n" "它应具有“sip:用户名@代理域”的形式,例如 sip:alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "无法登录为 %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "响铃。" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "响铃。" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "与 %s 通话" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "呼叫结束" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "通话结束。" -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "被叫正忙。" -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "您呼叫的用户暂时无法接通。" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "用户已开启免打扰功能。" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "呼叫被拒绝。" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "已重定向" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "呼叫失败。" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "成功注册到 %s" -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "已在 %s 解除注册。" -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "没有响应,超时" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "注册到 %s 失败: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Linphone - 需要认证" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "您错过了 %i 个呼叫。" +#~ msgid "aborted" +#~ msgstr "中断" + +#~ msgid "completed" +#~ msgstr "完成" + +#~ msgid "missed" +#~ msgstr "丢失" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s @ %s\n" +#~ "主叫:%s\n" +#~ "被叫: %s\n" +#~ "状态:%s\n" +#~ "状态:%i 分 %i 秒\n" + +#~ msgid "Outgoing call" +#~ msgstr "呼出" + #~ msgid "No response." #~ msgstr "没有响应。" diff --git a/po/zh_TW.po b/po/zh_TW.po index e44590a16..789c278d5 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 3.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2011-04-06 21:24+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: \n" @@ -17,12 +17,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "播打給 %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "傳送文字給 %s" @@ -32,50 +32,50 @@ msgstr "傳送文字給 %s" msgid "Recent calls (%i)" msgstr "通話中" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "已放棄" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "未接" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "拒接" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -96,7 +96,7 @@ msgstr "靜音" msgid "Couldn't find pixmap file: %s" msgstr "找不到 pixmap 檔:%s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "無效的 sip 連絡人!" @@ -146,7 +146,7 @@ msgstr "帳號設定助理" msgid "Call with %s" msgstr "和 %s 通話" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -158,7 +158,7 @@ msgstr "" "您是否要允許他看見您的上線狀態或將他加入您的連絡人清單?\n" "如果您回答否,這個人會被暫時列入黑名單。" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -167,61 +167,61 @@ msgstr "" "請輸入您使用者名稱 %s\n" "於網域 %s 的密碼:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "通話紀錄" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "通話已結束" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "來電" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "接聽" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "拒接" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "通話已放棄" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "連接埠" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "網站連結" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - 網路視訊電話" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (預設值)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "我們被轉接到 %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -229,7 +229,7 @@ msgstr "" "在這臺電腦中偵測不到音效卡。\n" "您將無法傳送或接收語音電話。" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "自由的 SIP 視訊電話" @@ -241,7 +241,7 @@ msgstr "" msgid "Presence status" msgstr "上線狀態" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "名稱" @@ -259,141 +259,141 @@ msgstr "" msgid "Search in %s directory" msgstr "在 %s 目錄中搜尋" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "編輯連絡人「%s」" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "刪除連絡人「%s」" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "刪除連絡人「%s」" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "從 %s 目錄加入新的連絡人" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "頻率 (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "狀態" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "最小頻寬 (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "參數" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "已啟用" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "已停用" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "帳號" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "英語" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "法語" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "瑞典語" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "義大利語" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "西班牙語" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "巴西葡萄牙語" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "波蘭語" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "德語" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "俄語" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日語" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "荷蘭語" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "匈牙利語" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "捷克語" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "中文" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "您需要重新啟動 linphone 才能讓新選擇的語言生效。" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -467,110 +467,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "使用者名稱:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "密碼: " -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "使用者名稱" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "密碼" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "使用者名稱:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "密碼: " -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "謝謝您。您的帳號已設定完成並且可以使用。" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "帳號設定助理" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "歡迎使用帳號設定助理" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "帳號設定助理" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "設定 SIP 帳號" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -641,131 +645,131 @@ msgstr "ICE 過濾器" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "播打..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "來電" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "通話中" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "暫停通話" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "通話結束。" -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 #, fuzzy msgid "Transfer done." msgstr "轉接" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "轉接" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "繼續" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "暫停" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "暫停" @@ -801,7 +805,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -810,59 +814,59 @@ msgstr "" "歡迎!\n" "這個助理會協助您使用電話的 SIP 帳號。" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "捕捉裝置:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "播放裝置" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "帳號設定助理" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "帳號設定助理" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1815,96 +1819,65 @@ msgstr "連線中..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "已放棄" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "已完成" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "未接" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s 於 %s\n" -"從:%s\n" -"到:%s\n" -"狀態:%s\n" -"持續時間:%i 分 %i 秒\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "去電" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "準備就緒" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "確認" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "尋找電話號碼目的端..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "無法解析這個號碼。" #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "正在連絡" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "無法通話" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "抱歉,我們已達瀏同步通話的最大數目" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "正在連絡您" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "並要求自動接聽。" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "修改通話參數..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "已連線。" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "通話已放棄" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "無法暫停通話" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "暫停目前的通話..." @@ -1969,14 +1942,14 @@ msgstr "時間長度" msgid "Unknown-bug" msgstr "不明錯誤" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" "您輸入的 sip 代理位址是無效的,它必須要以「sip:」開頭,後面接主機名稱。" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1984,130 +1957,155 @@ msgstr "" "您輸入的 sip 身分是無效的。\n" "它應該看起來像 sip:使用者名稱@代理網域,像是 sip:alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "無法以 %s 登入" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "遠端響鈴。" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "遠端響鈴..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "早期媒體。" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "和 %s 的通話已暫停。" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "通話由 %s 接聽 - 保留中。" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "通話已繼續。" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "通話由 %s 接聽。" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 #, fuzzy msgid "We have been resumed." msgstr "我們要繼續了..." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "通話已終止。" -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "使用者現正忙碌。" -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "使用者暫時無法聯繫。" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "使用者不想要被打擾。" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "通話被拒接。" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "已重新導向" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "通話失敗。" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "在 %s 註冊成功。" -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "在 %s 取消註冊完成。" -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "沒有回應逾時" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "在 %s 註冊失敗:%s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "驗證失敗" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "您有 %i 通未接來電。" +#~ msgid "aborted" +#~ msgstr "已放棄" + +#~ msgid "completed" +#~ msgstr "已完成" + +#~ msgid "missed" +#~ msgstr "未接" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s 於 %s\n" +#~ "從:%s\n" +#~ "到:%s\n" +#~ "狀態:%s\n" +#~ "持續時間:%i 分 %i 秒\n" + +#~ msgid "Outgoing call" +#~ msgstr "去電" + #~ msgid "No response." #~ msgstr "沒有回應。" diff --git a/share/audio-assistant.desktop.in b/share/audio-assistant.desktop.in index 5e164ca2b..8f2ef4c54 100644 --- a/share/audio-assistant.desktop.in +++ b/share/audio-assistant.desktop.in @@ -1,7 +1,9 @@ [Desktop Entry] Name=Audio assistant +Name[ru]=Помощник аудио Comment=Linphone audio assistant Comment[fr]=Assistant audio de Linphone. +Comment[ru]=Помощник аудио Linphone Type=Application Exec=linphone --run-audio-assistant Icon=/usr/local/share/pixmaps/linphone/linphone.png diff --git a/share/linphone.desktop.in b/share/linphone.desktop.in index d8ab62a5b..c162ed904 100644 --- a/share/linphone.desktop.in +++ b/share/linphone.desktop.in @@ -3,6 +3,43 @@ Name=Linphone Comment=Linphone is a web-phone Comment[fr]=Linphone est un web-phone. Comment[de]=Linphone ist ein web-phone. +Comment[af]=Linphone is 'n webtelefoon +Comment[sq]=Linphone është një telefon interneti +Comment[ast]=Linphone ye un teléfonu web +Comment[bn]=Linphone একটি ওয়েব ফোন +Comment[bs]=Linphone je mrežni telefon +Comment[pt_BR]=Linphone é um telefone web +Comment[bg]=Linphone е уеб телефон +Comment[ca@valencia]=El Linphone és un telèfon web +Comment[ca]=El Linphone és un telèfon web +Comment[zh_HK]=Linphone 是網絡電話(web-phone) +Comment[zh_TW]=Linphone 是網路電話(web-phone) +Comment[zh_CN]=Linphone 是一个网络电话程序 +Comment[crh]=Linphone bir web-telefonudur +Comment[nl]=Linphone is een webtelefoon +Comment[da]=Linphone er en nettelefon +Comment[cs]=Linphone webový telefon +Comment[fi]=Linphone on verkkopuhelin +Comment[gl]=Linphone é un teléfono-web +Comment[el]=Το Linphone είναι ένα διαδικτυακό τηλέφωνο +Comment[hu]=A Linphone egy webes telefon +Comment[is]=Linphone er vefsími +Comment[it]=Linphone è un telefono web +Comment[ja]=Linphone はウェブ電話です +Comment[ky]=Linphone - бул веб - телефон +Comment[ms]=Linphone adalah telefon-sesawang +Comment[oc]=Linphone es una aisina de telefonia IP +Comment[pl]=Rozbudowany telefon internetowy z funkcją wideorozmowy +Comment[nb]=Lintelefon er en nett-telefon +Comment[pt]=Linphone é um telefone da internet +Comment[ro]=Linphone este un telefon web +Comment[ru]=Linphone — это веб-телефон +Comment[sl]=Linphone je spletni telefon +Comment[sv]=Webbtelefon +Comment[es]=Linphone es un teléfono web +Comment[vi]=Linphone là một điện thoại web +Comment[uk]=Інтернет-телефон +Comment[tr]=Linphone bir web-telefonudur Type=Application Exec=linphone Icon=@prefix@/share/pixmaps/linphone/linphone.png diff --git a/tester/Makefile.am b/tester/Makefile.am index 348306bca..7fb08bb0f 100644 --- a/tester/Makefile.am +++ b/tester/Makefile.am @@ -21,13 +21,16 @@ liblinphonetester_la_SOURCES = tester.c \ flexisip_tester.c \ stun_tester.c \ remote_provisioning_tester.c \ - quality_reporting_tester.c + quality_reporting_tester.c \ + log_collection_tester.c \ + transport_tester.c \ + player_tester.c liblinphonetester_la_LDFLAGS= -no-undefined liblinphonetester_la_LIBADD= ../coreapi/liblinphone.la $(CUNIT_LIBS) AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/coreapi -AM_CFLAGS = $(STRICT_OPTIONS) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS) $(SQLITE3_CFLAGS) +AM_CFLAGS = $(STRICT_OPTIONS) $(STRICT_OPTIONS_CC) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS) $(SQLITE3_CFLAGS) if !BUILD_IOS diff --git a/tester/README b/tester/README new file mode 100644 index 000000000..dfc060ecc --- /dev/null +++ b/tester/README @@ -0,0 +1,9 @@ +This is the test suite of liblinphone, with many tests suites for Register, Calls, Message, Presence. + +All thoses tests suites require a SIP server configured accordingly in order to execute. Naturally a Flexisip SIP server is used, whose configuration is put in the flexisip/ directory here. + +In order to invoke it, just place into the tester directory and run +$ flexisip --configfile flexisip/flexisip.conf + +The tester_hosts file contains the host-like DNS configuration file to be used by the test suite in order to resolve the virtual SIP domains used by the SIP stack. +It is possible to run the flexisip SIP server and the test suite on the same machine by passing a new tester_hosts file where domains resolve to 127.0.0.1 to the tester, using the --dns-hosts option. diff --git a/tester/call_tester.c b/tester/call_tester.c index a64193a3d..f1a92a07c 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -25,9 +25,16 @@ #include "lpconfig.h" #include "private.h" #include "liblinphone_tester.h" +#include "mediastreamer2/dsptools.h" +#ifdef WIN32 +#define unlink _unlink +#endif + +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_audio_codecs_except_one(LinphoneCore *lc, const char *mime); +static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mime, int rate); +static char *create_filepath(const char *dir, const char *filename, const char *ext); // prototype definition for call_recording() #ifdef ANDROID @@ -66,6 +73,8 @@ void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState case LinphoneCallIncomingEarlyMedia :counters->number_of_LinphoneCallIncomingEarlyMedia++;break; case LinphoneCallUpdating :counters->number_of_LinphoneCallUpdating++;break; case LinphoneCallReleased :counters->number_of_LinphoneCallReleased++;break; + case LinphoneCallEarlyUpdating: counters->number_of_LinphoneCallEarlyUpdating++;break; + case LinphoneCallEarlyUpdatedByRemote: counters->number_of_LinphoneCallEarlyUpdatedByRemote++;break; default: CU_FAIL("unexpected event");break; } @@ -124,8 +133,8 @@ static void linphone_call_cb(LinphoneCall *call,void * user_data) { void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreManager* callee) { LinphoneCall *c1,*c2; - int i; int dummy=0; + MSTimeSpec ts; c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); @@ -136,7 +145,9 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana if (!c1 || !c2) return; linphone_call_ref(c1); linphone_call_ref(c2); - for (i=0; i<24 /*=12s need at least one exchange of SR to maybe 10s*/; i++) { + + liblinphone_tester_clock_start(&ts); + do { if (linphone_call_get_audio_stats(c1)->round_trip_delay >0.0 && linphone_call_get_audio_stats(c2)->round_trip_delay >0.0 && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || linphone_call_get_video_stats(c1)->round_trip_delay>0.0) @@ -145,8 +156,7 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana } wait_for_until(caller->lc,callee->lc,&dummy,1,500); /*just to sleep while iterating*/ - - } + }while (!liblinphone_tester_clock_elapsed(&ts,12000)); CU_ASSERT_TRUE(linphone_call_get_audio_stats(c1)->round_trip_delay>0.0); CU_ASSERT_TRUE(linphone_call_get_audio_stats(c2)->round_trip_delay>0.0); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { @@ -159,10 +169,10 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana linphone_call_unref(c2); } -bool_t call_with_params(LinphoneCoreManager* caller_mgr +bool_t call_with_params2(LinphoneCoreManager* caller_mgr ,LinphoneCoreManager* callee_mgr , const LinphoneCallParams *caller_params - , const LinphoneCallParams *callee_params) { + , const LinphoneCallParams *callee_params, bool_t build_callee_params) { int retry=0; stats initial_caller=caller_mgr->stat; stats initial_callee=callee_mgr->stat; @@ -207,17 +217,26 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr else { LinphoneAddress* callee_from=linphone_address_clone(caller_mgr->identity); linphone_address_set_port(callee_from,0); /*remove port because port is never present in from header*/ + if (linphone_call_params_get_privacy(linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc))) == LinphonePrivacyNone) { - CU_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_core_get_current_call_remote_address(callee_mgr->lc))); + /*don't check in case of p asserted id*/ + if (!lp_config_get_int(callee_mgr->lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0)) + CU_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_core_get_current_call_remote_address(callee_mgr->lc))); } else { CU_ASSERT_FALSE(linphone_address_weak_equal(callee_from,linphone_core_get_current_call_remote_address(callee_mgr->lc))); } linphone_address_destroy(callee_from); } - if (callee_params) + if (callee_params){ linphone_core_accept_call_with_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc),callee_params); - else + }else if (build_callee_params){ + LinphoneCallParams *default_params=linphone_core_create_call_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc)); + ms_error("Created default call params with video=%i", linphone_call_params_video_enabled(default_params)); + linphone_core_accept_call_with_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc),default_params); + linphone_call_params_destroy(default_params); + }else{ linphone_core_accept_call(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc)); + } CU_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); CU_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); @@ -237,11 +256,19 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee_mgr->lc)); CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc)); call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc)); - CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc)); + CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(callee_mgr->lc)); } } return result; } + +bool_t call_with_params(LinphoneCoreManager* caller_mgr + ,LinphoneCoreManager* callee_mgr + , const LinphoneCallParams *caller_params + , const LinphoneCallParams *callee_params){ + return call_with_params2(caller_mgr,callee_mgr,caller_params,callee_params,FALSE); +} + bool_t call_with_caller_params(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr, const LinphoneCallParams *params) { return call_with_params(caller_mgr,callee_mgr,params,NULL); } @@ -250,10 +277,12 @@ bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr){ return call_with_params(caller_mgr,callee_mgr,NULL,NULL); } -static void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){ +void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){ linphone_core_terminate_all_calls(m1->lc); CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m1->stat.number_of_LinphoneCallEnd,1)); CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m2->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m1->stat.number_of_LinphoneCallReleased,1)); + CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m2->stat.number_of_LinphoneCallReleased,1)); } static void simple_call(void) { @@ -429,28 +458,47 @@ static void call_with_specified_codec_bitrate(void) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); const LinphoneCallStats *pauline_stats,*marie_stats; bool_t call_ok; - if (linphone_core_find_payload_type(marie->lc,"opus",48000,-1)==NULL){ + char * codec = "opus"; + int rate = 48000; + int min_bw=24; + int max_bw=40; + +#ifdef __arm__ + if (ms_get_cpu_count() <2) { /*2 opus codec channel + resampler is too much for a single core*/ +#ifndef ANDROID + codec = "speex"; + rate = 8000; + min_bw=20; + max_bw=35; +#else + CU_PASS("Test requires at least a dual core"); + goto end; +#endif + } +#endif + + if (linphone_core_find_payload_type(marie->lc,codec,rate,-1)==NULL){ ms_warning("opus codec not supported, test skipped."); goto end; } - disable_all_audio_codecs_except_one(marie->lc,"opus"); - disable_all_audio_codecs_except_one(pauline->lc,"opus"); + disable_all_audio_codecs_except_one(marie->lc,codec,rate); + disable_all_audio_codecs_except_one(pauline->lc,codec,rate); linphone_core_set_payload_type_bitrate(marie->lc, - linphone_core_find_payload_type(marie->lc,"opus",48000,-1), - 50); + linphone_core_find_payload_type(marie->lc,codec,rate,-1), + max_bw); linphone_core_set_payload_type_bitrate(pauline->lc, - linphone_core_find_payload_type(pauline->lc,"opus",48000,-1), - 24); + linphone_core_find_payload_type(pauline->lc,codec,rate,-1), + min_bw); CU_ASSERT_TRUE((call_ok=call(pauline,marie))); if (!call_ok) goto end; liblinphone_tester_check_rtcp(marie,pauline); marie_stats=linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc)); pauline_stats=linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); - CU_ASSERT_TRUE(marie_stats->download_bandwidth<30); - CU_ASSERT_TRUE(pauline_stats->download_bandwidth>45); + CU_ASSERT_TRUE(marie_stats->download_bandwidth<(min_bw+5+min_bw*.1)); + CU_ASSERT_TRUE(pauline_stats->download_bandwidth>(max_bw-5-max_bw*.1)); end: linphone_core_manager_destroy(marie); @@ -544,7 +592,7 @@ static void cancelled_call(void) { linphone_core_manager_destroy(pauline); } -static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mime){ +static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mime, int rate){ const MSList *elem=linphone_core_get_audio_codecs(lc); PayloadType *pt; @@ -552,7 +600,7 @@ static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mi pt=(PayloadType*)elem->data; linphone_core_enable_payload_type(lc,pt,FALSE); } - pt=linphone_core_find_payload_type(lc,mime,-1,-1); + pt=linphone_core_find_payload_type(lc,mime,rate,-1); CU_ASSERT_PTR_NOT_NULL_FATAL(pt); linphone_core_enable_payload_type(lc,pt,TRUE); } @@ -576,14 +624,14 @@ static void call_failed_because_of_codecs(void) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); LinphoneCall* out_call; - disable_all_audio_codecs_except_one(marie->lc,"pcmu"); - disable_all_audio_codecs_except_one(pauline->lc,"pcma"); + disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1); + disable_all_audio_codecs_except_one(pauline->lc,"pcma",-1); out_call = linphone_core_invite(pauline->lc,"marie"); linphone_call_ref(out_call); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1)); - /*flexisip will retain the 488 until the "urgent reply" timeout arrives.*/ - CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,6000)); + /*flexisip will retain the 488 until the "urgent reply" timeout (I.E 5s) arrives.*/ + CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,7000)); CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonNotAcceptable); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived,0); @@ -600,7 +648,7 @@ static void call_with_dns_time_out(void) { linphone_core_set_sip_transports(marie->lc,&transport); linphone_core_iterate(marie->lc); sal_set_dns_timeout(marie->lc->sal,0); - linphone_core_invite(marie->lc,"\"t\x8et\x8e\" sip:toto@toto.com"); /*just to use non ascii values*/ + linphone_core_invite(marie->lc,"\"t\x8et\x8e\" "); /*just to use non ascii values*/ for(i=0;i<10;i++){ ms_usleep(200000); linphone_core_iterate(marie->lc); @@ -738,12 +786,13 @@ static void call_with_no_sdp(void) { linphone_core_manager_destroy(pauline); } + static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, LinphoneIceState state) { LinphoneCall *c1,*c2; bool_t audio_success=FALSE; bool_t video_success=FALSE; - int i; bool_t video_enabled; + MSTimeSpec ts; c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); @@ -756,7 +805,8 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee CU_ASSERT_EQUAL(linphone_call_params_video_enabled(linphone_call_get_current_params(c1)),linphone_call_params_video_enabled(linphone_call_get_current_params(c2))); video_enabled=linphone_call_params_video_enabled(linphone_call_get_current_params(c1)); - for (i=0;i<200;i++){ + liblinphone_tester_clock_start(&ts); + do{ if ((c1 != NULL) && (c2 != NULL)) { if (linphone_call_get_audio_stats(c1)->ice_state==state && linphone_call_get_audio_stats(c2)->ice_state==state ){ @@ -766,11 +816,12 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } - ms_usleep(50000); - } + ms_usleep(20000); + }while(!liblinphone_tester_clock_elapsed(&ts,10000)); if (video_enabled){ - for (i=0;i<200;i++){ + liblinphone_tester_clock_start(&ts); + do{ if ((c1 != NULL) && (c2 != NULL)) { if (linphone_call_get_video_stats(c1)->ice_state==state && linphone_call_get_video_stats(c2)->ice_state==state ){ @@ -780,8 +831,8 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } - ms_usleep(50000); - } + ms_usleep(20000); + }while(!liblinphone_tester_clock_elapsed(&ts,5000)); } /*make sure encryption mode are preserved*/ @@ -1142,7 +1193,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) { @@ -1181,10 +1267,60 @@ static void call_with_video_added_random_ports(void) { linphone_core_manager_destroy(pauline); } +static void call_with_several_video_switches(void) { + int dummy = 0; + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + CU_ASSERT_TRUE(call(pauline,marie)); + + CU_ASSERT_TRUE(add_video(pauline,marie)); + wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */ + CU_ASSERT_TRUE(remove_video(pauline,marie)); + CU_ASSERT_TRUE(add_video(pauline,marie)); + wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */ + CU_ASSERT_TRUE(remove_video(pauline,marie)); + /*just to sleep*/ + linphone_core_terminate_all_calls(pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void srtp_call_with_several_video_switches(void) { + int dummy = 0; + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + + if (linphone_core_media_encryption_supported(marie->lc, LinphoneMediaEncryptionSRTP)) { + linphone_core_set_media_encryption(marie->lc, LinphoneMediaEncryptionSRTP); + linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionSRTP); + + CU_ASSERT_TRUE(call(pauline,marie)); + + CU_ASSERT_TRUE(add_video(pauline,marie)); + wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */ + CU_ASSERT_TRUE(remove_video(pauline,marie)); + CU_ASSERT_TRUE(add_video(pauline,marie)); + wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */ + CU_ASSERT_TRUE(remove_video(pauline,marie)); + /*just to sleep*/ + linphone_core_terminate_all_calls(pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); + } else { + ms_warning("Not tested because SRTP is not available."); + } + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static void call_with_declined_video_base(bool_t using_policy) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - LinphoneCallParams* callee_params; + LinphoneCallParams* callee_params=NULL; LinphoneCallParams* caller_params; LinphoneCall* marie_call; LinphoneCall* pauline_call; @@ -1207,11 +1343,16 @@ static void call_with_declined_video_base(bool_t using_policy) { caller_params=linphone_core_create_default_call_parameters(pauline->lc); if (!using_policy) linphone_call_params_enable_video(caller_params,TRUE); - callee_params=linphone_core_create_default_call_parameters(marie->lc); - if (!using_policy) + + if (!using_policy){ + callee_params=linphone_core_create_default_call_parameters(marie->lc); linphone_call_params_enable_video(callee_params,FALSE); + } - CU_ASSERT_TRUE(call_with_params(pauline,marie,caller_params,callee_params)); + CU_ASSERT_TRUE(call_with_params2(pauline,marie,caller_params,callee_params,using_policy)); + + linphone_call_params_destroy(caller_params); + if (callee_params) linphone_call_params_destroy(callee_params); marie_call=linphone_core_get_current_call(marie->lc); pauline_call=linphone_core_get_current_call(pauline->lc); @@ -1234,7 +1375,7 @@ static void call_with_declined_video_using_policy(void) { } static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* marie, bool_t using_policy) { - LinphoneCallParams* callee_params; + LinphoneCallParams* callee_params=NULL; LinphoneCallParams* caller_params; LinphoneCall* marie_call; LinphoneCall* pauline_call; @@ -1257,16 +1398,18 @@ static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* ma caller_params=linphone_core_create_default_call_parameters(pauline->lc); if (!using_policy) linphone_call_params_enable_video(caller_params,TRUE); - callee_params=linphone_core_create_default_call_parameters(marie->lc); - if (!using_policy) + + if (!using_policy){ + callee_params=linphone_core_create_default_call_parameters(marie->lc); linphone_call_params_enable_video(callee_params,TRUE); + } - CU_ASSERT_TRUE(call_with_params(pauline,marie,caller_params,callee_params)); + CU_ASSERT_TRUE(call_with_params2(pauline,marie,caller_params,callee_params,using_policy)); marie_call=linphone_core_get_current_call(marie->lc); pauline_call=linphone_core_get_current_call(pauline->lc); linphone_call_params_destroy(caller_params); - linphone_call_params_destroy(callee_params); + if (callee_params) linphone_call_params_destroy(callee_params); if (marie_call && pauline_call ) { CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marie_call))); @@ -1747,6 +1890,120 @@ static void call_with_declined_srtp(void) { linphone_core_manager_destroy(pauline); } +static void on_eof(LinphonePlayer *player, void *user_data){ + LinphoneCoreManager *marie=(LinphoneCoreManager*)user_data; + marie->stat.number_of_player_eof++; +} + +static void call_with_file_player(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphonePlayer *player; + char hellopath[256]; + char *recordpath = create_filepath(liblinphone_tester_writable_dir_prefix, "record", "wav"); + double similar; + + /*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/ + unlink(recordpath); + + snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix); + + /*caller uses files instead of soundcard in order to avoid mixing soundcard input with file played using call's player*/ + linphone_core_use_files(pauline->lc,TRUE); + linphone_core_set_play_file(pauline->lc,NULL); + + /*callee is recording and plays file*/ + linphone_core_use_files(pauline->lc,TRUE); + linphone_core_set_play_file(pauline->lc,hellopath); + linphone_core_set_record_file(pauline->lc,recordpath); + + CU_ASSERT_TRUE(call(marie,pauline)); + + player=linphone_call_get_player(linphone_core_get_current_call(marie->lc)); + CU_ASSERT_PTR_NOT_NULL(player); + if (player){ + CU_ASSERT_TRUE(linphone_player_open(player,hellopath,on_eof,marie)==0); + CU_ASSERT_TRUE(linphone_player_start(player)==0); + } + CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000)); + + /*just to sleep*/ + linphone_core_terminate_all_calls(marie->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)); + CU_ASSERT_TRUE(ms_audio_diff(hellopath,recordpath,&similar,NULL,NULL)==0); + CU_ASSERT_TRUE(similar>0.9); + CU_ASSERT_TRUE(similar<=1.0); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + ms_free(recordpath); +} + +static bool_t is_format_supported(LinphoneCore *lc, const char *fmt){ + const char **formats=linphone_core_get_supported_file_formats(lc); + for(;*formats!=NULL;++formats){ + if (strcasecmp(*formats,fmt)==0) return TRUE; + } + return FALSE; +} + +static void call_with_mkv_file_player(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphonePlayer *player; + char hellomkv[256]; + char hellowav[256]; + char *recordpath; + double similar; + + ortp_set_log_level_mask(ORTP_ERROR | ORTP_FATAL | ORTP_MESSAGE | ORTP_WARNING); + + if (!is_format_supported(marie->lc,"mkv")){ + ms_warning("Test skipped, no mkv support."); + goto end; + } + recordpath = create_filepath(liblinphone_tester_writable_dir_prefix, "record", "wav"); + /*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/ + unlink(recordpath); + + snprintf(hellowav,sizeof(hellowav), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix); + snprintf(hellomkv,sizeof(hellomkv), "%s/sounds/hello8000.mkv", liblinphone_tester_file_prefix); + + /*caller uses files instead of soundcard in order to avoid mixing soundcard input with file played using call's player*/ + linphone_core_use_files(marie->lc,TRUE); + linphone_core_set_play_file(marie->lc,NULL); + /*callee is recording and plays file*/ + linphone_core_use_files(pauline->lc,TRUE); + linphone_core_set_play_file(pauline->lc,hellowav); /*just to send something but we are not testing what is sent by pauline*/ + linphone_core_set_record_file(pauline->lc,recordpath); + + CU_ASSERT_TRUE(call(marie,pauline)); + + player=linphone_call_get_player(linphone_core_get_current_call(marie->lc)); + CU_ASSERT_PTR_NOT_NULL(player); + if (player){ + CU_ASSERT_TRUE(linphone_player_open(player,hellomkv,on_eof,marie)==0); + CU_ASSERT_TRUE(linphone_player_start(player)==0); + CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000)); + linphone_player_close(player); + } + + /*just to sleep*/ + linphone_core_terminate_all_calls(marie->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)); + CU_ASSERT_TRUE(ms_audio_diff(hellowav,recordpath,&similar,NULL,NULL)==0); + CU_ASSERT_TRUE(similar>0.6); + CU_ASSERT_TRUE(similar<=1.0); + ms_free(recordpath); + +end: + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + +} + + static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -1875,6 +2132,10 @@ static void early_media_call_with_ringing(void){ LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_rc"); MSList* lcs = NULL; LinphoneCall* marie_call; + LinphoneCallLog *marie_call_log; + time_t connected_time=0; + time_t ended_time=0; + int dummy=0; lcs = ms_list_append(lcs,marie->lc); lcs = ms_list_append(lcs,pauline->lc); @@ -1888,6 +2149,7 @@ static void early_media_call_with_ringing(void){ linphone_core_set_play_file(pauline->lc,hellopath); marie_call = linphone_core_invite_address(marie->lc, pauline->identity); + marie_call_log = linphone_call_get_call_log(marie_call); CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived,1,3000)); CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging,1,1000)); @@ -1905,20 +2167,25 @@ static void early_media_call_with_ringing(void){ linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000)); + connected_time=time(NULL); CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); CU_ASSERT_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); liblinphone_tester_check_rtcp(marie, pauline); + /*just to have a call duration !=0*/ + wait_for_list(lcs,&dummy,1,2000); linphone_core_terminate_all_calls(pauline->lc); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); - - + ended_time=time(NULL); + CU_ASSERT_TRUE (labs (linphone_call_log_get_duration(marie_call_log) - (ended_time - connected_time)) <1 ); ms_list_free(lcs); } + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -1934,9 +2201,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_audio_codecs_except_one(marie->lc,"pcmu"); - disable_all_audio_codecs_except_one(pauline->lc,"pcmu"); - + disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1); + disable_all_audio_codecs_except_one(pauline->lc,"pcmu",-1); } /* Marie calls Pauline, and after the call has rung, transitions to an early_media session @@ -1960,33 +2226,30 @@ 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_audio_codecs_except_one(marie->lc,"pcma"); - disable_all_audio_codecs_except_one(pauline->lc,"pcma"); + disable_all_audio_codecs_except_one(marie->lc,"pcma",-1); + disable_all_audio_codecs_except_one(pauline->lc,"pcma",-1); } #define UPDATED_SESSION_NAME "nouveau nom de session" linphone_call_params_set_session_name(pauline_params,UPDATED_SESSION_NAME); linphone_core_update_call(pauline->lc, pauline_call, pauline_params); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallEarlyUpdating,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallEarlyUpdatedByRemote,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000)); /*just to wait 2s*/ liblinphone_tester_check_rtcp(marie, pauline); - wait_for_list(lcs, &marie->stat.number_of_LinphoneCallUpdatedByRemote,100000,2000); CU_ASSERT_STRING_EQUAL( linphone_call_params_get_session_name(linphone_call_get_remote_params(marie_call)) , UPDATED_SESSION_NAME); linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); - - CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning,1); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallConnected,1); - - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1); - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning,1); - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallConnected,1); - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallUpdating,1); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallConnected, 1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); liblinphone_tester_check_rtcp(marie, pauline); @@ -2166,6 +2429,10 @@ static void call_transfer_existing_call_outgoing_call(void) { MSList* lcs=ms_list_append(NULL,marie->lc); const MSList* calls; + + linphone_core_use_files (pauline->lc,TRUE); + linphone_core_use_files (laure->lc,TRUE); + lcs=ms_list_append(lcs,pauline->lc); lcs=ms_list_append(lcs,laure->lc); @@ -2180,7 +2447,7 @@ static void call_transfer_existing_call_outgoing_call(void) { CU_ASSERT_TRUE(call(marie,laure)); marie_call_laure=linphone_core_get_current_call(marie->lc); laure_called_by_marie=linphone_core_get_current_call(laure->lc); - /*marie pause pauline*/ + /*marie pause laure*/ CU_ASSERT_TRUE(pause_call_1(marie,marie_call_laure,laure,laure_called_by_marie)); reset_counters(&marie->stat); @@ -2435,7 +2702,9 @@ static void call_rejected_because_wrong_credentials_with_params(const char* user linphone_core_set_user_agent(marie->lc,user_agent,NULL); } if (!enable_auth_req_cb) { - marie->lc->vtable.auth_info_requested=NULL; + + ((LinphoneCoreVTable*)(marie->lc->vtables->data))->auth_info_requested=NULL; + linphone_core_add_auth_info(marie->lc,wrong_auth_info); } @@ -2670,83 +2939,265 @@ static void savpf_to_savpf_call(void) { profile_call(TRUE, TRUE, TRUE, TRUE, "RTP/SAVPF"); } -static void call_recording() { +static char *create_filepath(const char *dir, const char *filename, const char *ext) { + return ms_strdup_printf("%s/%s.%s",dir,filename,ext); +} + +static void record_call(const char *filename, bool_t enableVideo) { LinphoneCoreManager *marie = NULL; LinphoneCoreManager *pauline = NULL; LinphoneCallParams *marieParams = NULL; LinphoneCallParams *paulineParams = NULL; LinphoneCall *callInst = NULL; - int dummy=0; - char *filepath = NULL; + const char **formats, *format; + char *filepath; + int dummy=0, i; -#ifdef ANDROID -#ifdef HAVE_OPENH264 +#if defined(HAVE_OPENH264) && defined(ANDROID) + ms_init(); 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"; + if(enableVideo) { + if((linphone_core_find_payload_type(marie->lc, "H264", -1, -1) != NULL) + && (linphone_core_find_payload_type(pauline->lc, "H264", -1, -1) != NULL)) { + linphone_call_params_enable_video(marieParams, TRUE); + linphone_call_params_enable_video(paulineParams, TRUE); + disable_all_video_codecs_except_one(marie->lc, "H264"); + disable_all_video_codecs_except_one(pauline->lc, "H264"); + } else { + ms_warning("call_recording(): the H264 payload has not been found. Only sound will be recorded"); + } + } #endif - 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); + formats = linphone_core_get_supported_file_formats(marie->lc); + + for(i=0, format = formats[0]; format != NULL; i++, format = formats[i]) { + filepath = create_filepath(liblinphone_tester_writable_dir_prefix, filename, format); + remove(filepath); + linphone_call_params_set_record_file(marieParams, filepath); + if((CU_ASSERT_TRUE(call_with_params(marie, pauline, marieParams, paulineParams))) + && (CU_ASSERT_PTR_NOT_NULL(callInst = linphone_core_get_current_call(marie->lc)))) { + + ms_message("call_recording(): start recording into %s", filepath); + linphone_call_start_recording(callInst); + wait_for_until(marie->lc,pauline->lc,&dummy,1,5000); + linphone_call_stop_recording(callInst); + end_call(marie, pauline); + CU_ASSERT_EQUAL(access(filepath, F_OK), 0); + } + ms_free(filepath); } + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +#if defined(HAVE_OPENH264) && defined(ANDROID) + ms_exit(); +#endif +} - linphone_call_params_set_record_file(marieParams, filepath); +static void audio_call_recording_test(void) { + record_call("recording", FALSE); +} #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"); +static void video_call_recording_test(void) { + record_call("recording", TRUE); +} + +static void video_call_snapshot(void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); + LinphoneCallParams *marieParams = linphone_core_create_default_call_parameters(marie->lc); + LinphoneCallParams *paulineParams = linphone_core_create_default_call_parameters(pauline->lc); + LinphoneCall *callInst = NULL; + char *filename = create_filepath(liblinphone_tester_writable_dir_prefix, "snapshot", "jpeg"); + int dummy = 0; + + linphone_core_enable_video_capture(marie->lc, TRUE); + linphone_core_enable_video_display(marie->lc, TRUE); + linphone_core_enable_video_capture(pauline->lc, TRUE); + linphone_core_enable_video_display(pauline->lc, FALSE); + linphone_call_params_enable_video(marieParams, TRUE); + linphone_call_params_enable_video(paulineParams, TRUE); + + if((CU_ASSERT_TRUE(call_with_params(marie, pauline, marieParams, paulineParams))) + && (CU_ASSERT_PTR_NOT_NULL(callInst = linphone_core_get_current_call(marie->lc)))) { + linphone_call_take_video_snapshot(callInst, filename); + wait_for_until(marie->lc, pauline->lc, &dummy, 1, 5000); + CU_ASSERT_EQUAL(access(filename, F_OK), 0); + remove(filename); } + ms_free(filename); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + #endif - CU_ASSERT_TRUE(call_with_params(marie, pauline, marieParams, paulineParams)); - CU_ASSERT_PTR_NOT_NULL(callInst = linphone_core_get_current_call(marie->lc)); +static void call_with_in_dialog_update(void) { + int begin; + int leaked_objects; + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + LinphoneCallParams *params; + + belle_sip_object_enable_leak_detector(TRUE); + begin=belle_sip_object_get_object_count(); + + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new( "pauline_rc"); + CU_ASSERT_TRUE(call(pauline,marie)); + liblinphone_tester_check_rtcp(marie,pauline); + params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc)); + params->no_user_consent=TRUE; + linphone_core_update_call(marie->lc,linphone_core_get_current_call(marie->lc),params); + linphone_call_params_destroy(params); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallUpdatedByRemote,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); + end_call(marie,pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + + leaked_objects=belle_sip_object_get_object_count()-begin; + CU_ASSERT_TRUE(leaked_objects==0); + if (leaked_objects>0){ + belle_sip_object_dump_active_objects(); + } +} +static void call_with_in_dialog_codec_change_base(bool_t no_sdp) { + int begin; + int leaked_objects; + int dummy=0; + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + LinphoneCallParams *params; + + belle_sip_object_enable_leak_detector(TRUE); + begin=belle_sip_object_get_object_count(); + + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new( "pauline_rc"); + CU_ASSERT_TRUE(call(pauline,marie)); + liblinphone_tester_check_rtcp(marie,pauline); + params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc)); + + linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMU",8000,1),FALSE); /*disable PCMU*/ + linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMU",8000,1),FALSE); /*disable PCMU*/ + linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMA",8000,1),TRUE); /*enable PCMA*/ + linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMA",8000,1),TRUE); /*enable PCMA*/ + if (no_sdp) { + linphone_core_enable_sdp_200_ack(marie->lc,TRUE); + } + linphone_core_update_call(marie->lc,linphone_core_get_current_call(marie->lc),params); + linphone_call_params_destroy(params); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallUpdatedByRemote,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); + CU_ASSERT_STRING_EQUAL("PCMA",linphone_payload_type_get_mime_type(linphone_call_params_get_used_audio_codec(linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))))); + wait_for_until(marie->lc, pauline->lc, &dummy, 1, 3000); + CU_ASSERT_TRUE(linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc))->download_bandwidth>70); + CU_ASSERT_TRUE(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->download_bandwidth>70); + + end_call(marie,pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); - 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); + leaked_objects=belle_sip_object_get_object_count()-begin; + CU_ASSERT_TRUE(leaked_objects==0); + if (leaked_objects>0){ + belle_sip_object_dump_active_objects(); + } +} +static void call_with_in_dialog_codec_change(void) { + call_with_in_dialog_codec_change_base(FALSE); +} +static void call_with_in_dialog_codec_change_no_sdp(void) { + call_with_in_dialog_codec_change_base(TRUE); +} +static void call_with_custom_supported_tags(void) { + int begin; + int leaked_objects; + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + const LinphoneCallParams *remote_params; + const char *recv_supported; - CU_ASSERT_EQUAL(access(filepath, F_OK), 0); - end_call(marie, pauline); + belle_sip_object_enable_leak_detector(TRUE); + begin=belle_sip_object_get_object_count(); + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new( "pauline_rc"); + + linphone_core_add_supported_tag(marie->lc,"pouet-tag"); + CU_ASSERT_TRUE(call(pauline,marie)); + liblinphone_tester_check_rtcp(marie,pauline); + remote_params=linphone_call_get_remote_params(linphone_core_get_current_call(pauline->lc)); + recv_supported=linphone_call_params_get_custom_header(remote_params,"supported"); + CU_ASSERT_PTR_NOT_NULL(recv_supported); + if (recv_supported){ + CU_ASSERT_TRUE(strstr(recv_supported,"pouet-tag")!=NULL); + } + end_call(marie,pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); - ms_free(filepath); + + leaked_objects=belle_sip_object_get_object_count()-begin; + CU_ASSERT_TRUE(leaked_objects==0); + if (leaked_objects>0){ + belle_sip_object_dump_active_objects(); + } } +static void call_log_from_taken_from_p_asserted_id(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneCall *c1,*c2; + LinphoneCallParams *params; + const char* paulie_asserted_id ="\"Paupauche\" "; + LinphoneAddress *paulie_asserted_id_addr = linphone_address_new(paulie_asserted_id); + LpConfig *marie_lp; + + params=linphone_core_create_default_call_parameters(pauline->lc); + + linphone_call_params_add_custom_header(params,"P-Asserted-Identity",paulie_asserted_id); + /*fixme, should be able to add several time the same header linphone_call_params_add_custom_header(params,"P-Asserted-Identity","\"Paupauche\" ");*/ + + marie_lp = linphone_core_get_config(marie->lc); + lp_config_set_int(marie_lp,"sip","call_logs_use_asserted_id_instead_of_from",1); + + + CU_ASSERT_TRUE(call_with_caller_params(pauline,marie,params)); + linphone_call_params_destroy(params); + + c1=linphone_core_get_current_call(pauline->lc); + c2=linphone_core_get_current_call(marie->lc); + + CU_ASSERT_PTR_NOT_NULL(c1); + CU_ASSERT_PTR_NOT_NULL(c2); + + /*make sure remote identity is hidden*/ + CU_ASSERT_TRUE(linphone_address_weak_equal(linphone_call_get_remote_address(c2),paulie_asserted_id_addr)); + + + /*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); +} test_t call_tests[] = { { "Early declined call", early_declined_call }, { "Call declined", call_declined }, @@ -2757,6 +3208,7 @@ test_t call_tests[] = { { "Call failed because of codecs", call_failed_because_of_codecs }, { "Simple call", simple_call }, { "Outbound call with multiple proxy possible", call_outbound_with_multiple_proxy }, + { "Audio call recording", audio_call_recording_test }, #if 0 /* not yet activated because not implemented */ { "Multiple answers to a call", multiple_answers_call }, #endif @@ -2777,6 +3229,8 @@ test_t call_tests[] = { { "ZRTP call",zrtp_call}, { "ZRTP video call",zrtp_video_call}, { "SRTP call with declined srtp", call_with_declined_srtp }, + { "Call with file player", call_with_file_player}, + { "Call with mkv file player", call_with_mkv_file_player}, #ifdef VIDEO_ENABLED { "Simple video call",video_call}, { "Simple video call using policy",video_call_using_policy}, @@ -2785,12 +3239,16 @@ test_t call_tests[] = { { "ZRTP ice video call", zrtp_video_ice_call }, { "Call with video added", call_with_video_added }, { "Call with video added (random ports)", call_with_video_added_random_ports }, + { "Call with several video switches", call_with_several_video_switches }, + { "SRTP call with several video switches", srtp_call_with_several_video_switches }, { "Call with video declined", call_with_declined_video}, { "Call with video declined using policy", call_with_declined_video_using_policy}, { "Call with multiple early media", multiple_early_media }, { "Call with ICE from video to non-video", call_with_ice_video_to_novideo}, { "Call with ICE and video added", call_with_ice_video_added }, { "Video call with ICE no matching audio codecs", video_call_with_ice_no_matching_audio_codecs }, + { "Video call recording", video_call_recording_test }, + { "Snapshot", video_call_snapshot }, #endif { "SRTP ice call", srtp_ice_call }, { "ZRTP ice call", zrtp_ice_call }, @@ -2836,7 +3294,11 @@ test_t call_tests[] = { { "SAVPF to AVPF call", savpf_to_avpf_call }, { "SAVPF to SAVP call", savpf_to_savp_call }, { "SAVPF to SAVPF call", savpf_to_savpf_call }, - { "Call recording", call_recording } + { "Call with in-dialog UPDATE request", call_with_in_dialog_update }, + { "Call with in-dialog codec change", call_with_in_dialog_codec_change }, + { "Call with in-dialog codec change no sdp", call_with_in_dialog_codec_change_no_sdp }, + { "Call with custom supported tags", call_with_custom_supported_tags }, + { "Call log from taken from asserted id",call_log_from_taken_from_p_asserted_id} }; test_suite_t call_test_suite = { diff --git a/tester/certificates/altname/agent.pem b/tester/certificates/altname/agent.pem index c75085728..edb7c9fa1 100644 --- a/tester/certificates/altname/agent.pem +++ b/tester/certificates/altname/agent.pem @@ -13,17 +13,16 @@ RPIGEkQ2wzG9AJq7iJ2Yy8+2kTvULajvhI0JrSqVbgS9Z9fUKgCN6oIZfvQsrxus UcIc3KjqaP1mLw7aIpUCQH5S0B+GOwKa8+RbuRcgBvksqkRwRZn6jawoNJJSBCDn gQJ5B9PvJXppTsbnulSD2srhUqCR1pzGfnl8bYV8b8Q= -----END RSA PRIVATE KEY----- - Certificate: Data: Version: 3 (0x2) - Serial Number: 5 (0x5) + Serial Number: 9 (0x9) Signature Algorithm: sha1WithRSAEncryption Issuer: C=FR, ST=Some-State, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=Jehan Monnier/emailAddress=jehan.monnier@belledonne-communications.com Validity - Not Before: Sep 23 15:58:58 2013 GMT - Not After : Sep 23 15:58:58 2014 GMT - Subject: C=FR, ST=France, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=See altname for DNS name/emailAddress=jehan.monnier@belledonne-communications.com + Not Before: Sep 25 16:12:35 2014 GMT + Not After : Sep 22 16:12:35 2024 GMT + Subject: C=FR, ST=France, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=Jehan Monnier/emailAddress=jehan.monnier@belledonne-communications.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (1024 bit) @@ -46,31 +45,31 @@ Certificate: X509v3 Subject Alternative Name: DNS:altname.linphone.org, DNS:*.wildcard2.linphone.org Signature Algorithm: sha1WithRSAEncryption - 21:05:d3:36:82:5d:f4:f4:70:71:17:ac:06:12:49:0c:d6:c3: - 21:07:9c:2f:79:c8:14:da:e5:3a:92:04:22:5b:74:cf:53:3c: - 95:33:51:93:66:04:59:c6:3d:dd:22:cf:3f:f8:0e:24:93:6b: - 2a:02:f7:bf:ba:89:1b:72:9a:d4:1b:bf:22:3d:08:51:13:a4: - bf:43:d2:89:a1:c5:f2:e3:04:24:1e:d4:33:64:06:83:2d:b6: - 66:34:16:a9:f4:8d:6f:3f:71:86:ab:73:19:36:ae:43:29:7e: - 9d:6c:35:3a:75:f4:22:8b:c5:e3:1e:ee:c1:0d:d7:63:cc:95: - 4a:6a + 56:f5:23:64:4c:8d:85:6e:05:d6:42:a3:41:b2:6a:ab:a1:cd: + be:ae:4a:38:c5:23:4c:62:2c:06:4d:49:b7:fc:ad:86:1d:9b: + c0:7e:33:80:fa:7d:31:8b:ca:9c:28:44:b2:1c:f1:ed:73:5b: + d3:80:72:b0:6c:0b:20:2b:e5:2b:02:c6:be:14:ad:55:34:2f: + 6f:8e:bb:7b:61:ce:9c:af:85:a7:b0:cd:d1:4e:1e:17:e9:7e: + 61:ed:50:60:9a:de:d0:7a:6d:a5:ee:04:9a:5c:41:94:21:e5: + 05:61:a8:17:ab:eb:b4:cc:7f:90:9b:3a:0e:ca:31:fb:65:40: + 11:2d -----BEGIN CERTIFICATE----- -MIIDSjCCArOgAwIBAgIBBTANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx +MIIDPzCCAqigAwIBAgIBCTANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx EzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCEdyZW5vYmxlMSIwIAYDVQQK DBlCZWxsZWRvbm5lIENvbW11bmljYXRpb25zMQwwCgYDVQQLDANMQUIxFjAUBgNV BAMMDUplaGFuIE1vbm5pZXIxOjA4BgkqhkiG9w0BCQEWK2plaGFuLm1vbm5pZXJA -YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTMwOTIzMTU1ODU4WhcN -MTQwOTIzMTU1ODU4WjCBwjELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTER +YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTQwOTI1MTYxMjM1WhcN +MjQwOTIyMTYxMjM1WjCBtzELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTER MA8GA1UEBwwIR3Jlbm9ibGUxIjAgBgNVBAoMGUJlbGxlZG9ubmUgQ29tbXVuaWNh -dGlvbnMxDDAKBgNVBAsMA0xBQjEhMB8GA1UEAwwYU2VlIGFsdG5hbWUgZm9yIERO -UyBuYW1lMTowOAYJKoZIhvcNAQkBFitqZWhhbi5tb25uaWVyQGJlbGxlZG9ubmUt -Y29tbXVuaWNhdGlvbnMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDH -ZG78iwkkxJeq3ZPuQwY9DfdcNCvHXayW+5p5VUULV50ohJKtJJzhp5ysq4VH7q/d -mOnMnbYTACnqVSlph88zRdQJd/g0h6T4DyWa5Jxe+R1hwLWVfgeSXstCK8m9SwxK -qnqA5mPZxfARXg3r4XWkUK2A1lWIXCkZU3MMD4JJ4QIDAQABo1UwUzAJBgNVHRME -AjAAMAsGA1UdDwQEAwIF4DA5BgNVHREEMjAwghRhbHRuYW1lLmxpbnBob25lLm9y -Z4IYKi53aWxkY2FyZDIubGlucGhvbmUub3JnMA0GCSqGSIb3DQEBBQUAA4GBACEF -0zaCXfT0cHEXrAYSSQzWwyEHnC95yBTa5TqSBCJbdM9TPJUzUZNmBFnGPd0izz/4 -DiSTayoC97+6iRtymtQbvyI9CFETpL9D0omhxfLjBCQe1DNkBoMttmY0Fqn0jW8/ -cYarcxk2rkMpfp1sNTp19CKLxeMe7sEN12PMlUpq +dGlvbnMxDDAKBgNVBAsMA0xBQjEWMBQGA1UEAwwNSmVoYW4gTW9ubmllcjE6MDgG +CSqGSIb3DQEJARYramVoYW4ubW9ubmllckBiZWxsZWRvbm5lLWNvbW11bmljYXRp +b25zLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx2Ru/IsJJMSXqt2T +7kMGPQ33XDQrx12slvuaeVVFC1edKISSrSSc4aecrKuFR+6v3ZjpzJ22EwAp6lUp +aYfPM0XUCXf4NIek+A8lmuScXvkdYcC1lX4Hkl7LQivJvUsMSqp6gOZj2cXwEV4N +6+F1pFCtgNZViFwpGVNzDA+CSeECAwEAAaNVMFMwCQYDVR0TBAIwADALBgNVHQ8E +BAMCBeAwOQYDVR0RBDIwMIIUYWx0bmFtZS5saW5waG9uZS5vcmeCGCoud2lsZGNh +cmQyLmxpbnBob25lLm9yZzANBgkqhkiG9w0BAQUFAAOBgQBW9SNkTI2FbgXWQqNB +smqroc2+rko4xSNMYiwGTUm3/K2GHZvAfjOA+n0xi8qcKESyHPHtc1vTgHKwbAsg +K+UrAsa+FK1VNC9vjrt7Yc6cr4WnsM3RTh4X6X5h7VBgmt7Qem2l7gSaXEGUIeUF +YagXq+u0zH+QmzoOyjH7ZUARLQ== -----END CERTIFICATE----- diff --git a/tester/certificates/altname/openssl-altname.cnf b/tester/certificates/altname/openssl-altname.cnf index c4edb6c7d..0dc82fbe7 100644 --- a/tester/certificates/altname/openssl-altname.cnf +++ b/tester/certificates/altname/openssl-altname.cnf @@ -39,7 +39,7 @@ default_ca = CA_default # The default ca section #################################################################### [ CA_default ] -dir = ./demoCA # Where everything is kept +dir = . # Where everything is kept certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. diff --git a/tester/certificates/cn/openssl-cn.cnf b/tester/certificates/cn/openssl-cn.cnf index c6262db31..908f6ed4c 100644 --- a/tester/certificates/cn/openssl-cn.cnf +++ b/tester/certificates/cn/openssl-cn.cnf @@ -39,7 +39,7 @@ default_ca = CA_default # The default ca section #################################################################### [ CA_default ] -dir = ./demoCA # Where everything is kept +dir = . # Where everything is kept certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. diff --git a/tester/flexisip.conf b/tester/flexisip/flexisip.conf similarity index 99% rename from tester/flexisip.conf rename to tester/flexisip/flexisip.conf index 303a1022f..12f42d945 100755 --- a/tester/flexisip.conf +++ b/tester/flexisip/flexisip.conf @@ -151,7 +151,7 @@ db-implementation=file # for a DSN-less connection. ex3: /etc/flexisip/passwd; for a file # containing one 'user@domain password' by line. # Default value: -datasource=/etc/flexisip/userdb.conf +datasource=./flexisip/userdb.conf # Odbc SQL request to execute to obtain the password # . Named parameters are :id (the user found in the from header), diff --git a/tester/userdb.conf b/tester/flexisip/userdb.conf similarity index 100% rename from tester/userdb.conf rename to tester/flexisip/userdb.conf diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 9b2eeeb60..a1ad60ec0 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -58,6 +58,9 @@ extern test_suite_t flexisip_test_suite; extern test_suite_t stun_test_suite; extern test_suite_t remote_provisioning_test_suite; extern test_suite_t quality_reporting_test_suite; +extern test_suite_t log_collection_test_suite; +extern test_suite_t transport_test_suite; +extern test_suite_t player_test_suite; extern int liblinphone_tester_nb_test_suites(void); @@ -114,6 +117,8 @@ typedef struct _stats { int number_of_LinphoneCallIncomingEarlyMedia; int number_of_LinphoneCallUpdating; int number_of_LinphoneCallReleased; + int number_of_LinphoneCallEarlyUpdatedByRemote; + int number_of_LinphoneCallEarlyUpdating; int number_of_LinphoneTransferCallOutgoingInit; int number_of_LinphoneTransferCallOutgoingProgress; @@ -192,6 +197,9 @@ typedef struct _stats { int number_of_LinphoneCallEncryptedOn; int number_of_LinphoneCallEncryptedOff; + int number_of_NetworkReachableTrue; + int number_of_NetworkReachableFalse; + int number_of_player_eof; LinphoneChatMessage* last_received_chat_message; }stats; @@ -219,7 +227,7 @@ void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const Linph void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* message); void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size); void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size); -void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress); +void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total); void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room); void info_message_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg); void new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url); @@ -239,6 +247,7 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr , const LinphoneCallParams *caller_params , const LinphoneCallParams *callee_params); bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr); +void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2); stats * get_stats(LinphoneCore *lc); LinphoneCoreManager *get_manager(LinphoneCore *lc); const char *liblinphone_tester_get_subscribe_content(void); diff --git a/tester/log_collection_tester.c b/tester/log_collection_tester.c new file mode 100644 index 000000000..2fd91509e --- /dev/null +++ b/tester/log_collection_tester.c @@ -0,0 +1,147 @@ +/* + belle-sip - SIP (RFC3261) library. + Copyright (C) 2010 Belledonne Communications SARL + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include "CUnit/Basic.h" +#include "linphonecore.h" +#include "private.h" +#include "liblinphone_tester.h" + +extern char *strptime(char*, char*, struct tm*); + +LinphoneCoreManager* setup(bool_t enable_logs) { + LinphoneCoreManager *marie; + int timeout_ms = 3000; + + linphone_core_enable_log_collection(enable_logs); + + + // linphone_core_set_log_collection_size(10); + marie = linphone_core_manager_new( "marie_rc"); + // wait a few seconds to generate some traffic + while (timeout_ms > 0){ + linphone_core_iterate(marie->lc); + ms_usleep(100000); //100 ms sleep + timeout_ms -= 100; + // Generate some logs + ms_message("Time left: %d", timeout_ms); + } + return marie; +} + +time_t check_file(char * filepath, bool_t remove_file) { + time_t time_curr = -1; + if (filepath != NULL) { + int line_count = 0; + FILE *file = fopen(filepath, "r"); + char *line = NULL; + size_t line_size = 256; + struct tm tm_curr; + time_t time_prev = -1; + + // 1) expect to find folder name in filename path + CU_ASSERT_PTR_NOT_NULL(strstr(filepath, liblinphone_tester_writable_dir_prefix)); + + // 2) check file contents + while (getline(&line, &line_size, file) != -1) { + // a) there should be at least 100 lines + ++line_count; + + // b) logs should be ordered by date (format: 2014-11-04 15:22:12:606) + if (strlen(line) > 24) { + char date[24] = {'\0'}; + memcpy(date, line, 23); + if (strptime(date, "%Y-%m-%d %H:%M:%S", &tm_curr) != NULL) { + time_curr = mktime(&tm_curr); + CU_ASSERT_TRUE(time_curr >= time_prev); + time_prev = time_curr; + } + } + } + CU_ASSERT(line_count > 100); + free(line); + fclose(file); + if (remove_file) { + remove(filepath); + } + ms_free(filepath); + } + // return latest time in file + return time_curr; +} + +static OrtpLogLevel old_log_level; +// static LinphoneLogCollectionState old_collection_state; +static int collect_init() { + old_log_level = ortp_get_log_level_mask(); + // old_collection_state = liblinphone_log_collection_enabled; + // CU_ASSERT_FALSE("Fixme: // old_collection_state = liblinphone_log_collection_enabled;"); + + // if we want some logs, we must force them... even if user dont want to! + linphone_core_set_log_level(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL); + linphone_core_set_log_collection_path(liblinphone_tester_writable_dir_prefix); + + return 0; +} + +static int collect_cleanup() { + linphone_core_set_log_level(old_log_level); + // liblinphone_log_collection_enabled = old_collection_state; + // CU_ASSERT_FALSE("Fixme: // liblinphone_log_collection_enabled = old_collection_state;"); + + return 0; +} + +static void collect_files_disabled() { + LinphoneCoreManager* marie = setup(FALSE); + CU_ASSERT_PTR_NULL(linphone_core_compress_log_collection(marie->lc)); + linphone_core_manager_destroy(marie); +} + +static void collect_files_filled() { + LinphoneCoreManager* marie = setup(TRUE); + char * filepath = linphone_core_compress_log_collection(marie->lc); + CU_ASSERT_PTR_NOT_NULL(filepath); + CU_ASSERT_EQUAL(ms_time(0), check_file(filepath, FALSE)); + linphone_core_manager_destroy(marie); +} + +static void collect_files_small_size() { + LinphoneCoreManager* marie = setup(TRUE); + // linphone_core_set_log_collection_size(10); + char * filepath= linphone_core_compress_log_collection(marie->lc); + CU_ASSERT_PTR_NOT_NULL(filepath); + CU_ASSERT_EQUAL(ms_time(0), check_file(filepath, TRUE)); + linphone_core_manager_destroy(marie); +} + +test_t log_collection_tests[] = { + { "No file when disabled", collect_files_disabled}, + { "Collect files filled when enabled", collect_files_filled}, + { "Logs collected into small file", collect_files_small_size}, +}; + +test_suite_t log_collection_test_suite = { + "LogCollection", + collect_init, + collect_cleanup, + sizeof(log_collection_tests) / sizeof(log_collection_tests[0]), + log_collection_tests +}; + diff --git a/tester/message_tester.c b/tester/message_tester.c index d71f2db53..5fb61d999 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -47,7 +47,7 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess counters = get_stats(lc); counters->number_of_LinphoneMessageReceived++; 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); + counters->last_received_chat_message=linphone_chat_message_ref(message); if (linphone_chat_message_get_file_transfer_information(message)) { counters->number_of_LinphoneMessageReceivedWithFile++; } else if (linphone_chat_message_get_external_body_url(message)) { @@ -66,10 +66,9 @@ void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *message, cons FILE* file=NULL; char receive_file[256]; snprintf(receive_file,sizeof(receive_file), "%s/receive_file.dump", liblinphone_tester_writable_dir_prefix); - if (!linphone_chat_message_get_user_data(message)) { /*first chunk, creating file*/ - file = fopen("receive_file.dump","wb"); + file = fopen(receive_file,"wb"); linphone_chat_message_set_user_data(message,(void*)file); /*store fd for next chunks*/ } else { /*next chunk*/ @@ -77,8 +76,6 @@ void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *message, cons if (size==0) { /* tranfer complete */ stats* counters = get_stats(lc); - linphone_chat_room_destroy(linphone_chat_message_get_chat_room(message)); - linphone_chat_message_destroy(message); counters->number_of_LinphoneMessageExtBodyReceived++; fclose(file); } else { /* store content on a file*/ @@ -119,12 +116,13 @@ void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const L /** * function invoked to report file transfer progress. * */ -void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) { +void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) { const LinphoneAddress* from_address = linphone_chat_message_get_from(message); const LinphoneAddress* to_address = linphone_chat_message_get_to(message); 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); - ms_message(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress + int progress = (int)((offset * 100)/total); + ms_message(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", progress ,(linphone_chat_message_is_outgoing(message)?"sent":"received") , content->type , content->subtype @@ -173,7 +171,12 @@ static void text_message(void) { char* to = linphone_address_as_string(marie->identity); LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); ms_free(to); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1); @@ -195,7 +198,12 @@ static void text_message_within_dialog(void) { to = linphone_address_as_string(marie->identity); chat_room = linphone_core_create_chat_room(pauline->lc,to); ms_free(to); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } CU_ASSERT_TRUE(call(marie,pauline)); linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); @@ -209,12 +217,9 @@ static void text_message_within_dialog(void) { static LinphoneAuthInfo* text_message_with_credential_from_auth_cb_auth_info; static void text_message_with_credential_from_auth_cb_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { - stats* counters; ms_message("text_message_with_credential_from_auth_cb:Auth info requested for user id [%s] at realm [%s]\n" ,username ,realm); - counters = get_stats(lc); - counters->number_of_auth_info_requested++; linphone_core_add_auth_info(lc,text_message_with_credential_from_auth_cb_auth_info); /*add stored authentication info to LinphoneCore*/ } @@ -222,19 +227,25 @@ static void text_message_with_credential_from_auth_cb_auth_info_requested(Linpho static void text_message_with_credential_from_auth_cb(void) { char* to; LinphoneChatRoom* chat_room; + LinphoneCoreVTable* vtable = linphone_core_v_table_new(); LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); text_message_with_credential_from_auth_cb_auth_info=linphone_auth_info_clone((LinphoneAuthInfo*)(linphone_core_get_auth_info_list(marie->lc)->data)); /*to force cb to be called*/ linphone_core_clear_all_auth_info(marie->lc); - marie->lc->vtable.auth_info_requested=text_message_with_credential_from_auth_cb_auth_info_requested; + vtable->auth_info_requested=text_message_with_credential_from_auth_cb_auth_info_requested; + linphone_core_add_listener(marie->lc, vtable); to = linphone_address_as_string(marie->identity); chat_room = linphone_core_create_chat_room(pauline->lc,to); ms_free(to); - - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1); @@ -257,8 +268,13 @@ static void text_message_with_privacy(void) { linphone_core_get_default_proxy(pauline->lc,&pauline_proxy); linphone_proxy_config_set_privacy(pauline_proxy,LinphonePrivacyId); - CU_ASSERT_PTR_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); - + CU_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1); @@ -299,6 +315,12 @@ static void text_message_compatibility_mode(void) { CU_ASSERT_TRUE (wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationOk,1)); chat_room = linphone_core_create_chat_room(marie->lc,to); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceivedLegacy,1); @@ -307,17 +329,35 @@ static void text_message_compatibility_mode(void) { } static void text_message_with_ack(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - char* to = linphone_address_as_string(marie->identity); - LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); - LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); - linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); - CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); - CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); - linphone_core_manager_destroy(marie); - linphone_core_manager_destroy(pauline); + int leaked_objects; + int begin; + belle_sip_object_enable_leak_detector(TRUE); + begin=belle_sip_object_get_object_count(); + + { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + char* to = linphone_address_as_string(marie->identity); + LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); + LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } + linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + } + leaked_objects=belle_sip_object_get_object_count()-begin; + CU_ASSERT_TRUE(leaked_objects==0); + if (leaked_objects>0){ + belle_sip_object_dump_active_objects(); + } } static void text_message_with_external_body(void) { @@ -327,6 +367,12 @@ static void text_message_with_external_body(void) { LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); linphone_chat_message_set_external_body_url(message,message_external_body_url="http://www.linphone.org"); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); /* check transient message list: the message should be in it, and should be the only one */ @@ -377,11 +423,71 @@ static void file_transfer_message(void) { content.size=sizeof(big_file); /*total size to be transfered*/ content.name = "bigfile.txt"; message = linphone_chat_room_create_file_transfer_message(chat_room, &content); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } + linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1)); + if (marie->stat.last_received_chat_message ) { + linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc); + } + 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); +} + +/* same than previous but with a 160 characters file */ +#define SMALL_FILE_SIZE 160 +static void small_file_transfer_message(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); + + for (i=0;ilc,"https://www.linphone.org:444/lft.php"); + + /* create a chatroom on pauline's side */ + to = linphone_address_as_string(marie->identity); + chat_room = linphone_core_create_chat_room(pauline->lc,to); + ms_free(to); + /* create a file transfer message */ + memset(&content,0,sizeof(content)); + content.type="text"; + content.subtype="plain"; + content.size=SMALL_FILE_SIZE; /*total size to be transfered*/ + content.name = "bigfile.txt"; + message = linphone_chat_room_create_file_transfer_message(chat_room, &content); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1)); if (marie->stat.last_received_chat_message ) { - linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change); + linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc); } CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageExtBodyReceived,1)); @@ -426,7 +532,12 @@ static void file_transfer_message_io_error_upload(void) { content.size=sizeof(big_file); /*total size to be transfered*/ content.name = "bigfile.txt"; message = linphone_chat_room_create_file_transfer_message(chat_room, &content); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); /*wait for file to be 25% uploaded and simultate a network error*/ @@ -439,6 +550,10 @@ static void file_transfer_message_io_error_upload(void) { CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,0); sal_set_send_error(pauline->lc->sal, 0); + + linphone_core_refresh_registers(pauline->lc); /*to make sure registration is back in registered and so it can be later unregistered*/ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneRegistrationOk,pauline->stat.number_of_LinphoneRegistrationOk+1)); + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -478,7 +593,12 @@ static void file_transfer_message_io_error_download(void) { content.size=sizeof(big_file); /*total size to be transfered*/ content.name = "bigfile.txt"; message = linphone_chat_room_create_file_transfer_message(chat_room, &content); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); /* wait for marie to receive pauline's message */ @@ -486,7 +606,7 @@ static void file_transfer_message_io_error_download(void) { 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); + linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc); /* 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 */ @@ -537,7 +657,12 @@ static void file_transfer_message_upload_cancelled(void) { content.size=sizeof(big_file); /*total size to be transfered*/ content.name = "bigfile.txt"; message = linphone_chat_room_create_file_transfer_message(chat_room, &content); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); /*wait for file to be 50% uploaded and cancel the transfer */ @@ -554,6 +679,7 @@ static void file_transfer_message_upload_cancelled(void) { } static void file_transfer_message_download_cancelled(void) { +#if 0 int i; char* to; LinphoneChatRoom* chat_room; @@ -586,7 +712,12 @@ static void file_transfer_message_download_cancelled(void) { content.size=sizeof(big_file); /*total size to be transfered*/ content.name = "bigfile.txt"; message = linphone_chat_room_create_file_transfer_message(chat_room, &content); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); /* wait for marie to receive pauline's message */ @@ -594,7 +725,7 @@ static void file_transfer_message_download_cancelled(void) { 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); + linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc); /* 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 */ @@ -608,6 +739,8 @@ static void file_transfer_message_download_cancelled(void) { linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); +#endif + ms_error("Test skipped"); } static void text_message_with_send_error(void) { @@ -621,6 +754,12 @@ static void text_message_with_send_error(void) { /*simultate a network error*/ sal_set_send_error(marie->lc->sal, -1); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,marie->lc); /* check transient message list: the message should be in it, and should be the only one */ @@ -646,12 +785,15 @@ static void text_message_denied(void) { char* to = linphone_address_as_string(pauline->identity); LinphoneChatRoom* chat_room = linphone_core_create_chat_room(marie->lc,to); LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); - reset_counters(&marie->stat); - reset_counters(&pauline->stat); /*pauline doesn't want to be disturbed*/ linphone_core_disable_chat(pauline->lc,LinphoneReasonDoNotDisturb); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,marie->lc); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1)); @@ -694,6 +836,12 @@ static void info_message_with_args(bool_t with_content) { ct.size=strlen(info_content); linphone_info_message_set_content(info,&ct); } + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info); linphone_info_message_destroy(info); @@ -739,6 +887,12 @@ static void is_composing_notification(void) { int dummy = 0; ms_free(to); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_compose(chat_room); wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /*just to sleep while iterating*/ linphone_chat_room_send_message(chat_room, "Composing a message"); @@ -754,12 +908,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; @@ -768,21 +921,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" */ @@ -790,16 +939,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) { @@ -811,10 +961,11 @@ static void message_storage_migration() { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); char src_db[256]; char tmp_db[256]; + MSList* chatrooms; snprintf(src_db,sizeof(src_db), "%s/messages.db", liblinphone_tester_file_prefix); snprintf(tmp_db,sizeof(tmp_db), "%s/tmp.db", liblinphone_tester_writable_dir_prefix); - CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 1); + CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 0); // enable to test the performances of the migration step //linphone_core_message_storage_set_debug(marie->lc, TRUE); @@ -823,13 +974,59 @@ static void message_storage_migration() { // This will test the migration procedure linphone_core_set_chat_database_path(marie->lc, tmp_db); - MSList* chatrooms = linphone_core_get_chat_rooms(marie->lc); + chatrooms = linphone_core_get_chat_rooms(marie->lc); CU_ASSERT(ms_list_size(chatrooms) > 0); // check that all messages have been migrated to the UTC time storage CU_ASSERT(sqlite3_exec(marie->lc->db, "SELECT * FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK ); + + linphone_core_manager_destroy(marie); + remove(tmp_db); +} + +static void history_messages_count() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *jehan_addr = linphone_address_new(""); + LinphoneChatRoom *chatroom; + MSList *messages; + char src_db[256]; + char tmp_db[256]; + snprintf(src_db,sizeof(src_db), "%s/messages.db", liblinphone_tester_file_prefix); + snprintf(tmp_db,sizeof(tmp_db), "%s/tmp.db", liblinphone_tester_writable_dir_prefix); + + CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 0); + + linphone_core_set_chat_database_path(marie->lc, tmp_db); + + chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr); + CU_ASSERT_PTR_NOT_NULL(chatroom); + if (chatroom){ + MSList *history=linphone_chat_room_get_history(chatroom,0); + CU_ASSERT_EQUAL(linphone_chat_room_get_history_size(chatroom), 1270); + CU_ASSERT_EQUAL(ms_list_size(history), linphone_chat_room_get_history_size(chatroom)); + /*check the second most recent message*/ + CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)history->next->data), "Fore and aft follow each other."); + + /*test offset+limit: retrieve the 42th latest message only and check its content*/ + messages=linphone_chat_room_get_history_range(chatroom, 42, 42); + CU_ASSERT_EQUAL(ms_list_size(messages), 1); + CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->data), "If you open yourself to the Tao is intangible and evasive, yet prefers to keep us at the mercy of the kingdom, then all of the streams of hundreds of valleys because of its limitless possibilities."); + + /*test offset without limit*/ + CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, -1)), 1270-1265); + + /*test limit without offset*/ + CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 0, 5)), 6); + + /*test invalid start*/ + CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, 1260)), 1270-1265); + } + linphone_core_manager_destroy(marie); + linphone_address_destroy(jehan_addr); + remove(tmp_db); } + #endif test_t message_tests[] = { @@ -842,6 +1039,7 @@ 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 }, + { "Small File transfer message", small_file_transfer_message}, { "File transfer message with io error at upload", file_transfer_message_io_error_upload }, /* { "File transfer message with io error at download", file_transfer_message_io_error_download },*/ { "File transfer message upload cancelled", file_transfer_message_upload_cancelled }, @@ -852,6 +1050,7 @@ test_t message_tests[] = { { "IsComposing notification", is_composing_notification } #ifdef MSG_STORAGE_ENABLED ,{ "Database migration", message_storage_migration } + ,{ "History count", history_messages_count } #endif }; diff --git a/tester/messages.db b/tester/messages.db index 072aed397..30fd10efb 100644 Binary files a/tester/messages.db and b/tester/messages.db differ diff --git a/tester/player_tester.c b/tester/player_tester.c new file mode 100644 index 000000000..17e692d23 --- /dev/null +++ b/tester/player_tester.c @@ -0,0 +1,100 @@ +/* + liblinphone_tester - liblinphone test suite + Copyright (C) 2013 Belledonne Communications SARL + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "liblinphone_tester.h" + +static const char *_get_default_video_renderer(void){ +#ifdef WIN32 + return "MSDrawDibDisplay"; +#elif defined(ANDROID) + return "MSAndroidDisplay"; +#elif __APPLE__ && !defined(__ios) + return "MSOSXGLDisplay"; +#elif defined (HAVE_XV) + return "MSX11Video"; +#elif defined(HAVE_GL) + return "MSGLXVideo"; +#elif defined(__ios) + return "IOSDisplay"; +#else + return "MSVideoOut"; +#endif +} + +static bool_t wait_for_eof(bool_t *eof, int *time,int time_refresh, int timeout) { + while(*time < timeout && !*eof) { + ms_usleep(time_refresh * 1000U); + *time += time_refresh; + } + return *time < timeout; +} + +static void eof_callback(LinphonePlayer *player, void *user_data) { + bool_t *eof = (bool_t *)user_data; + *eof = TRUE; +} + +static void play_file(const char *filename, bool_t unsupported_format) { + LinphoneCoreManager *lc_manager; + LinphonePlayer *player; + int res, time = 0; + bool_t eof = FALSE; + + lc_manager = linphone_core_manager_new("marie_rc"); + CU_ASSERT_PTR_NOT_NULL(lc_manager); + if(lc_manager == NULL) return; + + player = linphone_core_create_local_player(lc_manager->lc, ms_snd_card_manager_get_default_card(ms_snd_card_manager_get()), _get_default_video_renderer(), NULL); + CU_ASSERT_PTR_NOT_NULL(player); + if(player == NULL) goto fail; + + res = linphone_player_open(player, filename, eof_callback, &eof); + if(unsupported_format) { + CU_ASSERT_EQUAL(res, -1); + } else { + CU_ASSERT_EQUAL(res, 0); + } + if(res == -1) goto fail; + + CU_ASSERT_EQUAL((res = linphone_player_start(player)), 0); + if(res == -1) goto fail; + + CU_ASSERT_TRUE(wait_for_eof(&eof, &time, 100, 13000)); + + linphone_player_close(player); + + fail: + if(player) linphone_player_destroy(player); + if(lc_manager) linphone_core_manager_destroy(lc_manager); +} + +static void playing_test(void) { + play_file("sounds/hello_opus_h264.mkv", !linphone_local_player_matroska_supported()); +} + +test_t player_tests[] = { + { "Playing" , playing_test } +}; + +test_suite_t player_test_suite = { + "Player", + NULL, + NULL, + sizeof(player_tests) / sizeof(test_t), + player_tests +}; diff --git a/tester/presence_tester.c b/tester/presence_tester.c index a1a1b6b63..ca3c8c18e 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -347,6 +347,62 @@ static void presence_information(void) { linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } +#define USE_PRESENCE_SERVER 0 + +#if USE_PRESENCE_SERVER +static void test_subscribe_notify_publish(void) { + + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneProxyConfig* proxy; + LinphonePresenceModel* presence; + + LpConfig *pauline_lp = linphone_core_get_config(pauline->lc); + char* lf_identity=linphone_address_as_string_uri_only(marie->identity); + LinphoneFriend *lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity); + + lp_config_set_int(pauline_lp,"sip","subscribe_expires",5); + + linphone_core_add_friend(pauline->lc,lf); + + /*wait for subscribe acknowledgment*/ + wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,1,2000); + CU_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf)); + + /*enable publish*/ + + linphone_core_get_default_proxy(marie->lc,&proxy); + linphone_proxy_config_edit(proxy); + + linphone_proxy_config_enable_publish(proxy,TRUE); + linphone_proxy_config_set_publish_expires(proxy,3); + linphone_proxy_config_done(proxy); + + /*wait for marie status*/ + wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,2,2000); + CU_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf)); + + presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,NULL); + linphone_core_set_presence_model(marie->lc,presence); + + /*wait for new status*/ + wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,3,2000); + CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf)); + + /*wait for refresh*/ + wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000); + CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf)); + + //linphone_core_remove_friend(pauline->lc,lf); + /*wait for final notify*/ + //wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000); + //CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +#endif test_t presence_tests[] = { { "Simple Subscribe", simple_subscribe }, @@ -356,6 +412,9 @@ test_t presence_tests[] = { { "Unsubscribe while subscribing", unsubscribe_while_subscribing }, { "Presence information", presence_information }, { "App managed presence failure", subscribe_failure_handle_by_app }, +#if USE_PRESENCE_SERVER + { "Subscribe with late publish", test_subscribe_notify_publish }, +#endif }; test_suite_t presence_test_suite = { diff --git a/tester/quality_reporting_tester.c b/tester/quality_reporting_tester.c index b6b449b91..d0ad63968 100644 --- a/tester/quality_reporting_tester.c +++ b/tester/quality_reporting_tester.c @@ -80,11 +80,13 @@ char * on_report_send_verify_metrics(const reporting_content_metrics_t *metrics, CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SessionDesc:")); CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "JitterBuffer:")); CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PacketLoss:")); - CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "QualityEst:")); } if (metrics->rtcp_sr_count+metrics->rtcp_xr_count>0){ CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "Delay:")); } + if (metrics->rtcp_xr_count){ + CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "QualityEst:")); + } return body; } @@ -113,16 +115,29 @@ void on_report_send_with_rtcp_xr_both(const LinphoneCall *call, int stream_type, on_report_send_with_rtcp_xr_remote(call,stream_type,content); } -void create_call_for_quality_reporting_tests( +bool_t create_call_for_quality_reporting_tests( LinphoneCoreManager* marie, LinphoneCoreManager* pauline, LinphoneCall** call_marie, - LinphoneCall** call_pauline) { - CU_ASSERT_TRUE(call(pauline,marie)); - *call_marie = linphone_core_get_current_call(marie->lc); - *call_pauline = linphone_core_get_current_call(pauline->lc); - CU_ASSERT_PTR_NOT_NULL(*call_marie); - CU_ASSERT_PTR_NOT_NULL(*call_pauline); + LinphoneCall** call_pauline, + LinphoneCallParams * params_marie, + LinphoneCallParams * params_pauline + ) { + + + bool_t call_succeeded = call_with_params(marie,pauline,params_marie,params_pauline); + CU_ASSERT_TRUE(call_succeeded); + if (call_succeeded) { + if (call_marie) { + *call_marie = linphone_core_get_current_call(marie->lc); + CU_ASSERT_PTR_NOT_NULL(*call_marie); + } + if (call_pauline) { + *call_pauline = linphone_core_get_current_call(pauline->lc); + CU_ASSERT_PTR_NOT_NULL(*call_pauline); + } + } + return call_succeeded; } static void quality_reporting_not_used_without_config() { @@ -131,21 +146,20 @@ static void quality_reporting_not_used_without_config() { LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; - create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline); - + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { // marie has stats collection enabled but pauline has not - CU_ASSERT_TRUE(linphone_proxy_config_quality_reporting_enabled(call_marie->dest_proxy)); - CU_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(call_pauline->dest_proxy)); - - CU_ASSERT_EQUAL(strcmp("sip:collector@sip.example.org", - linphone_proxy_config_get_quality_reporting_collector(call_marie->dest_proxy)), 0); + CU_ASSERT_TRUE(linphone_proxy_config_quality_reporting_enabled(call_marie->dest_proxy)); + CU_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(call_pauline->dest_proxy)); - // this field should be already filled - CU_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->info.local_addr.ip); + CU_ASSERT_EQUAL(strcmp("sip:collector@sip.example.org", + linphone_proxy_config_get_quality_reporting_collector(call_marie->dest_proxy)), 0); - // but not this one since it is updated at the end of call - CU_ASSERT_PTR_NULL(call_marie->log->reporting.reports[0]->dialog_id); + // this field should be already filled + CU_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->info.local_addr.ip); + // but not this one since it is updated at the end of call + CU_ASSERT_PTR_NULL(call_marie->log->reporting.reports[0]->dialog_id); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -189,13 +203,13 @@ static void quality_reporting_not_sent_if_low_bandwidth() { marie_params=linphone_core_create_default_call_parameters(marie->lc); linphone_call_params_enable_low_bandwidth(marie_params,TRUE); - CU_ASSERT_TRUE(call_with_params(marie,pauline,marie_params,NULL)); - - linphone_core_terminate_all_calls(marie->lc); - - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + if (create_call_for_quality_reporting_tests(marie, pauline, NULL, NULL, marie_params, NULL)) { + linphone_core_terminate_all_calls(marie->lc); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + } + linphone_call_params_destroy(marie_params); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -212,15 +226,15 @@ static void quality_reporting_invalid_report() { LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; - create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline); - linphone_reporting_set_on_report_send(call_marie, on_report_send_remove_fields); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { + linphone_reporting_set_on_report_send(call_marie, on_report_send_remove_fields); - linphone_core_terminate_all_calls(marie->lc); - - CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1)); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishError,1,3000)); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + linphone_core_terminate_all_calls(marie->lc); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishError,1,3000)); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -231,24 +245,24 @@ static void quality_reporting_at_call_termination() { LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; - create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline); - linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_remote); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { + linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_remote); - linphone_core_terminate_all_calls(marie->lc); + linphone_core_terminate_all_calls(marie->lc); - // now dialog id should be filled - CU_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->dialog_id); + // now dialog id should be filled + CU_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->dialog_id); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000)); - CU_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000)); + CU_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000)); - CU_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc)); - CU_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc)); - - // PUBLISH submission to the collector should be ok - CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); - CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); + CU_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc)); + CU_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc)); + // PUBLISH submission to the collector should be ok + CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -259,17 +273,17 @@ static void quality_reporting_interval_report() { LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; - create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline); - linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory); - linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 3); - - CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc)); - CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc)); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { + linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory); + linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 3); - // PUBLISH submission to the collector should be ok - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,3,25000)); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,3,25000)); + CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc)); + CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc)); + // PUBLISH submission to the collector should be ok + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,3,25000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,3,25000)); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -278,6 +292,7 @@ static void quality_reporting_session_report_if_video_stopped() { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc_rtcp_xr"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); LinphoneCall* call_pauline = NULL; + LinphoneCall* call_marie = NULL; LinphoneCallParams* pauline_params; LinphoneCallParams* marie_params; @@ -289,29 +304,32 @@ static void quality_reporting_session_report_if_video_stopped() { linphone_call_params_enable_video(marie_params,TRUE); pauline_params=linphone_core_create_default_call_parameters(pauline->lc); linphone_call_params_enable_video(pauline_params,TRUE); - CU_ASSERT_TRUE(call_with_params(pauline,marie,pauline_params,marie_params)); - call_pauline=linphone_core_get_current_call(pauline->lc); - linphone_reporting_set_on_report_send(linphone_core_get_current_call(marie->lc), on_report_send_with_rtcp_xr_local); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, marie_params, pauline_params)) { + linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_local); + + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,NULL,0,3000)); - CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,NULL,0,3000)); + CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); - /*remove video*/ - linphone_call_params_enable_video(pauline_params,FALSE); - linphone_core_update_call(pauline->lc,call_pauline,pauline_params); + /*remove video*/ + linphone_call_params_enable_video(pauline_params,FALSE); + linphone_core_update_call(pauline->lc,call_pauline,pauline_params); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,5000)); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,5000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,5000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,5000)); - CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); + CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); - linphone_core_terminate_all_calls(marie->lc); + linphone_core_terminate_all_calls(marie->lc); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,2,5000)); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,2,5000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,2,5000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,2,5000)); + } + linphone_call_params_destroy(marie_params); + linphone_call_params_destroy(pauline_params); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); diff --git a/tester/rcfiles/laure_rc b/tester/rcfiles/laure_rc index 54a682401..7f4d099f5 100644 --- a/tester/rcfiles/laure_rc +++ b/tester/rcfiles/laure_rc @@ -38,4 +38,7 @@ automatically_accept=0 device=StaticImage: Static picture [sound] -echocancellation=0 #to not overload cpu in case of VG \ No newline at end of file +echocancellation=0 #to not overload cpu in case of VG + +[net] +dns_srv_enabled=0 #no srv needed in general \ No newline at end of file diff --git a/tester/rcfiles/marie_rc b/tester/rcfiles/marie_rc index f4f9aa793..a1721c22a 100644 --- a/tester/rcfiles/marie_rc +++ b/tester/rcfiles/marie_rc @@ -48,3 +48,6 @@ device=StaticImage: Static picture [sound] echocancellation=0 #to not overload cpu in case of VG + +[net] +dns_srv_enabled=0 #no srv needed in general diff --git a/tester/rcfiles/pauline_rc b/tester/rcfiles/pauline_rc index 09669b72c..7322fd99a 100644 --- a/tester/rcfiles/pauline_rc +++ b/tester/rcfiles/pauline_rc @@ -45,3 +45,6 @@ device=StaticImage: Static picture [sound] echocancellation=0 #to not overload cpu in case of VG + +[net] +dns_srv_enabled=0 #no srv needed in general \ No newline at end of file diff --git a/tester/rcfiles/remote_zero_length_params_rc b/tester/rcfiles/remote_zero_length_params_rc new file mode 100644 index 000000000..915722787 --- /dev/null +++ b/tester/rcfiles/remote_zero_length_params_rc @@ -0,0 +1,7 @@ + + +
    + + test +
    +
    diff --git a/tester/rcfiles/zero_length_params_rc b/tester/rcfiles/zero_length_params_rc new file mode 100644 index 000000000..108749a5d --- /dev/null +++ b/tester/rcfiles/zero_length_params_rc @@ -0,0 +1,3 @@ +[test] +zero_len= +non_zero_len=test diff --git a/tester/register_tester.c b/tester/register_tester.c index 612e40a0b..907a10db7 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -22,20 +22,10 @@ #include "private.h" #include "liblinphone_tester.h" -static void auth_info_requested2(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { - stats* counters; - - ms_message("Auth info requested for user id [%s] at realm [%s]\n" - ,username - ,realm); - counters = get_stats(lc); - counters->number_of_auth_info_requested++; -} static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { LinphoneAuthInfo *info; - auth_info_requested2(lc,realm,username,domain); info=linphone_auth_info_new(test_username,NULL,test_password,NULL,realm,domain); /*create authentication structure from identity*/ linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ } @@ -46,7 +36,9 @@ static LinphoneCoreManager* create_lcm_with_auth(unsigned int with_auth) { LinphoneCoreManager* mgr=linphone_core_manager_new(NULL); if (with_auth) { - mgr->lc->vtable.auth_info_requested=auth_info_requested; + LinphoneCoreVTable* vtable = linphone_core_v_table_new(); + vtable->auth_info_requested=auth_info_requested; + linphone_core_add_listener(mgr->lc,vtable); } /*to allow testing with 127.0.0.1*/ @@ -322,6 +314,7 @@ static void ha1_authenticated_register(){ static void authenticated_register_with_no_initial_credentials(){ LinphoneCoreManager *mgr; + LinphoneCoreVTable* vtable = linphone_core_v_table_new(); stats* counters; char route[256]; @@ -329,7 +322,8 @@ static void authenticated_register_with_no_initial_credentials(){ mgr = linphone_core_manager_new(NULL); - mgr->lc->vtable.auth_info_requested=auth_info_requested; + vtable->auth_info_requested=auth_info_requested; + linphone_core_add_listener(mgr->lc,vtable); counters= get_stats(mgr->lc); counters->number_of_auth_info_requested=0; @@ -387,8 +381,6 @@ static void authenticated_register_with_wrong_credentials_with_params_base(const sprintf(route,"sip:%s",test_route); - mgr->lc->vtable.auth_info_requested=auth_info_requested2; - sal_set_refresher_retry_after(mgr->lc->sal,500); if (user_agent) { linphone_core_set_user_agent(mgr->lc,user_agent,NULL); @@ -467,9 +459,12 @@ static void network_state_change(){ counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; linphone_core_set_network_reachable(lc,FALSE); + CU_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_NetworkReachableFalse,1)); CU_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationNone,register_ok)); linphone_core_set_network_reachable(lc,TRUE); + CU_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_NetworkReachableTrue,1)); wait_for(lc,lc,&counters->number_of_LinphoneRegistrationOk,2*register_ok); + linphone_core_manager_destroy(mgr); } static int get_number_of_udp_proxy(const LinphoneCore* lc) { diff --git a/tester/setup_tester.c b/tester/setup_tester.c index cc72e2e95..eaa9b6a97 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -23,6 +23,12 @@ #include "lpconfig.h" #include "private.h" +static void linphone_version_test(void){ + const char *version=linphone_core_get_version(); + /*make sure the git version is always included in the version number*/ + CU_ASSERT_TRUE(strstr(version,"unknown")==NULL); +} + static void core_init_test(void) { LinphoneCoreVTable v_table; LinphoneCore* lc; @@ -102,8 +108,62 @@ static void linphone_lpconfig_from_buffer(){ conf = lp_config_new_from_buffer(buffer_linebreaks); CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"buffer_linebreaks","test",""),"ok"); lp_config_destroy(conf); +} + +static void linphone_lpconfig_from_buffer_zerolen_value(){ + /* parameters that have no value should return NULL, not "". */ + static const char* zerolen = "[test]\nzero_len=\nnon_zero_len=test"; + LpConfig* conf; + + conf = lp_config_new_from_buffer(zerolen); + + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","zero_len","LOL"),"LOL"); + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len",""),"test"); + + lp_config_set_string(conf, "test", "non_zero_len", ""); /* should remove "non_zero_len" */ + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len","LOL"), "LOL"); + + lp_config_destroy(conf); +} + +static void linphone_lpconfig_from_file_zerolen_value(){ + /* parameters that have no value should return NULL, not "". */ + static const char* zero_rc_file = "zero_length_params_rc"; + char* rc_path = ms_strdup_printf("%s/rcfiles/%s", liblinphone_tester_file_prefix, zero_rc_file); + LpConfig* conf; + + conf = lp_config_new(rc_path); + + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","zero_len","LOL"),"LOL"); + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len",""),"test"); + + lp_config_set_string(conf, "test", "non_zero_len", ""); /* should remove "non_zero_len" */ + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len","LOL"), "LOL"); + + lp_config_destroy(conf); +} + +static void linphone_lpconfig_from_xml_zerolen_value(){ + static const char* zero_xml_file = "remote_zero_length_params_rc"; + char* xml_path = ms_strdup_printf("%s/rcfiles/%s", liblinphone_tester_file_prefix, zero_xml_file); + LpConfig* conf; + + LinphoneCoreManager* mgr = linphone_core_manager_new2("empty_rc",FALSE); + + CU_ASSERT_EQUAL(linphone_remote_provisioning_load_file(mgr->lc, xml_path), 0); + + conf = mgr->lc->config; + + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","zero_len","LOL"),"LOL"); + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len",""),"test"); + + lp_config_set_string(conf, "test", "non_zero_len", ""); /* should remove "non_zero_len" */ + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len","LOL"), "LOL"); + + linphone_core_manager_destroy(mgr); } + void linphone_proxy_config_address_equal_test() { LinphoneAddress *a = linphone_address_new("sip:toto@titi"); LinphoneAddress *b = linphone_address_new("sips:toto@titi"); @@ -177,6 +237,7 @@ static void chat_root_test(void) { } test_t setup_tests[] = { + { "Version check", linphone_version_test }, { "Linphone Address", linphone_address_test }, { "Linphone proxy config address equal (internal api)", linphone_proxy_config_address_equal_test}, { "Linphone proxy config server address change (internal api)", linphone_proxy_config_is_server_config_changed_test}, @@ -184,6 +245,9 @@ test_t setup_tests[] = { { "Linphone random transport port",core_sip_transport_test}, { "Linphone interpret url", linphone_interpret_url_test }, { "LPConfig from buffer", linphone_lpconfig_from_buffer }, + { "LPConfig zero_len value from buffer", linphone_lpconfig_from_buffer_zerolen_value }, + { "LPConfig zero_len value from file", linphone_lpconfig_from_file_zerolen_value }, + { "LPConfig zero_len value from XML", linphone_lpconfig_from_xml_zerolen_value }, { "Chat room", chat_root_test } }; diff --git a/tester/sounds/hello8000.mkv b/tester/sounds/hello8000.mkv new file mode 100644 index 000000000..812d62563 Binary files /dev/null and b/tester/sounds/hello8000.mkv differ diff --git a/tester/sounds/hello_opus_h264.mkv b/tester/sounds/hello_opus_h264.mkv new file mode 100644 index 000000000..4aa5d338b Binary files /dev/null and b/tester/sounds/hello_opus_h264.mkv differ diff --git a/tester/tester.c b/tester/tester.c index 12dd60a4a..c157fe49b 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -1,4 +1,4 @@ -/* + /* tester - liblinphone test suite Copyright (C) 2013 Belledonne Communications SARL @@ -50,10 +50,22 @@ const char *liblinphone_tester_file_prefix="."; #endif /* TODO: have the same "static" for QNX and windows as above? */ +#ifdef ANDROID +const char *liblinphone_tester_writable_dir_prefix = "/data/data/org.linphone.tester/cache"; +#else const char *liblinphone_tester_writable_dir_prefix = "."; +#endif const char *userhostsfile = "tester_hosts"; - +static void network_reachable(LinphoneCore *lc, bool_t reachable) { + stats* counters; + ms_message("Network reachable [%s]",reachable?"TRUE":"FALSE"); + counters = get_stats(lc); + if (reachable) + counters->number_of_NetworkReachableTrue++; + else + counters->number_of_NetworkReachableFalse++; +} void liblinphone_tester_clock_start(MSTimeSpec *start){ ms_get_cur_time(start); } @@ -156,7 +168,7 @@ bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) { for (iterator=lcs;iterator!=NULL;iterator=iterator->next) { linphone_core_iterate((LinphoneCore*)(iterator->data)); } - ms_usleep(100000); + ms_usleep(20000); } if(counter && *counterv_table.publish_state_changed=linphone_publish_state_changed; mgr->v_table.configuring_status=linphone_configuration_status; mgr->v_table.call_encryption_changed=linphone_call_encryption_changed; + mgr->v_table.network_reachable=network_reachable; reset_counters(&mgr->stat); if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file); @@ -222,6 +235,13 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f else proxy_count=0; +#if TARGET_OS_IPHONE + linphone_core_set_playback_device( mgr->lc, "AU: Audio Unit Tester"); + linphone_core_set_capture_device( mgr->lc, "AU: Audio Unit Tester"); + linphone_core_set_ringer_device( mgr->lc, "AQ: Audio Queue Device"); + linphone_core_set_ringback(mgr->lc, NULL); +#endif + if (proxy_count) wait_for_until(mgr->lc,NULL,&mgr->stat.number_of_LinphoneRegistrationOk,proxy_count,5000*proxy_count); CU_ASSERT_EQUAL(mgr->stat.number_of_LinphoneRegistrationOk,proxy_count); @@ -250,6 +270,7 @@ void linphone_core_manager_stop(LinphoneCoreManager *mgr){ void linphone_core_manager_destroy(LinphoneCoreManager* mgr) { if (mgr->lc) linphone_core_destroy(mgr->lc); if (mgr->identity) linphone_address_destroy(mgr->identity); + if (mgr->stat.last_received_chat_message) linphone_chat_message_unref(mgr->stat.last_received_chat_message); ms_free(mgr); } @@ -366,6 +387,9 @@ void liblinphone_tester_init(void) { add_test_suite(&flexisip_test_suite); add_test_suite(&remote_provisioning_test_suite); add_test_suite(&quality_reporting_test_suite); + add_test_suite(&log_collection_test_suite); + add_test_suite(&transport_test_suite); + add_test_suite(&player_test_suite); } void liblinphone_tester_uninit(void) { @@ -444,9 +468,9 @@ int liblinphone_tester_run_tests(const char *suite_name, const char *test_name) return ret; } int liblinphone_tester_fprintf(FILE * stream, const char * format, ...) { + int result; va_list args; va_start(args, format); - int result; #ifndef ANDROID result = vfprintf(stream,format,args); #else diff --git a/tester/transport_tester.c b/tester/transport_tester.c new file mode 100644 index 000000000..8f0673d60 --- /dev/null +++ b/tester/transport_tester.c @@ -0,0 +1,174 @@ +/* + liblinphone_tester - liblinphone test suite + Copyright (C) 2013 Belledonne Communications SARL + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#include +#include +#include +#include "CUnit/Basic.h" +#include "linphonecore.h" +#include "lpconfig.h" +#include "private.h" +#include "liblinphone_tester.h" + +/* Retrieve the public IP from a given hostname */ +static const char* get_ip_from_hostname(const char * tunnel_hostname){ + struct addrinfo hints; + struct addrinfo *res = NULL, *it = NULL; + struct sockaddr_in *add; + char * output = NULL; + int err; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if ((err = getaddrinfo(tunnel_hostname, NULL, &hints, &res))){ + ms_error("error while retrieving IP from %s: %s", tunnel_hostname, gai_strerror(err)); + return NULL; + } + + for (it=res; it!=NULL; it=it->ai_next){ + add = (struct sockaddr_in *) it->ai_addr; + output = inet_ntoa( add->sin_addr ); + } + freeaddrinfo(res); + return output; +} +static char* get_public_contact_ip(LinphoneCore* lc) { + long contact_host_ip_len; + char contact_host_ip[255]; + char * contact = linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(lc)); + CU_ASSERT_PTR_NOT_NULL(contact); + contact_host_ip_len = strchr(contact, ':')-contact; + strncpy(contact_host_ip, contact, contact_host_ip_len); + contact_host_ip[contact_host_ip_len]='\0'; + ms_free(contact); + return ms_strdup(contact_host_ip); +} +static void call_with_transport_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption) { + if (linphone_core_tunnel_available()){ + char *tmp_char; + LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneCoreManager *marie = linphone_core_manager_new( "marie_rc"); + LinphoneCall *pauline_call; + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(pauline->lc); + LinphoneAddress *server_addr = linphone_address_new(linphone_proxy_config_get_server_addr(proxy)); + LinphoneAddress *route = linphone_address_new(linphone_proxy_config_get_route(proxy)); + const char * tunnel_ip = get_ip_from_hostname("tunnel.linphone.org"); + char *public_ip, *public_ip2=NULL; + + CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,1)); + public_ip = get_public_contact_ip(pauline->lc); + CU_ASSERT_STRING_NOT_EQUAL(public_ip, tunnel_ip); + + linphone_core_set_media_encryption(pauline->lc, encryption); + + if (tunnel_mode != LinphoneTunnelModeDisable){ + LinphoneTunnel *tunnel = linphone_core_get_tunnel(pauline->lc); + LinphoneTunnelConfig *config = linphone_tunnel_config_new(); + + /*tunnel works only in UDP mode*/ + linphone_proxy_config_edit(proxy); + linphone_address_set_transport(server_addr, LinphoneTransportUdp); + linphone_address_set_transport(route, LinphoneTransportUdp); + tmp_char = linphone_address_as_string(server_addr); + linphone_proxy_config_set_server_addr(proxy, tmp_char); + ms_free(tmp_char); + tmp_char = linphone_address_as_string(route); + linphone_proxy_config_set_route(proxy, tmp_char); + ms_free(tmp_char); + linphone_tunnel_config_set_host(config, "tunnel.linphone.org"); + linphone_tunnel_config_set_port(config, 443); + linphone_tunnel_config_set_remote_udp_mirror_port(config, 12345); + linphone_tunnel_add_server(tunnel, config); + linphone_tunnel_set_mode(tunnel, tunnel_mode); + linphone_tunnel_enable_sip(tunnel, with_sip); + linphone_proxy_config_done(proxy); + + /*enabling the tunnel cause another REGISTER to be made*/ + CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2)); + + if(tunnel_mode == LinphoneTunnelModeEnable) { + /* Ensure that we did use the tunnel. If so, we should see contact changed from: + Contact: ;.[...] + To: + Contact: ;[....] (91.121.209.194 must be tunnel.liphone.org) + */ + ms_free(public_ip); + public_ip = get_public_contact_ip(pauline->lc); + CU_ASSERT_STRING_EQUAL(public_ip, tunnel_ip); + } else { + public_ip2 = get_public_contact_ip(pauline->lc); + CU_ASSERT_STRING_EQUAL(public_ip, public_ip2); + } + } + + CU_ASSERT_TRUE(call(pauline,marie)); + pauline_call=linphone_core_get_current_call(pauline->lc); + CU_ASSERT_PTR_NOT_NULL(pauline_call); + if (pauline_call!=NULL){ + CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(pauline_call)), + encryption); + } + end_call(pauline,marie); + + ms_free(public_ip); + if(public_ip2 != NULL) ms_free(public_ip2); + linphone_address_destroy(server_addr); + linphone_address_destroy(route); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie); + }else{ + ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__); + } +} + +static void call_with_tunnel(void) { + call_with_transport_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone); +} + +static void call_with_tunnel_srtp(void) { + call_with_transport_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionSRTP); +} + +static void call_with_tunnel_without_sip(void) { + call_with_transport_base(LinphoneTunnelModeEnable, FALSE, LinphoneMediaEncryptionNone); +} + +static void call_with_tunnel_auto(void) { + call_with_transport_base(LinphoneTunnelModeAuto, TRUE, LinphoneMediaEncryptionNone); +} + +static void call_with_tunnel_auto_without_sip_with_srtp(void) { + call_with_transport_base(LinphoneTunnelModeAuto, FALSE, LinphoneMediaEncryptionSRTP); +} + +test_t transport_tests[] = { + { "Tunnel only", call_with_tunnel }, + { "Tunnel with SRTP", call_with_tunnel_srtp }, + { "Tunnel without SIP", call_with_tunnel_without_sip }, + { "Tunnel in automatic mode", call_with_tunnel_auto }, + { "Tunnel in automatic mode with SRTP without SIP", call_with_tunnel_auto_without_sip_with_srtp }, +}; + +test_suite_t transport_test_suite = { + "Transport", + NULL, + NULL, + sizeof(transport_tests) / sizeof(transport_tests[0]), + transport_tests +}; diff --git a/tester/upnp_tester.c b/tester/upnp_tester.c index 04b5b865b..656c9c3eb 100644 --- a/tester/upnp_tester.c +++ b/tester/upnp_tester.c @@ -43,9 +43,10 @@ static void upnp_check_state(void) { static void upnp_check_ipaddress(void) { int tmp = 0; + const char *addr; LinphoneCoreManager* lc_upnp = linphone_core_manager_new2( "upnp_rc", FALSE); wait_for(lc_upnp->lc,lc_upnp->lc,&tmp,1); - const char *addr = linphone_core_get_upnp_external_ipaddress(lc_upnp->lc); + addr = linphone_core_get_upnp_external_ipaddress(lc_upnp->lc); CU_ASSERT_TRUE(addr != NULL && strlen(addr)>=7); linphone_core_manager_destroy(lc_upnp); } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 000000000..6d383a4a7 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,55 @@ +############################################################################ +# 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() + +set(LP_GEN_WRAPPERS_SOURCE_FILES + generator.cc + generator.hh + genwrappers.cc + software-desc.cc + software-desc.hh +) + +add_definitions( + -DIN_LINPHONE +) + +set(LP_GEN_WRAPPERS_LIBS + ${LIBGCC} + ${LIBMINGWEX} + ${XML2_LIBRARIES} +) + +add_executable(lp-gen-wrappers ${LP_GEN_WRAPPERS_SOURCE_FILES}) +target_link_libraries(lp-gen-wrappers ${LP_GEN_WRAPPERS_LIBS}) + + +install(TARGETS lp-gen-wrappers + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) diff --git a/tools/Makefile.am b/tools/Makefile.am index d993aa591..0515faae2 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -2,17 +2,18 @@ AM_CPPFLAGS=\ -I$(top_srcdir) \ - -I$(top_srcdir)/coreapi + -I$(top_srcdir)/coreapi COMMON_CFLAGS=\ -DIN_LINPHONE \ $(ORTP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ $(STRICT_OPTIONS) \ - $(LIBXML2_CFLAGS) + $(STRICT_OPTIONS_CC) \ + $(LIBXML2_CFLAGS) #-fpermissive to workaround a g++ bug on macos 32bit SDK. -AM_CXXFLAGS=$(LIBXML2_CFLAGS) -fpermissive $(STRICT_OPTIONS) +AM_CXXFLAGS=$(LIBXML2_CFLAGS) -fpermissive $(STRICT_OPTIONS) $(STRICT_OPTIONS_CXX) EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc diff --git a/tools/genapixml.py b/tools/genapixml.py index 388870e2c..4f834fb0c 100755 --- a/tools/genapixml.py +++ b/tools/genapixml.py @@ -72,6 +72,7 @@ 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(' ') @@ -302,6 +303,8 @@ def __cleanDescription(self, descriptionNode): 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': @@ -335,6 +338,11 @@ def __discoverClasses(self): 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: @@ -480,6 +488,10 @@ def __parseCFunctionMemberdef(self, node): 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" @@ -499,6 +511,10 @@ def __parseCFunctionMemberdef(self, node): 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: @@ -589,12 +605,16 @@ def __generateFunction(self, parentNode, nodeName, f): 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) diff --git a/tools/generator.cc b/tools/generator.cc index 82f50c660..2b8ab0a39 100644 --- a/tools/generator.cc +++ b/tools/generator.cc @@ -52,7 +52,7 @@ void CplusplusGenerator::generate(Project *proj){ void CplusplusGenerator::writeEnumMember(ConstField *cf, bool isLast){ writeTabs(1); - mOutfile<getName(); + mOutfile<getName()<<"="<getValue(); if (!isLast) mOutfile<<","; if (!cf->getHelp().empty()) mOutfile<<"\t/**< "<getHelp()<<" */"; mOutfile< members=klass->getConstFields(); list::iterator it; string enum_name=getEnumName(klass); - int value=0; filename<getName())<<"/"<getHelp().empty()){ writeTabs(1); @@ -254,7 +253,7 @@ void JavascriptGenerator::writeEnum(Class *klass){ mOutfile<<"*/"<getName().substr(prefix_size,string::npos)<<" : "<getName().substr(prefix_size,string::npos)<<" : "<getValue(); if (++it!=members.end()) mOutfile<<","; mOutfile<setHelp(node.getChild("detaileddescription").getChild("para").getText()); list enumValues=node.getChildren("enumvalue"); list::iterator it; + int value = 0; for (it=enumValues.begin();it!=enumValues.end();++it){ - ConstField *cf=new ConstField(Type::getType("int"),(*it).getChild("name").getText()); + string initializer = (*it).getChild("initializer").getText(); + if ((initializer.length() > 1) && (initializer.at(0) == '=')) { + std::stringstream ss; + if ((initializer.length() > 2) && (initializer.at(1) == '0')) { + if ((initializer.length() > 3) && (initializer.at(2) == 'x')) { + ss << std::hex << initializer.substr(3); + } else { + ss << std::oct << initializer.substr(2); + } + } else { + ss << std::dec << initializer.substr(1); + } + ss >> value; + } + ConstField *cf=new ConstField(Type::getType("int"),(*it).getChild("name").getText(),value); cf->setHelp((*it).getChild("detaileddescription").getChild("para").getText()); klass->addConstField(cf); - + value++; } } diff --git a/tools/lpc2xml_test.c b/tools/lpc2xml_test.c index cdad72f97..03ac571cf 100644 --- a/tools/lpc2xml_test.c +++ b/tools/lpc2xml_test.c @@ -47,13 +47,15 @@ void show_usage(int argc, char *argv[]) { } int main(int argc, char *argv[]) { + lpc2xml_context *ctx; + LpConfig *lpc; if(argc != 4) { show_usage(argc, argv); return -1; } - - lpc2xml_context *ctx = lpc2xml_context_new(cb_function, NULL); - LpConfig *lpc = lp_config_new(argv[2]); + + ctx = lpc2xml_context_new(cb_function, NULL); + lpc = lp_config_new(argv[2]); lpc2xml_set_lpc(ctx, lpc); if(strcmp("convert", argv[1]) == 0) { lpc2xml_convert_file(ctx, argv[3]); diff --git a/tools/python/apixml2python.py b/tools/python/apixml2python.py index 29a2904c2..357816a5a 100755 --- a/tools/python/apixml2python.py +++ b/tools/python/apixml2python.py @@ -38,58 +38,31 @@ 'LinphoneCoreFileTransferSendCb' # missing LinphoneContent ] blacklisted_functions = [ - 'linphone_call_get_user_pointer', # rename to linphone_call_get_user_data - 'linphone_call_set_user_pointer', # rename to linphone_call_set_user_data 'linphone_call_log_get_local_stats', # missing rtp_stats_t 'linphone_call_log_get_remote_stats', # missing rtp_stats_t - 'linphone_call_log_get_start_date', # missing time_t - 'linphone_call_log_get_user_pointer', # rename to linphone_call_log_get_user_data - 'linphone_call_log_set_user_pointer', # rename to linphone_call_log_set_user_data - 'linphone_call_params_get_received_video_size', # missing MSVideoSize 'linphone_call_params_get_privacy', # missing LinphonePrivacyMask - 'linphone_call_params_get_sent_video_size', # missing MSVideoSize - 'linphone_call_params_get_used_audio_codec', # missing PayloadType - 'linphone_call_params_get_used_video_codec', # missing PayloadType 'linphone_call_params_set_privacy', # missing LinphonePrivacyMask 'linphone_chat_message_get_file_transfer_information', # missing LinphoneContent - 'linphone_chat_message_get_time', # missing time_t '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_chat_room_create_message_2', # missing time_t - 'linphone_chat_room_send_message2', # to be handwritten because of callback + 'linphone_core_add_listener', 'linphone_core_can_we_add_call', # private function - 'linphone_core_enable_payload_type', # missing PayloadType - 'linphone_core_find_payload_type', # missing PayloadType - 'linphone_core_get_audio_codecs', # missing PayloadType and MSList - 'linphone_core_get_auth_info_list', # missing MSList - 'linphone_core_get_call_logs', # missing MSList - 'linphone_core_get_calls', # missing MSList - 'linphone_core_get_chat_rooms', # missing MSList - 'linphone_core_get_default_proxy', # to be handwritten because of double pointer indirection - 'linphone_core_get_payload_type_bitrate', # missing PayloadType - 'linphone_core_get_preferred_video_size', # missing MSVideoSize - 'linphone_core_get_friend_list', # missing MSList - 'linphone_core_get_proxy_config_list', # missing MSList + 'linphone_core_enable_log_collection', # need to handle class properties + 'linphone_core_get_audio_port_range', # to be handwritten because of result via arguments 'linphone_core_get_sip_transports', # missing LCSipTransports 'linphone_core_get_sip_transports_used', # missing LCSipTransports 'linphone_core_get_supported_video_sizes', # missing MSVideoSizeDef - 'linphone_core_get_video_codecs', # missing PayloadType and MSList 'linphone_core_get_video_policy', # missing LinphoneVideoPolicy - 'linphone_core_payload_type_enabled', # missing PayloadType - 'linphone_core_payload_type_is_vbr', # missing PayloadType + 'linphone_core_get_video_port_range', # to be handwritten because of result via arguments 'linphone_core_publish', # missing LinphoneContent + 'linphone_core_remove_listener', 'linphone_core_serialize_logs', # There is no use to wrap this function + 'linphone_core_set_log_collection_path', # need to handle class properties 'linphone_core_set_log_file', # There is no use to wrap this function 'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module 'linphone_core_set_log_level', # There is no use to wrap this function - 'linphone_core_set_payload_type_bitrate', # missing PayloadType - 'linphone_core_set_preferred_video_size', # missing MSVideoSize 'linphone_core_set_video_policy', # missing LinphoneVideoPolicy - 'linphone_core_play_dtmf', # handling of char - 'linphone_core_send_dtmf', # handling of char - 'linphone_core_set_audio_codecs', # missing PayloadType and MSList - 'linphone_core_set_preview_video_size', # missing MSVideoSize 'linphone_core_set_sip_transports', # missing LCSipTransports 'linphone_core_subscribe', # missing LinphoneContent 'linphone_event_notify', # missing LinphoneContent @@ -97,7 +70,6 @@ 'linphone_event_send_subscribe', # missing LinphoneContent 'linphone_event_update_publish', # missing LinphoneContent 'linphone_event_update_subscribe', # missing LinphoneContent - 'linphone_presence_model_get_timestamp', # missing time_t '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 @@ -110,6 +82,9 @@ 'lp_config_section_to_dict' # missing LinphoneDictionary ] hand_written_functions = [ + 'linphone_chat_room_send_message2', + 'linphone_core_get_sound_devices', + 'linphone_core_get_video_devices', 'linphone_core_new', 'linphone_core_new_with_config' ] diff --git a/tools/python/apixml2python/handwritten.mustache b/tools/python/apixml2python/handwritten.mustache deleted file mode 100644 index df58453dc..000000000 --- a/tools/python/apixml2python/handwritten.mustache +++ /dev/null @@ -1,195 +0,0 @@ -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"); - 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"); - 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"); - 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_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; -} diff --git a/tools/python/apixml2python/handwritten_declarations.mustache b/tools/python/apixml2python/handwritten_declarations.mustache new file mode 100644 index 000000000..d5be0a3c4 --- /dev/null +++ b/tools/python/apixml2python/handwritten_declarations.mustache @@ -0,0 +1,15 @@ +static PyObject * pylinphone_Core_get_sound_devices(PyObject *self, void *closure); +static PyObject * pylinphone_Core_get_video_devices(PyObject *self, void *closure); + +static PyTypeObject pylinphone_VideoSizeType; + +typedef struct { + PyObject_HEAD + MSVideoSize vs; +} pylinphone_VideoSizeObject; + +int PyLinphoneVideoSize_Check(PyObject *p); +MSVideoSize PyLinphoneVideoSize_AsMSVideoSize(PyObject *obj); +PyObject * PyLinphoneVideoSize_FromMSVideoSize(MSVideoSize vs); +time_t PyDateTime_As_time_t(PyObject *obj); +PyObject * PyDateTime_From_time_t(time_t t); diff --git a/tools/python/apixml2python/handwritten_definitions.mustache b/tools/python/apixml2python/handwritten_definitions.mustache new file mode 100644 index 000000000..4ae90a9ac --- /dev/null +++ b/tools/python/apixml2python/handwritten_definitions.mustache @@ -0,0 +1,528 @@ +static void pylinphone_dispatch_messages(void) { +#ifdef WIN32 + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, 1)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +#endif +} + +static void pylinphone_log(const char *level, int indent, const char *fmt, va_list args) { + static int current_indent = 1; + PyObject *linphone_module; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + if (gstate != PyGILState_LOCKED) return; + linphone_module = PyImport_ImportModule("linphone.linphone"); + if (linphone_module != NULL) { + if (PyObject_HasAttrString(linphone_module, "__log_handler")) { + PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler"); + if (log_handler != NULL) { + if (PyCallable_Check(log_handler)) { + char logstr[4096]; + int i = 0; + if (indent == -1) current_indent--; + if (current_indent < 1) current_indent = 1; + if ((indent >= -1) && (indent <= 1)) { + for (i = 0; i < current_indent; i++) { + logstr[i] = '\t'; + } + } + if (indent == 1) current_indent++; + if (vsnprintf(logstr + i, sizeof(logstr) - i, fmt, args) > 0) { + PyObject *pyargs = Py_BuildValue("ss", level, logstr); + if (PyEval_CallObject(log_handler, pyargs) == NULL) { + PyErr_Print(); + } + Py_DECREF(pyargs); + } + } + Py_DECREF(log_handler); + } + } + Py_DECREF(linphone_module); + } + PyGILState_Release(gstate); +} + +static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + pylinphone_log("debug", indent, fmt, args); + va_end(args); +} + +static const char * pylinphone_ortp_log_level_to_string(OrtpLogLevel lev) { + switch (lev) { + default: + case ORTP_DEBUG: + return "debug"; + case ORTP_MESSAGE: + return "info"; + case ORTP_WARNING: + return "warning"; + case ORTP_ERROR: + return "error"; + case ORTP_FATAL: + return "critical"; + case ORTP_TRACE: + return "debug"; + } +} + +static void pylinphone_module_log_handler(OrtpLogLevel lev, const char *fmt, va_list args) { + PyGILState_STATE gstate; + PyObject *linphone_module; + const char *level; + + gstate = PyGILState_Ensure(); + if (gstate != PyGILState_LOCKED) return; + linphone_module = PyImport_ImportModule("linphone.linphone"); + level = pylinphone_ortp_log_level_to_string(lev); + if (linphone_module != NULL) { + if (PyObject_HasAttrString(linphone_module, "__log_handler")) { + PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler"); + if (log_handler != NULL) { + if (PyCallable_Check(log_handler)) { + char logstr[4096]; + if (vsnprintf(logstr, sizeof(logstr), fmt, args) > 0) { + PyObject *pyargs = Py_BuildValue("ss", level, logstr); + if (PyEval_CallObject(log_handler, pyargs) == NULL) { + PyErr_Print(); + } + Py_DECREF(pyargs); + } + } + Py_DECREF(log_handler); + } + } + Py_DECREF(linphone_module); + } + PyGILState_Release(gstate); +} + +static void pylinphone_init_logging(void) { + linphone_core_serialize_logs(); + linphone_core_set_log_handler(pylinphone_module_log_handler); + linphone_core_set_log_level(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL); +} + + +static PyObject * pylinphone_module_method_set_log_handler(PyObject *self, PyObject *args) { + PyObject *linphone_module = PyImport_ImportModule("linphone.linphone"); + PyObject *callback; + if (!PyArg_ParseTuple(args, "O", &callback)) { + return NULL; + } + if (!PyCallable_Check(callback) && (callback != Py_None)) { + PyErr_SetString(PyExc_TypeError, "The argument must be a callable or None"); + return NULL; + } + if (linphone_module != NULL) { + PyObject_SetAttrString(linphone_module, "__log_handler", callback); + Py_DECREF(linphone_module); + } + Py_RETURN_NONE; +} + + +static PyObject * pylinphone_Core_get_sound_devices(PyObject *self, void *closure) { + PyObject *_list; + const char **_devices; + LinphoneCore *native_ptr = pylinphone_Core_get_native_ptr(self); + + if (native_ptr == NULL) { + PyErr_SetString(PyExc_TypeError, "Invalid linphone.Core instance"); + return NULL; + } + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, self, native_ptr); + _devices = linphone_core_get_sound_devices(native_ptr); + pylinphone_dispatch_messages(); + + _list = PyList_New(0); + while (*_devices != NULL) { + PyObject *_item = PyString_FromString(*_devices); + PyList_Append(_list, _item); + _devices++; + } + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, _list); + return _list; +} + +static PyObject * pylinphone_Core_get_video_devices(PyObject *self, void *closure) { + PyObject *_list; + const char **_devices; + LinphoneCore *native_ptr = pylinphone_Core_get_native_ptr(self); + + if (native_ptr == NULL) { + PyErr_SetString(PyExc_TypeError, "Invalid linphone.Core instance"); + return NULL; + } + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, self, native_ptr); + _devices = linphone_core_get_video_devices(native_ptr); + pylinphone_dispatch_messages(); + + _list = PyList_New(0); + while (*_devices != NULL) { + PyObject *_item = PyString_FromString(*_devices); + PyList_Append(_list, _item); + _devices++; + } + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, _list); + return _list; +} + +static PyObject * pylinphone_Core_class_method_new(PyObject *cls, PyObject *args) { + LinphoneCore * cresult; + pylinphone_CoreObject *self; + PyObject * pyret; + LinphoneCoreVTable _vtable = { 0 }; + PyObject * _vtable_dict; + const char * _config_path; + const char * _factory_config_path; + + if (!PyArg_ParseTuple(args, "Ozz", &_vtable_dict, &_config_path, &_factory_config_path)) { + return NULL; + } + if (!PyDict_Check(_vtable_dict)) { + PyErr_SetString(PyExc_TypeError, "The first argument must be a dictionary"); + return NULL; + } + + self = (pylinphone_CoreObject *)PyObject_CallObject((PyObject *) &pylinphone_CoreType, NULL); + if (self == NULL) { + return NULL; + } + Py_INCREF(_vtable_dict); + self->vtable_dict = _vtable_dict; +{{#events}} + {{{event_vtable_reference}}} +{{/events}} + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p, \"%s\", \"%s\")", __FUNCTION__, _vtable_dict, _config_path, _factory_config_path); + cresult = linphone_core_new(&_vtable, _config_path, _factory_config_path, self); + self->native_ptr = cresult; + + pyret = Py_BuildValue("O", self); + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret); + Py_DECREF(self); + return pyret; +} + +static PyObject * pylinphone_Core_class_method_new_with_config(PyObject *cls, PyObject *args) { + LinphoneCore * cresult; + pylinphone_CoreObject *self; + PyObject * pyret; + LinphoneCoreVTable _vtable = { 0 }; + PyObject * _vtable_dict; + PyObject * _config; + LpConfig * _config_native_ptr; + + if (!PyArg_ParseTuple(args, "OO", &_vtable_dict, &_config)) { + return NULL; + } + if (!PyDict_Check(_vtable_dict)) { + PyErr_SetString(PyExc_TypeError, "The first argument must be a dictionary"); + return NULL; + } + + if ((_config_native_ptr = pylinphone_LpConfig_get_native_ptr(_config)) == NULL) { + return NULL; + } + + self = (pylinphone_CoreObject *)PyObject_CallObject((PyObject *) &pylinphone_CoreType, NULL); + if (self == NULL) { + return NULL; + } + Py_INCREF(_vtable_dict); + self->vtable_dict = _vtable_dict; +{{#events}} + {{{event_vtable_reference}}} +{{/events}} + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, _config, _config_native_ptr); + cresult = linphone_core_new_with_config(&_vtable, _config_native_ptr, self); + self->native_ptr = cresult; + + pyret = Py_BuildValue("O", self); + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret); + Py_DECREF(self); + return pyret; +} + + +static void pylinphone_ChatRoom_callback_chat_message_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state, void *ud) { + PyGILState_STATE pygil_state; + PyObject *pycm = NULL; + PyObject *_dict = (PyObject *)ud; + PyObject *_cb = PyDict_GetItemString(_dict, "callback"); + PyObject *_ud = PyDict_GetItemString(_dict, "user_data"); + + pygil_state = PyGILState_Ensure(); + pycm = pylinphone_ChatMessage_from_native_ptr(&pylinphone_ChatMessageType, msg); + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p, %p [%p], %d, %p)", __FUNCTION__, pycm, msg, state, ud); + if ((_cb != NULL) && PyCallable_Check(_cb)) { + PyObject *args = Py_BuildValue("OiO", pycm, state, _ud); + if (PyEval_CallObject(_cb, args) == NULL) { + PyErr_Print(); + } + Py_DECREF(args); + } + pylinphone_trace(-1, "[PYLINPHONE] <<< %s", __FUNCTION__); + PyGILState_Release(pygil_state); +} + +static PyObject * pylinphone_ChatRoom_instance_method_send_message2(PyObject *self, PyObject *args) { + PyObject *_chat_message; + PyObject *_dict; + PyObject *_cb; + PyObject *_ud; + LinphoneChatMessage * _chat_message_native_ptr; + LinphoneChatRoom *native_ptr = pylinphone_ChatRoom_get_native_ptr(self); + + if (native_ptr == NULL) { + PyErr_SetString(PyExc_TypeError, "Invalid linphone.ChatRoom instance"); + return NULL; + } + if (!PyArg_ParseTuple(args, "OOO", &_chat_message, &_cb, &_ud)) { + return NULL; + } + if (!PyObject_IsInstance(_chat_message, (PyObject *)&pylinphone_ChatMessageType)) { + PyErr_SetString(PyExc_TypeError, "The msg argument must be a linphone.ChatMessage"); + return NULL; + } + if ((_cb != Py_None) && !PyCallable_Check(_cb)) { + PyErr_SetString(PyExc_TypeError, "The status_cb argument must be a callable"); + return NULL; + } + if ((_chat_message_native_ptr = pylinphone_ChatMessage_get_native_ptr(_chat_message)) == NULL) { + return NULL; + } + _dict = PyDict_New(); + PyDict_SetItemString(_dict, "callback", _cb); + PyDict_SetItemString(_dict, "user_data", _ud); + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p], %p [%p], %p, %p)", __FUNCTION__, self, native_ptr, _chat_message, _chat_message_native_ptr, _cb, _ud); + linphone_chat_room_send_message2(native_ptr, _chat_message_native_ptr, pylinphone_ChatRoom_callback_chat_message_state_changed, _dict); + pylinphone_dispatch_messages(); + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> None", __FUNCTION__); + Py_RETURN_NONE; +} + + + +static void pylinphone_VideoSize_dealloc(PyObject *self) { + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p)", __FUNCTION__, self); + self->ob_type->tp_free(self); + pylinphone_trace(-1, "[PYLINPHONE] <<< %s", __FUNCTION__); +} + +static PyObject * pylinphone_VideoSize_new(PyTypeObject *type, PyObject *args, PyObject *kw) { + pylinphone_VideoSizeObject *self = (pylinphone_VideoSizeObject *)type->tp_alloc(type, 0); + pylinphone_trace(1, "[PYLINPHONE] >>> %s()", __FUNCTION__); + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, self); + return (PyObject *)self; +} + +static int pylinphone_VideoSize_init(PyObject *self, PyObject *args, PyObject *kw) { + pylinphone_VideoSizeObject *vso = (pylinphone_VideoSizeObject *)self; + int width; + int height; + if (!PyArg_ParseTuple(args, "ii", &width, &height)) { + return -1; + } + vso->vs.width = width; + vso->vs.height = height; + return 0; +} + +static PyMemberDef pylinphone_VideoSize_members[] = { + { "width", T_INT, offsetof(pylinphone_VideoSizeObject, vs) + offsetof(MSVideoSize, width), 0, "[int] The width of the video" }, + { "height", T_INT, offsetof(pylinphone_VideoSizeObject, vs) + offsetof(MSVideoSize, height), 0, "[int] The height of the video" }, + { NULL, 0, 0, 0, NULL } /* Sentinel */ +}; + +static PyTypeObject pylinphone_VideoSizeType = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "linphone.VideoSize", /* tp_name */ + sizeof(pylinphone_VideoSizeObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + pylinphone_VideoSize_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "Object representing the size of a video: its width and its height in pixels.", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + pylinphone_VideoSize_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + pylinphone_VideoSize_init, /* tp_init */ + 0, /* tp_alloc */ + pylinphone_VideoSize_new, /* tp_new */ + 0, /* tp_free */ +}; + +int PyLinphoneVideoSize_Check(PyObject *p) { + return PyObject_IsInstance(p, (PyObject *)&pylinphone_VideoSizeType); +} + +MSVideoSize PyLinphoneVideoSize_AsMSVideoSize(PyObject *obj) { + return ((pylinphone_VideoSizeObject *)obj)->vs; +} + +PyObject * PyLinphoneVideoSize_FromMSVideoSize(MSVideoSize vs) { + PyObject *linphone_module; + PyObject *pyret = NULL; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + linphone_module = PyImport_ImportModule("linphone.linphone"); + if (linphone_module != NULL) { + PyObject *cls = PyObject_GetAttrString(linphone_module, "VideoSize"); + if (cls != NULL) { + PyObject *args = Py_BuildValue("ii", vs.width, vs.height); + pyret = PyEval_CallObject(cls, args); + if (pyret == NULL) { + PyErr_Print(); + } + Py_DECREF(args); + Py_DECREF(cls); + } + Py_DECREF(linphone_module); + } + PyGILState_Release(gstate); + + if (pyret == NULL) { + Py_RETURN_NONE; + } + return pyret; +} + + +time_t PyDateTime_As_time_t(PyObject *obj) { + time_t ret = -1; + PyObject *utctimetuple = PyObject_GetAttrString(obj, "utctimetuple"); + if (utctimetuple != NULL) { + PyObject *calendar_module = PyImport_ImportModule("calendar"); + if (calendar_module != NULL) { + PyObject *timegm = PyObject_GetAttrString(calendar_module, "timegm"); + if (timegm != NULL) { + PyObject *args; + PyObject *tuple; + PyObject *pyres; + args = Py_BuildValue("()"); + tuple = PyEval_CallObject(utctimetuple, args); + Py_DECREF(args); + args = Py_BuildValue("(O)", tuple); + pyres = PyEval_CallObject(timegm, args); + Py_DECREF(args); + ret = (time_t)PyLong_AsLong(pyres); + Py_DECREF(timegm); + } + Py_DECREF(calendar_module); + } + Py_DECREF(utctimetuple); + } + return ret; +} + +PyObject * PyDateTime_From_time_t(time_t t) { + PyObject *pyret = NULL; + PyObject *datetime_module; + if (t == -1) { + Py_RETURN_NONE; + } + datetime_module = PyImport_ImportModule("datetime"); + if (datetime_module != NULL) { + PyObject *datetime_class = PyObject_GetAttrString(datetime_module, "datetime"); + if (datetime_class != NULL) { + PyObject *utcfromtimestamp = PyObject_GetAttrString(datetime_class, "utcfromtimestamp"); + if (utcfromtimestamp != NULL) { + PyObject *args = Py_BuildValue("(f)", (float)t); + pyret = PyEval_CallObject(utcfromtimestamp, args); + if (pyret == NULL) { + PyErr_Print(); + } + Py_DECREF(args); + Py_DECREF(utcfromtimestamp); + } + Py_DECREF(datetime_class); + } + Py_DECREF(datetime_module); + } + if (pyret == NULL) { + Py_RETURN_NONE; + } + return pyret; +} + + +static PyObject * pylinphone_PayloadTypeType_module_method_string(PyObject *self, PyObject *args) { + const char *value_str = "[invalid]"; + int value; + PyObject *pyret; + if (!PyArg_ParseTuple(args, "i", &value)) { + return NULL; + } + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%d)", __FUNCTION__, value); + switch (value) { + case PAYLOAD_AUDIO_CONTINUOUS: + value_str = "PAYLOAD_AUDIO_CONTINUOUS"; + break; + case PAYLOAD_AUDIO_PACKETIZED: + value_str = "PAYLOAD_AUDIO_PACKETIZED"; + break; + case PAYLOAD_VIDEO: + value_str = "PAYLOAD_VIDEO"; + break; + case PAYLOAD_TEXT: + value_str = "PAYLOAD_TEXT"; + break; + case PAYLOAD_OTHER: + value_str = "PAYLOAD_OTHER"; + break; + default: + break; + } + pyret = Py_BuildValue("z", value_str); + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret); + return pyret; +} + +static PyMethodDef pylinphone_PayloadTypeType_ModuleMethods[] = { + { "string", pylinphone_PayloadTypeType_module_method_string, METH_VARARGS, "Get a string representation of a linphone.PayloadTypeType value." }, + /* Sentinel */ + { NULL, NULL, 0, NULL } +}; diff --git a/tools/python/apixml2python/linphone.py b/tools/python/apixml2python/linphone.py index 1e3b44492..e90926f25 100644 --- a/tools/python/apixml2python/linphone.py +++ b/tools/python/apixml2python/linphone.py @@ -15,6 +15,7 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +from sets import Set import sys @@ -37,6 +38,147 @@ def compute_event_name(s): return event_name +class ArgumentType: + def __init__(self, basic_type, complete_type, contained_type, linphone_module): + self.basic_type = basic_type + self.complete_type = complete_type + self.contained_type = contained_type + self.linphone_module = linphone_module + self.type_str = None + self.check_func = None + self.convert_func = None + self.convert_from_func = None + self.fmt_str = 'O' + self.cfmt_str = '%p' + self.cnativefmt_str = '%p' + self.use_native_pointer = False + self.cast_convert_func_result = True + self.__compute() + if self.basic_type == 'MSList' and self.contained_type is not None: + self.linphone_module.mslist_types.add(self.contained_type) + + def __compute(self): + splitted_type = self.complete_type.split(' ') + if self.basic_type == 'char': + if '*' in splitted_type: + self.type_str = 'string' + self.check_func = 'PyString_Check' + self.convert_func = 'PyString_AsString' + self.fmt_str = 'z' + self.cfmt_str = '\\"%s\\"' + else: + self.type_str = 'int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsLong' + self.fmt_str = 'b' + self.cfmt_str = '%08x' + elif self.basic_type == 'int': + if 'unsigned' in splitted_type: + self.type_str = 'unsigned int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsUnsignedLongMask' + self.fmt_str = 'I' + self.cfmt_str = '%u' + else: + self.type_str = 'int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AS_LONG' + self.fmt_str = 'i' + self.cfmt_str = '%d' + elif self.basic_type in ['int8_t', 'int16_t' 'int32_t']: + self.type_str = 'int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AS_LONG' + if self.basic_type == 'int8_t': + self.fmt_str = 'c' + elif self.basic_type == 'int16_t': + self.fmt_str = 'h' + elif self.basic_type == 'int32_t': + self.fmt_str = 'l' + self.cfmt_str = '%d' + elif self.basic_type in ['uint8_t', 'uint16_t', 'uint32_t']: + self.type_str = 'unsigned int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsUnsignedLongMask' + if self.basic_type == 'uint8_t': + self.fmt_str = 'b' + elif self.basic_type == 'uint16_t': + self.fmt_str = 'H' + elif self.basic_type == 'uint32_t': + self.fmt_str = 'k' + self.cfmt_str = '%u' + elif self.basic_type == 'int64_t': + self.type_str = '64bits int' + self.check_func = 'PyLong_Check' + self.convert_func = 'PyLong_AsLongLong' + self.fmt_str = 'L' + self.cfmt_str = '%ld' + elif self.basic_type == 'uint64_t': + self.type_str = '64bits unsigned int' + self.check_func = 'PyLong_Check' + self.convert_func = 'PyLong_AsUnsignedLongLong' + self.fmt_str = 'K' + self.cfmt_str = '%lu' + elif self.basic_type == 'size_t': + self.type_str = 'size_t' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsSsize_t' + self.fmt_str = 'n' + self.cfmt_str = '%lu' + elif self.basic_type in ['float', 'double']: + self.type_str = 'float' + self.check_func = 'PyFloat_Check' + self.convert_func = 'PyFloat_AsDouble' + if self.basic_type == 'float': + self.fmt_str = 'f' + elif self.basic_type == 'double': + self.fmt_str = 'd' + self.cfmt_str = '%f' + elif self.basic_type == 'bool_t': + self.type_str = 'bool' + self.check_func = 'PyBool_Check' + self.convert_func = 'PyObject_IsTrue' + self.convert_from_func = 'PyBool_FromLong' + self.fmt_str = 'O' + self.cfmt_str = '%p' + self.cnativefmt_str = '%u' + elif self.basic_type == 'time_t': + self.type_str = 'DateTime' + self.check_func = 'PyDateTime_Check' + self.convert_func = 'PyDateTime_As_time_t' + self.convert_from_func = 'PyDateTime_From_time_t' + self.fmt_str = 'O' + self.cfmt_str = '%p' + self.cnativefmt_str = '%ld' + elif self.basic_type == 'MSList': + self.type_str = 'list of linphone.' + self.contained_type + self.check_func = 'PyList_Check' + self.convert_func = 'PyList_AsMSListOf' + self.contained_type + self.convert_from_func = 'PyList_FromMSListOf' + self.contained_type + self.fmt_str = 'O' + self.cfmt_str = '%p' + elif self.basic_type == 'MSVideoSize': + self.type_str = 'linphone.VideoSize' + self.check_func = 'PyLinphoneVideoSize_Check' + self.convert_func = 'PyLinphoneVideoSize_AsMSVideoSize' + self.convert_from_func = 'PyLinphoneVideoSize_FromMSVideoSize' + self.fmt_str = 'O' + self.cfmt_str = '%p' + self.cast_convert_func_result = False + else: + if strip_leading_linphone(self.basic_type) in self.linphone_module.enum_names: + self.type_str = 'int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsLong' + self.fmt_str = 'i' + self.cfmt_str = '%d' + elif '*' in splitted_type: + self.type_str = 'linphone.' + strip_leading_linphone(self.basic_type) + self.use_native_pointer = True + else: + self.type_str = 'linphone.' + strip_leading_linphone(self.basic_type) + + class MethodDefinition: def __init__(self, linphone_module, class_, method_node = None): self.body = '' @@ -45,6 +187,7 @@ def __init__(self, linphone_module, class_, method_node = None): self.build_value_format = '' self.return_type = 'void' self.return_complete_type = 'void' + self.return_contained_type = None self.method_node = method_node self.class_ = class_ self.linphone_module = linphone_module @@ -58,23 +201,30 @@ def format_local_variables_definition(self): if self.xml_method_return is not None: self.return_type = self.xml_method_return.get('type') self.return_complete_type = self.xml_method_return.get('completetype') + self.return_contained_type = self.xml_method_return.get('containedtype') if self.return_complete_type != 'void': body += "\t" + self.return_complete_type + " cresult;\n" - self.build_value_format = self.ctype_to_python_format(self.return_type, self.return_complete_type) + argument_type = ArgumentType(self.return_type, self.return_complete_type, self.return_contained_type, self.linphone_module) + self.build_value_format = argument_type.fmt_str if self.build_value_format == 'O': body += "\tPyObject * pyresult;\n" body += "\tPyObject * pyret;\n" + body += "\tconst char *pyret_fmt;\n" if self.self_arg is not None: body += "\t" + self.self_arg.get('completetype') + "native_ptr;\n" for xml_method_arg in self.xml_method_args: arg_name = "_" + xml_method_arg.get('name') arg_type = xml_method_arg.get('type') arg_complete_type = xml_method_arg.get('completetype') - fmt = self.ctype_to_python_format(arg_type, arg_complete_type) - self.parse_tuple_format += fmt - if fmt == 'O': + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + self.parse_tuple_format += argument_type.fmt_str + if argument_type.fmt_str == 'O' and argument_type.use_native_pointer: body += "\tPyObject * " + arg_name + ";\n" - body += "\t" + arg_complete_type + " " + arg_name + "_native_ptr;\n" + body += "\t" + arg_complete_type + " " + arg_name + "_native_ptr = NULL;\n" + elif argument_type.fmt_str == 'O' and argument_type.convert_func is not None: + body += "\tPyObject * " + arg_name + ";\n" + body += "\t" + arg_complete_type + " " + arg_name + "_native_obj;\n" elif strip_leading_linphone(arg_complete_type) in self.linphone_module.enum_names: body += "\tint " + arg_name + ";\n" else: @@ -89,17 +239,32 @@ def format_arguments_parsing(self): parse_tuple_code = '' if len(self.arg_names) > 0: parse_tuple_code = \ -""" if (!PyArg_ParseTuple(args, "{fmt}", {args})) {{ +"""if (!PyArg_ParseTuple(args, "{fmt}", {args})) {{ return NULL; }} """.format(fmt=self.parse_tuple_format, args=', '.join(map(lambda a: '&' + a, self.arg_names))) + args_conversion_code = '' + for xml_method_arg in self.xml_method_args: + arg_name = "_" + xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O' and argument_type.convert_func is not None: + args_conversion_code += \ +""" {arg_name}_native_obj = {convert_func}({arg_name}); +""".format(arg_name=arg_name, convert_func=argument_type.convert_func) return \ """ {class_native_ptr_check_code} {parse_tuple_code} + {args_type_check_code} {args_native_ptr_check_code} + {args_conversion_code} """.format(class_native_ptr_check_code=class_native_ptr_check_code, parse_tuple_code=parse_tuple_code, - args_native_ptr_check_code=self.format_args_native_pointer_check()) + args_type_check_code=self.format_args_type_check(), + args_native_ptr_check_code=self.format_args_native_pointer_check(), + args_conversion_code=args_conversion_code) def format_enter_trace(self): fmt = '' @@ -111,12 +276,19 @@ def format_enter_trace(self): arg_name = "_" + xml_method_arg.get('name') arg_type = xml_method_arg.get('type') arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') if fmt != '': fmt += ', ' - f, a = self.ctype_to_str_format(arg_name, arg_type, arg_complete_type) - fmt += f - args += a - args=', '.join(args) + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + fmt += argument_type.cfmt_str + args.append(arg_name) + if argument_type.fmt_str == 'O': + fmt += ' [' + argument_type.cnativefmt_str + ']' + if argument_type.use_native_pointer: + args.append(arg_name + '_native_ptr') + else: + args.append(arg_name + '_native_obj') + args = ', '.join(args) if args != '': args = ', ' + args return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s({fmt})\", __FUNCTION__{args});\n".format(fmt=fmt, args=args) @@ -128,9 +300,12 @@ def format_c_function_call(self): arg_name = "_" + xml_method_arg.get('name') arg_type = xml_method_arg.get('type') arg_complete_type = xml_method_arg.get('completetype') - type_str, checkfunc, convertfunc = self.ctype_to_python_type(arg_type, arg_complete_type) - if convertfunc is None: + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O' and argument_type.use_native_pointer: arg_names.append(arg_name + "_native_ptr") + elif argument_type.fmt_str == 'O' and argument_type.convert_func is not None: + arg_names.append(arg_name + "_native_obj") else: arg_names.append(arg_name) if self.return_type != 'void': @@ -141,46 +316,36 @@ def format_c_function_call(self): if len(arg_names) > 0: c_function_call_code += ', ' c_function_call_code += ', '.join(arg_names) + ");" - return_from_user_data_code = '' - new_from_native_pointer_code = '' - ref_native_pointer_code = '' + from_native_pointer_code = '' + convert_from_code = '' build_value_code = '' result_variable = '' if self.return_complete_type != 'void': if self.build_value_format == 'O': stripped_return_type = strip_leading_linphone(self.return_type) return_type_class = self.find_class_definition(self.return_type) - if return_type_class['class_has_user_data']: - get_user_data_function = return_type_class['class_c_function_prefix'] + "get_user_data" - return_from_user_data_code = \ -""" if ((cresult != NULL) && ({func}(cresult) != NULL)) {{ - return (PyObject *){func}(cresult); - }} -""".format(func=get_user_data_function) - new_from_native_pointer_code = "\tpyresult = pylinphone_{return_type}_new_from_native_ptr(&pylinphone_{return_type}Type, cresult);\n".format(return_type=stripped_return_type) - if self.self_arg is not None and return_type_class['class_refcountable']: - ref_function = return_type_class['class_c_function_prefix'] + "ref" - ref_native_pointer_code = \ -""" if (cresult != NULL) {{ - {func}(({cast_type})cresult); - }} -""".format(func=ref_function, cast_type=self.remove_const_from_complete_type(self.return_complete_type)) + if return_type_class is not None: + from_native_pointer_code = "pyresult = pylinphone_{return_type}_from_native_ptr(&pylinphone_{return_type}Type, cresult);\n".format(return_type=stripped_return_type) + else: + return_argument_type = ArgumentType(self.return_type, self.return_complete_type, self.return_contained_type, self.linphone_module) + if return_argument_type.convert_from_func is not None: + convert_from_code = \ +"""pyresult = {convert_func}(cresult); +""".format(convert_func=return_argument_type.convert_from_func) result_variable = 'pyresult' else: result_variable = 'cresult' if result_variable != '': - build_value_code = "pyret = Py_BuildValue(\"{fmt}\", {result_variable});\n".format(fmt=self.build_value_format, result_variable=result_variable) + build_value_code = "pyret = Py_BuildValue(\"{fmt}\", {result_variable});".format(fmt=self.build_value_format, result_variable=result_variable) body = \ """ {c_function_call_code} pylinphone_dispatch_messages(); - {return_from_user_data_code} - {new_from_native_pointer_code} - {ref_native_pointer_code} + {from_native_pointer_code} + {convert_from_code} {build_value_code} """.format(c_function_call_code=c_function_call_code, - return_from_user_data_code=return_from_user_data_code, - new_from_native_pointer_code=new_from_native_pointer_code, - ref_native_pointer_code=ref_native_pointer_code, + from_native_pointer_code=from_native_pointer_code, + convert_from_code=convert_from_code, build_value_code=build_value_code) return body @@ -192,12 +357,7 @@ def format_return_trace(self): def format_return_result(self): if self.return_complete_type != 'void': - if self.build_value_format == 'O': - return \ -""" Py_DECREF(pyresult); - return pyret;""" - else: - return "\treturn pyret;" + return "\treturn pyret;" return "\tPy_RETURN_NONE;" def format_return_none_trace(self): @@ -208,26 +368,58 @@ def format_class_native_pointer_check(self, return_int): if return_int: return_value = "-1" return \ -""" native_ptr = pylinphone_{class_name}_get_native_ptr(self); +"""native_ptr = pylinphone_{class_name}_get_native_ptr(self); if (native_ptr == NULL) {{ PyErr_SetString(PyExc_TypeError, "Invalid linphone.{class_name} instance"); return {return_value}; }} """.format(class_name=self.class_['class_name'], return_value=return_value) + def format_args_type_check(self): + body = '' + for xml_method_arg in self.xml_method_args: + arg_name = "_" + xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O': + if argument_type.use_native_pointer: + body += \ +""" if (({arg_name} != Py_None) && !PyObject_IsInstance({arg_name}, (PyObject *)&pylinphone_{arg_type}Type)) {{ + PyErr_SetString(PyExc_TypeError, "The '{arg_name}' argument must be a {type_str} instance."); + return NULL; + }} +""".format(arg_name=arg_name, arg_type=strip_leading_linphone(arg_type), type_str=argument_type.type_str) + else: + body += \ +""" if (!{check_func}({arg_name})) {{ + PyErr_SetString(PyExc_TypeError, "The '{arg_name}' argument must be a {type_str} instance."); + return NULL; + }} +""".format(arg_name=arg_name, check_func=argument_type.check_func, type_str=argument_type.type_str) + if body != '': + body = body[1:] # Remove leading '\t' + return body + def format_args_native_pointer_check(self): body = '' for xml_method_arg in self.xml_method_args: arg_name = "_" + xml_method_arg.get('name') arg_type = xml_method_arg.get('type') arg_complete_type = xml_method_arg.get('completetype') - fmt = self.ctype_to_python_format(arg_type, arg_complete_type) - if fmt == 'O': + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O' and argument_type.use_native_pointer: body += \ -""" if (({arg_name}_native_ptr = pylinphone_{arg_type}_get_native_ptr({arg_name})) == NULL) {{ - return NULL; +""" if (({arg_name} != NULL) && ({arg_name} != Py_None)) {{ + if (({arg_name}_native_ptr = pylinphone_{arg_type}_get_native_ptr({arg_name})) == NULL) {{ + return NULL; + }} }} """.format(arg_name=arg_name, arg_type=strip_leading_linphone(arg_type)) + if body != '': + body = body[1:] # Remove leading '\t' return body def parse_method_node(self): @@ -245,120 +437,6 @@ def remove_const_from_complete_type(self, complete_type): splitted_type.remove('const') return ' '.join(splitted_type) - def ctype_to_str_format(self, name, basic_type, complete_type, with_native_ptr=True): - splitted_type = complete_type.split(' ') - if basic_type == 'char': - if '*' in splitted_type: - return ('\\"%s\\"', [name]) - elif 'unsigned' in splitted_type: - return ('%08x', [name]) - elif basic_type == 'int': - # TODO: - return ('%d', [name]) - elif basic_type == 'int8_t': - return ('%d', [name]) - elif basic_type == 'uint8_t': - return ('%u', [name]) - elif basic_type == 'int16_t': - return ('%d', [name]) - elif basic_type == 'uint16_t': - return ('%u', [name]) - elif basic_type == 'int32_t': - return ('%d', [name]) - elif basic_type == 'uint32_t': - return ('%u', [name]) - elif basic_type == 'int64_t': - return ('%ld', [name]) - elif basic_type == 'uint64_t': - return ('%lu', [name]) - elif basic_type == 'size_t': - return ('%lu', [name]) - elif basic_type == 'float': - return ('%f', [name]) - elif basic_type == 'double': - return ('%f', [name]) - elif basic_type == 'bool_t': - return ('%d', [name]) - else: - if strip_leading_linphone(basic_type) in self.linphone_module.enum_names: - return ('%d', [name]) - elif with_native_ptr: - return ('%p [%p]', [name, name + "_native_ptr"]) - else: - return ('%p', [name]) - - def ctype_to_python_format(self, basic_type, complete_type): - splitted_type = complete_type.split(' ') - if basic_type == 'char': - if '*' in splitted_type: - return 'z' - elif 'unsigned' in splitted_type: - return 'b' - elif basic_type == 'int': - # TODO: - return 'i' - elif basic_type == 'int8_t': - return 'c' - elif basic_type == 'uint8_t': - return 'b' - elif basic_type == 'int16_t': - return 'h' - elif basic_type == 'uint16_t': - return 'H' - elif basic_type == 'int32_t': - return 'l' - elif basic_type == 'uint32_t': - return 'k' - elif basic_type == 'int64_t': - return 'L' - elif basic_type == 'uint64_t': - return 'K' - elif basic_type == 'size_t': - return 'n' - elif basic_type == 'float': - return 'f' - elif basic_type == 'double': - return 'd' - elif basic_type == 'bool_t': - return 'i' - else: - if strip_leading_linphone(basic_type) in self.linphone_module.enum_names: - return 'i' - else: - return 'O' - - def ctype_to_python_type(self, basic_type, complete_type): - splitted_type = complete_type.split(' ') - if basic_type == 'char': - if '*' in splitted_type: - return ('string', 'PyString_Check', 'PyString_AsString') - else: - return ('int', 'PyInt_Check', 'PyInt_AsLong') - elif basic_type == 'int': - if 'unsigned' in splitted_type: - return ('unsigned int', 'PyLong_Check', 'PyLong_AsUnsignedLong') - else: - return ('int', 'PyLong_Check', 'PyLong_AsLong') - elif basic_type in ['int8_t', 'int16_t' 'int32_t']: - return ('int', 'PyLong_Check', 'PyLong_AsLong') - elif basic_type in ['uint8_t', 'uin16_t', 'uint32_t']: - return ('unsigned int', 'PyLong_Check', 'PyLong_AsUnsignedLong') - elif basic_type == 'int64_t': - return ('64bits int', 'PyLong_Check', 'PyLong_AsLongLong') - elif basic_type == 'uint64_t': - return ('64bits unsigned int', 'PyLong_Check', 'PyLong_AsUnsignedLongLong') - elif basic_type == 'size_t': - return ('size_t', 'PyLong_Check', 'PyLong_AsSsize_t') - elif basic_type in ['float', 'double']: - return ('float', 'PyFloat_Check', 'PyFloat_AsDouble') - elif basic_type == 'bool_t': - return ('bool', 'PyBool_Check', 'PyInt_AsLong') - else: - if strip_leading_linphone(basic_type) in self.linphone_module.enum_names: - return ('int', 'PyInt_Check', 'PyInt_AsLong') - else: - return (None, None, None) - def find_class_definition(self, basic_type): basic_type = strip_leading_linphone(basic_type) for c in self.linphone_module.classes: @@ -390,7 +468,7 @@ def format_enter_trace(self): return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s()\", __FUNCTION__);\n" def format_c_function_call(self): - return "\tself->native_ptr = NULL;\n" + return '' def format_return_trace(self): return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> %p\", __FUNCTION__, self);\n" @@ -398,12 +476,41 @@ def format_return_trace(self): def format_return_result(self): return "\treturn (PyObject *)self;" -class NewFromNativePointerMethodDefinition(MethodDefinition): +class InitMethodDefinition(MethodDefinition): + def __init__(self, linphone_module, class_, method_node = None): + MethodDefinition.__init__(self, linphone_module, class_, method_node) + + def format_local_variables_definition(self): + return "\tpylinphone_{class_name}Object *self_obj = (pylinphone_{class_name}Object *)self;\n".format(class_name=self.class_['class_name']) + + def format_arguments_parsing(self): + return '' + + def format_enter_trace(self): + return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s()\", __FUNCTION__);\n" + + def format_c_function_call(self): + specific_member_initialization_code = '' + for member in self.class_['class_object_members']: + specific_member_initialization_code += "\tself_obj->{member} = NULL;\n".format(member=member) + return \ +""" self_obj->native_ptr = NULL; + self_obj->user_data = NULL; +{specific_member_initialization_code} +""".format(specific_member_initialization_code=specific_member_initialization_code) + + def format_return_trace(self): + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> %p\", __FUNCTION__, self);\n" + + def format_return_result(self): + return "\treturn 0;" + +class FromNativePointerMethodDefinition(MethodDefinition): def __init__(self, linphone_module, class_): MethodDefinition.__init__(self, linphone_module, class_, None) def format_local_variables_definition(self): - return "\tpylinphone_{class_name}Object *self;\n".format(class_name=self.class_['class_name']) + return "\tpylinphone_{class_name}Object *self = NULL;\n".format(class_name=self.class_['class_name']) def format_arguments_parsing(self): return '' @@ -412,23 +519,34 @@ def format_enter_trace(self): return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s(%p)\", __FUNCTION__, native_ptr);\n" def format_c_function_call(self): + get_user_data_func_call = '' set_user_data_func_call = '' if self.class_['class_has_user_data']: - set_user_data_func_call = "\t{function_prefix}set_user_data(self->native_ptr, self);\n".format(function_prefix=self.class_['class_c_function_prefix']) + get_user_data_func_call = "self = (pylinphone_{class_name}Object *){function_prefix}get_user_data(native_ptr);".format(class_name=self.class_['class_name'], function_prefix=self.class_['class_c_function_prefix']) + set_user_data_func_call = "{function_prefix}set_user_data(self->native_ptr, self);".format(function_prefix=self.class_['class_c_function_prefix']) + ref_native_pointer_code = '' + if self.class_['class_refcountable']: + ref_native_pointer_code = "{func}(self->native_ptr);".format(func=self.class_['class_c_function_prefix'] + "ref") return \ """ if (native_ptr == NULL) {{ {none_trace} Py_RETURN_NONE; }} - self = (pylinphone_{class_name}Object *)PyObject_New(pylinphone_{class_name}Object, type); + {get_user_data_func_call} if (self == NULL) {{ - {none_trace} - Py_RETURN_NONE; + self = (pylinphone_{class_name}Object *)PyObject_CallObject((PyObject *)&pylinphone_{class_name}Type, NULL); + if (self == NULL) {{ + {none_trace} + Py_RETURN_NONE; + }} + self->native_ptr = ({class_cname} *)native_ptr; + {set_user_data_func_call} + {ref_native_pointer_code} }} - self->native_ptr = ({class_cname} *)native_ptr; - {set_user_data_func_call} """.format(class_name=self.class_['class_name'], class_cname=self.class_['class_cname'], - none_trace=self.format_return_none_trace(), set_user_data_func_call=set_user_data_func_call) + none_trace=self.format_return_none_trace(), + get_user_data_func_call=get_user_data_func_call, set_user_data_func_call=set_user_data_func_call, + ref_native_pointer_code=ref_native_pointer_code) def format_return_trace(self): return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> %p\", __FUNCTION__, self);\n" @@ -447,14 +565,22 @@ def format_local_variables_definition(self): """.format(arg_type=self.class_['class_cname'], func=func) def format_arguments_parsing(self): - return '' + # Check that the dealloc is not called a second time because of reentrancy + return "\tif (Py_REFCNT(self) < 0) return;\n" def format_enter_trace(self): return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s(%p [%p])\", __FUNCTION__, self, native_ptr);\n" def format_c_function_call(self): - # Increment the refcount on self to prevent reentrancy in the dealloc method. - native_ptr_dealloc_code = "\tPy_INCREF(self);\n" + reset_user_data_code = '' + if self.class_['class_name'] != 'Core' and self.class_['class_has_user_data']: + reset_user_data_code += \ +"""if (native_ptr != NULL) {{ + {function_prefix}set_user_data(native_ptr, NULL); + }} +""".format(function_prefix=self.class_['class_c_function_prefix']) + native_ptr_dealloc_code = '' + specific_member_decref_code = '' if self.class_['class_refcountable']: native_ptr_dealloc_code += \ """ if (native_ptr != NULL) {{ @@ -467,11 +593,16 @@ def format_c_function_call(self): {function_prefix}destroy(native_ptr); }} """.format(function_prefix=self.class_['class_c_function_prefix']) + for member in self.class_['class_object_members']: + specific_member_decref_code += "\tPy_XDECREF(((pylinphone_{class_name}Object *)self)->{member});\n".format(class_name=self.class_['class_name'], member=member) return \ -"""{native_ptr_dealloc_code} +""" {reset_user_data_code} + {native_ptr_dealloc_code} pylinphone_dispatch_messages(); + Py_XDECREF(((pylinphone_{class_name}Object *)self)->user_data); +{specific_member_decref_code} self->ob_type->tp_free(self); -""".format(native_ptr_dealloc_code=native_ptr_dealloc_code) +""".format(class_name=self.class_['class_name'], reset_user_data_code=reset_user_data_code, native_ptr_dealloc_code=native_ptr_dealloc_code, specific_member_decref_code=specific_member_decref_code) def format_return_trace(self): return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s\", __FUNCTION__);" @@ -488,41 +619,50 @@ def __init__(self, linphone_module, class_, method_node = None): MethodDefinition.__init__(self, linphone_module, class_, method_node) def format_arguments_parsing(self): - if self.checkfunc is None: + if self.first_argument_type.check_func is None: attribute_type_check_code = \ -"""if (!PyObject_IsInstance(value, (PyObject *)&pylinphone_{class_name}Type)) {{ - PyErr_SetString(PyExc_TypeError, "The {attribute_name} attribute value must be a linphone.{class_name} instance"); +"""if ((value != Py_None) && !PyObject_IsInstance(value, (PyObject *)&pylinphone_{class_name}Type)) {{ + PyErr_SetString(PyExc_TypeError, "The '{attribute_name}' attribute value must be a linphone.{class_name} instance."); return -1; }} """.format(class_name=self.first_arg_class, attribute_name=self.attribute_name) else: checknotnone = '' - if self.type_str == 'string': + if self.first_argument_type.type_str == 'string': checknotnone = "(value != Py_None) && " attribute_type_check_code = \ """if ({checknotnone}!{checkfunc}(value)) {{ - PyErr_SetString(PyExc_TypeError, "The {attribute_name} attribute value must be a {type_str}"); + PyErr_SetString(PyExc_TypeError, "The '{attribute_name}' attribute value must be a {type_str}."); return -1; }} -""".format(checknotnone=checknotnone, checkfunc=self.checkfunc, attribute_name=self.attribute_name, type_str=self.type_str) - if self.convertfunc is None: - attribute_conversion_code = "{arg_name} = value;\n".format(arg_name="_" + self.first_arg_name) - else: - attribute_conversion_code = "{arg_name} = ({arg_type}){convertfunc}(value);\n".format( - arg_name="_" + self.first_arg_name, arg_type=self.first_arg_complete_type, convertfunc=self.convertfunc) +""".format(checknotnone=checknotnone, checkfunc=self.first_argument_type.check_func, attribute_name=self.attribute_name, type_str=self.first_argument_type.type_str) + attribute_conversion_code = '' + if (self.first_argument_type.convert_func is None) or \ + (self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None): + attribute_conversion_code += "{arg_name} = value;\n".format(arg_name="_" + self.first_arg_name) + if self.first_argument_type.convert_func is not None: + cast_code = '' + suffix = '' + if self.first_argument_type.cast_convert_func_result: + cast_code = "({arg_type})".format(arg_type=self.first_arg_complete_type) + if self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None: + suffix = '_native_obj' + attribute_conversion_code += "\t{arg_name}{suffix} = {cast_code}{convertfunc}(value);\n".format( + arg_name="_" + self.first_arg_name, suffix=suffix, cast_code=cast_code, convertfunc=self.first_argument_type.convert_func) attribute_native_ptr_check_code = '' - if self.python_fmt == 'O': + if self.first_argument_type.use_native_pointer: attribute_native_ptr_check_code = \ -"""{arg_name}_native_ptr = pylinphone_{arg_class}_get_native_ptr({arg_name}); - if ({arg_name}_native_ptr == NULL) {{ - PyErr_SetString(PyExc_TypeError, "Invalid linphone.{arg_class} instance"); - return -1; +"""if ({arg_name} != Py_None) {{ + if (({arg_name}_native_ptr = pylinphone_{arg_class}_get_native_ptr({arg_name})) == NULL) {{ + PyErr_SetString(PyExc_TypeError, "Invalid linphone.{arg_class} instance."); + return -1; + }} }} """.format(arg_name="_" + self.first_arg_name, arg_class=self.first_arg_class) return \ """ {native_ptr_check_code} if (value == NULL) {{ - PyErr_SetString(PyExc_TypeError, "Cannot delete the {attribute_name} attribute"); + PyErr_SetString(PyExc_TypeError, "Cannot delete the '{attribute_name}' attribute."); return -1; }} {attribute_type_check_code} @@ -535,13 +675,15 @@ def format_arguments_parsing(self): attribute_native_ptr_check_code=attribute_native_ptr_check_code) def format_c_function_call(self): - use_native_ptr = '' - if self.python_fmt == 'O': - use_native_ptr = '_native_ptr' + suffix = '' + if self.first_argument_type.fmt_str == 'O' and self.first_argument_type.use_native_pointer: + suffix = '_native_ptr' + elif self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None: + suffix = '_native_obj' return \ -""" {method_name}(native_ptr, {arg_name}{use_native_ptr}); +""" {method_name}(native_ptr, {arg_name}{suffix}); pylinphone_dispatch_messages(); -""".format(arg_name="_" + self.first_arg_name, method_name=self.method_node.get('name'), use_native_ptr=use_native_ptr) +""".format(arg_name="_" + self.first_arg_name, method_name=self.method_node.get('name'), suffix=suffix) def format_return_trace(self): return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> 0\", __FUNCTION__);\n" @@ -557,10 +699,10 @@ def parse_method_node(self): self.attribute_name = self.method_node.get('property_name') self.first_arg_type = self.xml_method_args[0].get('type') self.first_arg_complete_type = self.xml_method_args[0].get('completetype') + self.first_arg_contained_type = self.xml_method_args[0].get('containedtype') self.first_arg_name = self.xml_method_args[0].get('name') - self.type_str, self.checkfunc, self.convertfunc = self.ctype_to_python_type(self.first_arg_type, self.first_arg_complete_type) + self.first_argument_type = ArgumentType(self.first_arg_type, self.first_arg_complete_type, self.first_arg_contained_type, self.linphone_module) self.first_arg_class = strip_leading_linphone(self.first_arg_type) - self.python_fmt = self.ctype_to_python_format(self.first_arg_type, self.first_arg_complete_type) class EventCallbackMethodDefinition(MethodDefinition): def __init__(self, linphone_module, class_, method_node = None): @@ -569,39 +711,26 @@ def __init__(self, linphone_module, class_, method_node = None): def format_local_variables_definition(self): common = \ """ pylinphone_CoreObject *pylc = (pylinphone_CoreObject *)linphone_core_get_user_data(lc); - PyObject *func = PyDict_GetItemString(pylc->vtable_dict, "{name}"); - PyGILState_STATE pygil_state;""".format(name=self.class_['event_name']) + PyObject *func; + PyObject *args; + PyGILState_STATE pygil_state;""" specific = '' for xml_method_arg in self.xml_method_args: - arg_name = 'py' + xml_method_arg.get('name') + arg_name = xml_method_arg.get('name') arg_type = xml_method_arg.get('type') arg_complete_type = xml_method_arg.get('completetype') - fmt = self.ctype_to_python_format(arg_type, arg_complete_type) - if fmt == 'O': - specific += "\tPyObject * " + arg_name + " = NULL;\n" + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O': + specific += "\tPyObject * py" + arg_name + " = NULL;\n" return "{common}\n{specific}".format(common=common, specific=specific) def format_arguments_parsing(self): - body = "\tpygil_state = PyGILState_Ensure();\n" - for xml_method_arg in self.xml_method_args: - arg_name = xml_method_arg.get('name') - arg_type = xml_method_arg.get('type') - arg_complete_type = xml_method_arg.get('completetype') - fmt = self.ctype_to_python_format(arg_type, arg_complete_type) - if fmt == 'O': - type_class = self.find_class_definition(arg_type) - get_user_data_code = '' - new_from_native_pointer_code = "py{name} = pylinphone_{arg_type}_new_from_native_ptr(&pylinphone_{arg_type}Type, {name});".format(name=arg_name, arg_type=strip_leading_linphone(arg_type)) - if type_class is not None and type_class['class_has_user_data']: - get_user_data_function = type_class['class_c_function_prefix'] + "get_user_data" - get_user_data_code = "py{name} = {get_user_data_function}({name});".format(name=arg_name, get_user_data_function=get_user_data_function) - body += \ -""" {get_user_data_code} - if (py{name} == NULL) {{ - {new_from_native_pointer_code} - }} -""".format(name=arg_name, get_user_data_code=get_user_data_code, new_from_native_pointer_code=new_from_native_pointer_code) - return body + return \ +""" if (Py_REFCNT(pylc) <= 0) return; + func = PyDict_GetItemString(pylc->vtable_dict, "{name}"); + pygil_state = PyGILState_Ensure(); +""".format(name=self.class_['event_name']) def format_enter_trace(self): fmt = '%p' @@ -610,37 +739,49 @@ def format_enter_trace(self): arg_name = xml_method_arg.get('name') arg_type = xml_method_arg.get('type') arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') if fmt != '': fmt += ', ' - f, a = self.ctype_to_str_format(arg_name, arg_type, arg_complete_type, with_native_ptr=False) - fmt += f - args += a + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + fmt += argument_type.cfmt_str + args.append(arg_name) args=', '.join(args) if args != '': args = ', ' + args return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s({fmt})\", __FUNCTION__{args});\n".format(fmt=fmt, args=args) def format_c_function_call(self): + create_python_objects_code = '' fmt = 'O' args = ['pylc'] for xml_method_arg in self.xml_method_args: arg_name = xml_method_arg.get('name') arg_type = xml_method_arg.get('type') arg_complete_type = xml_method_arg.get('completetype') - f = self.ctype_to_python_format(arg_type, arg_complete_type) - fmt += f - if f == 'O': + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + fmt += argument_type.fmt_str + if argument_type.fmt_str == 'O': args.append('py' + arg_name) else: args.append(arg_name) + if argument_type.fmt_str == 'O': + if argument_type.type_str == "bool": + create_python_objects_code += "\t\tpy{name} = {convert_from_func}({name});\n".format(name=arg_name, convert_from_func=argument_type.convert_from_func) + else: + type_class = self.find_class_definition(arg_type) + create_python_objects_code += "\t\tpy{name} = pylinphone_{arg_type}_from_native_ptr(&pylinphone_{arg_type}Type, {name});\n".format(name=arg_name, arg_type=strip_leading_linphone(arg_type)) args=', '.join(args) return \ """ if ((func != NULL) && PyCallable_Check(func)) {{ - if (PyEval_CallObject(func, Py_BuildValue("{fmt}", {args})) == NULL) {{ +{create_python_objects_code} + args = Py_BuildValue("{fmt}", {args}); + if (PyEval_CallObject(func, args) == NULL) {{ PyErr_Print(); }} + Py_DECREF(args); }} -""".format(fmt=fmt, args=args) +""".format(fmt=fmt, args=args, create_python_objects_code=create_python_objects_code) def format_return_trace(self): return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s\", __FUNCTION__);\n" @@ -668,6 +809,7 @@ class LinphoneModule(object): def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_functions, hand_written_functions): self.internal_instance_method_names = ['destroy', 'ref', 'unref'] self.internal_property_names = ['user_data'] + self.mslist_types = Set([]) self.enums = [] self.enum_names = [] xml_enums = tree.findall("./enums/enum") @@ -676,7 +818,8 @@ def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_fu continue e = {} e['enum_name'] = strip_leading_linphone(xml_enum.get('name')) - e['enum_doc'] = self.__format_doc(xml_enum.find('briefdescription'), xml_enum.find('detaileddescription')) + e['enum_doc'] = self.__format_doc_content(xml_enum.find('briefdescription'), xml_enum.find('detaileddescription')) + e['enum_doc'] += "\n\nValues:\n" e['enum_values'] = [] xml_enum_values = xml_enum.findall("./values/value") for xml_enum_value in xml_enum_values: @@ -685,7 +828,10 @@ def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_fu v = {} v['enum_value_cname'] = xml_enum_value.get('name') v['enum_value_name'] = strip_leading_linphone(v['enum_value_cname']) + v['enum_value_doc'] = self.__format_doc(xml_enum_value.find('briefdescription'), xml_enum_value.find('detaileddescription')) + e['enum_doc'] += '\t' + v['enum_value_name'] + ': ' + v['enum_value_doc'] + '\n' e['enum_values'].append(v) + e['enum_doc'] = self.__replace_doc_special_chars(e['enum_doc']) self.enums.append(e) self.enum_names.append(e['enum_name']) self.events = [] @@ -708,9 +854,12 @@ def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_fu c['class_type_methods'] = [] c['class_type_hand_written_methods'] = [] c['class_instance_hand_written_methods'] = [] - c['class_object_members'] = '' + c['class_hand_written_properties'] = [] + c['class_object_members'] = [] + c['class_object_members_code'] = '' if c['class_name'] == 'Core': - c['class_object_members'] = "\tPyObject *vtable_dict;" + c['class_object_members'].append("vtable_dict") + c['class_object_members_code'] = "\tPyObject *vtable_dict;" xml_events = xml_class.findall("./events/event") for xml_event in xml_events: if xml_event.get('deprecated') == 'true': @@ -745,7 +894,7 @@ def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_fu method_name = xml_instance_method.get('name') if method_name in blacklisted_functions: continue - if method_name in self.internal_instance_method_names: + if method_name.replace(c['class_c_function_prefix'], '') in self.internal_instance_method_names: continue m = {} m['method_name'] = method_name.replace(c['class_c_function_prefix'], '') @@ -766,31 +915,45 @@ def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_fu p['property_name'] = property_name xml_property_getter = xml_property.find("./getter") xml_property_setter = xml_property.find("./setter") - if xml_property_getter is not None and ( - xml_property_getter.get('name') in blacklisted_functions or xml_property_getter.get('deprecated') == 'true'): - continue - if xml_property_setter is not None and ( - xml_property_setter.get('name') in blacklisted_functions or xml_property_setter.get('deprecated') == 'true'): - continue + handwritten_property = False if xml_property_getter is not None: - xml_property_getter.set('property_name', property_name) - p['getter_name'] = xml_property_getter.get('name').replace(c['class_c_function_prefix'], '') - p['getter_xml_node'] = xml_property_getter - p['getter_reference'] = "(getter)pylinphone_" + c['class_name'] + "_" + p['getter_name'] - p['getter_definition_begin'] = "static PyObject * pylinphone_" + c['class_name'] + "_" + p['getter_name'] + "(PyObject *self, void *closure) {" - p['getter_definition_end'] = "}" - else: - p['getter_reference'] = "NULL" + if xml_property_getter.get('name') in blacklisted_functions or xml_property_getter.get('deprecated') == 'true': + continue + elif xml_property_getter.get('name') in hand_written_functions: + handwritten_property = True if xml_property_setter is not None: - xml_property_setter.set('property_name', property_name) - p['setter_name'] = xml_property_setter.get('name').replace(c['class_c_function_prefix'], '') - p['setter_xml_node'] = xml_property_setter - p['setter_reference'] = "(setter)pylinphone_" + c['class_name'] + "_" + p['setter_name'] - p['setter_definition_begin'] = "static int pylinphone_" + c['class_name'] + "_" + p['setter_name'] + "(PyObject *self, PyObject *value, void *closure) {" - p['setter_definition_end'] = "}" + if xml_property_setter.get('name') in blacklisted_functions or xml_property_setter.get('deprecated') == 'true': + continue + elif xml_property_setter.get('name') in hand_written_functions: + handwritten_property = True + if handwritten_property: + p['getter_reference'] = 'NULL' + p['setter_reference'] = 'NULL' + if xml_property_getter is not None: + p['getter_reference'] = '(getter)pylinphone_' + c['class_name'] + '_get_' + p['property_name'] + if xml_property_setter is not None: + p['setter_reference'] = '(setter)pylinphone_' + c['class_name'] + '_set_' + p['property_name'] + c['class_hand_written_properties'].append(p) else: - p['setter_reference'] = "NULL" - c['class_properties'].append(p) + if xml_property_getter is not None: + xml_property_getter.set('property_name', property_name) + p['getter_name'] = xml_property_getter.get('name').replace(c['class_c_function_prefix'], '') + p['getter_xml_node'] = xml_property_getter + p['getter_reference'] = "(getter)pylinphone_" + c['class_name'] + "_" + p['getter_name'] + p['getter_definition_begin'] = "static PyObject * pylinphone_" + c['class_name'] + "_" + p['getter_name'] + "(PyObject *self, void *closure) {" + p['getter_definition_end'] = "}" + else: + p['getter_reference'] = "NULL" + if xml_property_setter is not None: + xml_property_setter.set('property_name', property_name) + p['setter_name'] = xml_property_setter.get('name').replace(c['class_c_function_prefix'], '') + p['setter_xml_node'] = xml_property_setter + p['setter_reference'] = "(setter)pylinphone_" + c['class_name'] + "_" + p['setter_name'] + p['setter_definition_begin'] = "static int pylinphone_" + c['class_name'] + "_" + p['setter_name'] + "(PyObject *self, PyObject *value, void *closure) {" + p['setter_definition_end'] = "}" + else: + p['setter_reference'] = "NULL" + c['class_properties'].append(p) self.classes.append(c) # Format events definitions for ev in self.events: @@ -805,24 +968,35 @@ def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_fu e.args += (c['class_name'], 'new_body') raise try: - c['new_from_native_pointer_body'] = NewFromNativePointerMethodDefinition(self, c).format() + c['init_body'] = InitMethodDefinition(self, c, xml_new_method).format() + except Exception, e: + e.args += (c['class_name'], 'init_body') + raise + try: + c['from_native_pointer_body'] = FromNativePointerMethodDefinition(self, c).format() except Exception, e: - e.args += (c['class_name'], 'new_from_native_pointer_body') + e.args += (c['class_name'], 'from_native_pointer_body') raise try: for m in c['class_type_methods']: m['method_body'] = MethodDefinition(self, c, m['method_xml_node']).format() + m['method_doc'] = self.__format_method_doc(m['method_xml_node']) for m in c['class_instance_methods']: m['method_body'] = MethodDefinition(self, c, m['method_xml_node']).format() + m['method_doc'] = self.__format_method_doc(m['method_xml_node']) except Exception, e: e.args += (c['class_name'], m['method_name']) raise try: for p in c['class_properties']: - if p.has_key('getter_xml_node'): - p['getter_body'] = GetterMethodDefinition(self, c, p['getter_xml_node']).format() + p['property_doc'] = '' if p.has_key('setter_xml_node'): p['setter_body'] = SetterMethodDefinition(self, c, p['setter_xml_node']).format() + p['property_doc'] = self.__format_setter_doc(p['setter_xml_node']) + if p.has_key('getter_xml_node'): + p['getter_body'] = GetterMethodDefinition(self, c, p['getter_xml_node']).format() + if p['property_doc'] == '': + p['property_doc'] = self.__format_getter_doc(p['getter_xml_node']) except Exception, e: e.args += (c['class_name'], p['property_name']) raise @@ -838,6 +1012,14 @@ def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_fu except Exception, e: e.args += (c['class_name'], 'dealloc_body') raise + # Convert mslist_types to a list of dictionaries for the template + d = [] + for mslist_type in self.mslist_types: + t = {} + t['c_contained_type'] = mslist_type + t['python_contained_type'] = strip_leading_linphone(mslist_type) + d.append(t) + self.mslist_types = d def __format_doc_node(self, node): desc = '' @@ -863,7 +1045,7 @@ def __format_doc_node(self, node): desc += '\n' return desc - def __format_doc(self, brief_description, detailed_description): + def __format_doc_content(self, brief_description, detailed_description): doc = '' if brief_description is None: brief_description = '' @@ -873,12 +1055,73 @@ def __format_doc(self, brief_description, detailed_description): desc = '' for node in list(detailed_description): desc += self.__format_doc_node(node) + '\n' - detailed_description = desc.strip().replace('\n', '\\n') + detailed_description = desc.strip() brief_description = brief_description.strip() doc += brief_description if detailed_description != '': if doc != '': - doc += '\\n\\n' - doc+= detailed_description - doc = '\"' + doc + '\"' + doc += '\n\n' + doc += detailed_description + return doc + + def __replace_doc_special_chars(self, doc): + return doc.replace('"', '').encode('string-escape') + + def __format_doc(self, brief_description, detailed_description): + doc = self.__format_doc_content(brief_description, detailed_description) + doc = self.__replace_doc_special_chars(doc) + return doc + + def __format_method_doc(self, xml_node): + doc = self.__format_doc_content(xml_node.find('briefdescription'), xml_node.find('detaileddescription')) + xml_method_return = xml_node.find('./return') + xml_method_args = xml_node.findall('./arguments/argument') + method_type = xml_node.tag + if method_type != 'classmethod' and len(xml_method_args) > 0: + xml_method_args = xml_method_args[1:] + doc += '\n' + if len(xml_method_args) > 0: + for xml_method_arg in xml_method_args: + arg_name = xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self) + arg_doc = self.__format_doc_content(None, xml_method_arg.find('description')) + doc += '\n:param ' + arg_name + ':' + if arg_doc != '': + doc += ' ' + arg_doc + doc += '\n:type ' + arg_name + ': ' + argument_type.type_str + if xml_method_return is not None: + return_type = xml_method_return.get('type') + return_complete_type = xml_method_return.get('completetype') + return_contained_type = xml_method_return.get('containedtype') + if return_complete_type != 'void': + return_doc = self.__format_doc_content(None, xml_method_return.find('description')) + return_argument_type = ArgumentType(return_type, return_complete_type, return_contained_type, self) + doc += '\n:returns: ' + return_doc + doc += '\n:rtype: ' + return_argument_type.type_str + doc = self.__replace_doc_special_chars(doc) + return doc + + def __format_setter_doc(self, xml_node): + xml_method_arg = xml_node.findall('./arguments/argument')[1] + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self) + doc = self.__format_doc_content(xml_node.find('briefdescription'), xml_node.find('detaileddescription')) + doc = '[' + argument_type.type_str + '] ' + doc + doc = self.__replace_doc_special_chars(doc) + return doc + + def __format_getter_doc(self, xml_node): + xml_method_return = xml_node.find('./return') + return_type = xml_method_return.get('type') + return_complete_type = xml_method_return.get('completetype') + return_contained_type = xml_method_return.get('containedtype') + return_argument_type = ArgumentType(return_type, return_complete_type, return_contained_type, self) + doc = self.__format_doc_content(xml_node.find('briefdescription'), xml_node.find('detaileddescription')) + doc = '[' + return_argument_type.type_str + '] ' + doc + doc = self.__replace_doc_special_chars(doc) return doc diff --git a/tools/python/apixml2python/linphone_module.mustache b/tools/python/apixml2python/linphone_module.mustache index aad4ff777..925902da7 100644 --- a/tools/python/apixml2python/linphone_module.mustache +++ b/tools/python/apixml2python/linphone_module.mustache @@ -17,11 +17,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include +#include #include #include #include #include +#include "gitversion.h" + #ifdef WIN32 #include #endif @@ -37,6 +41,10 @@ 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}} @@ -45,15 +53,16 @@ static PyTypeObject pylinphone_{{class_name}}Type; typedef struct { PyObject_HEAD + PyObject *user_data; {{class_cname}} *native_ptr; -{{{class_object_members}}} +{{{class_object_members_code}}} } pylinphone_{{class_name}}Object; {{/classes}} {{#classes}} static {{class_cname}} * pylinphone_{{class_name}}_get_native_ptr(PyObject *self); -static PyObject * pylinphone_{{class_name}}_new_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr); +static PyObject * pylinphone_{{class_name}}_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr); {{#class_type_hand_written_methods}} static PyObject * pylinphone_{{class_name}}_class_method_{{method_name}}(PyObject *cls, PyObject *args); {{/class_type_hand_written_methods}} @@ -62,6 +71,32 @@ static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyOb {{/class_instance_hand_written_methods}} {{/classes}} +{{#mslist_types}} +PyObject * PyList_FromMSListOf{{c_contained_type}}(const MSList *msl) { + PyObject *pyl = PyList_New(0); + while (msl != NULL) { + {{c_contained_type}} *native_ptr = ({{c_contained_type}} *)msl->data; + PyObject *item = pylinphone_{{python_contained_type}}_from_native_ptr(&pylinphone_{{python_contained_type}}Type, native_ptr); + PyList_Append(pyl, item); + msl = ms_list_next(msl); + } + return pyl; +} + +MSList * PyList_AsMSListOf{{c_contained_type}}(PyObject *pyl) { + MSList *msl = NULL; + Py_ssize_t idx; + Py_ssize_t size = PyList_Size(pyl); + for (idx = 0; idx < size; idx++) { + PyObject *item = PyList_GetItem(pyl, idx); + {{c_contained_type}} *native_ptr = pylinphone_{{python_contained_type}}_get_native_ptr(item); + msl = ms_list_append(msl, native_ptr); + } + return msl; +} + +{{/mslist_types}} + {{#events}} {{{event_callback_definition}}} {{/events}} @@ -72,14 +107,18 @@ 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}}_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr) { +{{{from_native_pointer_body}}} } static PyObject * pylinphone_{{class_name}}_new(PyTypeObject *type, PyObject *args, PyObject *kw) { {{{new_body}}} } +static int pylinphone_{{class_name}}_init(PyObject *self, PyObject *args, PyObject *kw) { +{{{init_body}}} +} + static void pylinphone_{{class_name}}_dealloc(PyObject *self) { {{{dealloc_body}}} } @@ -100,26 +139,30 @@ static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyOb {{/class_instance_methods}} -static PyMethodDef pylinphone_{{class_name}}_instance_methods[] = { - // TODO: Handle doc +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_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_name}}", pylinphone_{{class_name}}_instance_method_{{method_name}}, METH_VARARGS, "{{{method_doc}}}" }, {{/class_instance_methods}} /* Sentinel */ { NULL, NULL, 0, NULL } }; +static PyMemberDef pylinphone_{{class_name}}_members[] = { + { "user_data", T_OBJECT, offsetof(pylinphone_{{class_name}}Object, user_data), 0, "A place to store some user data." }, + { NULL, 0, 0, 0, NULL } /* Sentinel */ +}; + {{#class_properties}} {{{getter_definition_begin}}} @@ -133,9 +176,11 @@ static PyMethodDef pylinphone_{{class_name}}_instance_methods[] = { {{/class_properties}} static PyGetSetDef pylinphone_{{class_name}}_getseters[] = { - // TODO: Handle doc -{{#class_properties}} +{{#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 } @@ -163,22 +208,22 @@ static PyTypeObject pylinphone_{{class_name}}Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ - {{{class_doc}}}, /* tp_doc */ + "{{{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}}_instance_methods, /* tp_methods */ - 0, /* tp_members */ + pylinphone_{{class_name}}_methods, /* tp_methods */ + pylinphone_{{class_name}}_members, /* tp_members */ pylinphone_{{class_name}}_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - 0, /* tp_init */ + pylinphone_{{class_name}}_init, /* tp_init */ 0, /* tp_alloc */ pylinphone_{{class_name}}_new, /* tp_new */ 0, /* tp_free */ @@ -187,7 +232,7 @@ static PyTypeObject pylinphone_{{class_name}}Type = { {{/classes}} -{{> handwritten}} +{{> handwritten_definitions}} static PyMethodDef pylinphone_ModuleMethods[] = { @@ -220,37 +265,61 @@ static PyObject * pylinphone_{{enum_name}}_module_method_string(PyObject *self, } static PyMethodDef pylinphone_{{enum_name}}_ModuleMethods[] = { - { "string", pylinphone_{{enum_name}}_module_method_string, METH_VARARGS, "" }, + { "string", pylinphone_{{enum_name}}_module_method_string, METH_VARARGS, "Get a string representation of a linphone.{{enum_name}} value." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; {{/enums}} +{{> linphone_testing_module}} + PyMODINIT_FUNC initlinphone(void) { PyObject *m; PyObject *menum; + PyDateTime_IMPORT; pylinphone_init_logging(); {{#classes}} if (PyType_Ready(&pylinphone_{{class_name}}Type) < 0) return; {{/classes}} + /* Hand-written classes. */ + if (PyType_Ready(&pylinphone_VideoSizeType) < 0) return; + m = Py_InitModule3("linphone", pylinphone_ModuleMethods, "Python module giving access to the Linphone library."); if (m == NULL) return; + if (PyModule_AddStringConstant(m, "__version__", LINPHONE_GIT_REVISION) < 0) return; {{#enums}} - menum = Py_InitModule3("{{enum_name}}", pylinphone_{{enum_name}}_ModuleMethods, {{{enum_doc}}}); + menum = Py_InitModule3("{{enum_name}}", pylinphone_{{enum_name}}_ModuleMethods, "{{{enum_doc}}}"); if (menum == NULL) return; + Py_INCREF(menum); if (PyModule_AddObject(m, "{{enum_name}}", menum) < 0) return; {{#enum_values}} if (PyModule_AddIntConstant(menum, "{{enum_value_name}}", {{enum_value_cname}}) < 0) return; {{/enum_values}} {{/enums}} + menum = Py_InitModule3("PayloadTypeType", pylinphone_PayloadTypeType_ModuleMethods, "Type of linphone.PayloadType."); + if (menum == NULL) return; + Py_INCREF(menum); + if (PyModule_AddObject(m, "PayloadTypeType", menum) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_AUDIO_CONTINUOUS", PAYLOAD_AUDIO_CONTINUOUS) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_AUDIO_PACKETIZED", PAYLOAD_AUDIO_PACKETIZED) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_VIDEO", PAYLOAD_VIDEO) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_TEXT", PAYLOAD_TEXT) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_OTHER", PAYLOAD_OTHER) < 0) return; + {{#classes}} Py_INCREF(&pylinphone_{{class_name}}Type); PyModule_AddObject(m, "{{class_name}}", (PyObject *)&pylinphone_{{class_name}}Type); {{/classes}} + + /* Hand-written classes. */ + Py_INCREF(&pylinphone_VideoSizeType); + PyModule_AddObject(m, "VideoSize", (PyObject *)&pylinphone_VideoSizeType); + + pylinphone_init_testing_module(m); } diff --git a/tools/python/apixml2python/linphone_testing_module.mustache b/tools/python/apixml2python/linphone_testing_module.mustache new file mode 100644 index 000000000..b68f8a558 --- /dev/null +++ b/tools/python/apixml2python/linphone_testing_module.mustache @@ -0,0 +1,40 @@ +#include "private.h" + +static PyObject * pylinphone_testing_module_method_set_dns_user_hosts_file(PyObject *self, PyObject *args) { + PyObject *_core; + char *_path; + LinphoneCore *_core_native_ptr; + + if (!PyArg_ParseTuple(args, "Oz", &_core, &_path)) { + return NULL; + } + if ((_core != Py_None) && !PyObject_IsInstance(_core, (PyObject *)&pylinphone_CoreType)) { + PyErr_SetString(PyExc_TypeError, "The '_core' argument must be a linphone.Core instance."); + return NULL; + } + + if ((_core != NULL) && (_core != Py_None)) { + if ((_core_native_ptr = pylinphone_Core_get_native_ptr(_core)) == NULL) { + return NULL; + } + } + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p], %s)", __FUNCTION__, _core, _core_native_ptr, _path); + sal_set_dns_user_hosts_file(_core_native_ptr->sal, _path); + pylinphone_dispatch_messages(); + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> None", __FUNCTION__); + Py_RETURN_NONE; +} + +static PyMethodDef pylinphone_TestingModuleMethods[] = { + { "set_dns_user_hosts_file", pylinphone_testing_module_method_set_dns_user_hosts_file, METH_VARARGS, "Allows to set a user specified hosts file." }, + /* Sentinel */ + { NULL, NULL, 0, NULL } +}; + +static void pylinphone_init_testing_module(PyObject *linphone_module) { + PyObject *mtesting = Py_InitModule3("testing", pylinphone_TestingModuleMethods, "Python module adding some testing features for the Linphone library."); + Py_INCREF(mtesting); + if (PyModule_AddObject(linphone_module, "testing", mtesting) < 0) return; +} diff --git a/tools/python/doc/Makefile b/tools/python/doc/Makefile new file mode 100644 index 000000000..b8c40c718 --- /dev/null +++ b/tools/python/doc/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Linphone.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Linphone.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Linphone" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Linphone" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/tools/python/doc/make.bat b/tools/python/doc/make.bat new file mode 100644 index 000000000..9c081c72b --- /dev/null +++ b/tools/python/doc/make.bat @@ -0,0 +1,242 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source +set I18NSPHINXOPTS=%SPHINXOPTS% source +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Linphone.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Linphone.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/tools/python/doc/source/conf.py b/tools/python/doc/source/conf.py new file mode 100644 index 000000000..125e5c6d9 --- /dev/null +++ b/tools/python/doc/source/conf.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +# +# Linphone documentation build configuration file, created by +# sphinx-quickstart on Wed Aug 20 15:37:38 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Linphone' +copyright = u'2014, Belledonne Communications' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '3.7' +# The full version, including alpha/beta/rc tags. +release = '3.7.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Linphonedoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'Linphone.tex', u'Linphone Documentation', + u'Belledonne Communications', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'linphone', u'Linphone Documentation', + [u'Belledonne Communications'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Linphone', u'Linphone Documentation', + u'Belledonne Communications', 'Linphone', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/tools/python/doc/source/index.rst b/tools/python/doc/source/index.rst new file mode 100644 index 000000000..f1c615162 --- /dev/null +++ b/tools/python/doc/source/index.rst @@ -0,0 +1,72 @@ +.. Linphone documentation master file, created by + sphinx-quickstart on Wed Aug 20 15:37:38 2014. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Linphone for Python documentation +================================= + +Getting started +--------------- + +Installing the Python module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can install prebuilt packages of Linphone for Python. You will find the +releases at https://pypi.python.org/pypi/linphone. This includes only packages +for the Windows platform right now. The easiest way to install is to use pip, +eg.: + +.. code-block:: none + + > pip install linphone --pre + +You can also find nightly-built packages for Windows, Mac OS X and Linux at +https://www.linphone.org/snapshots/linphone-python/. + +Otherwise you can compile the Python module. To do so get the build system code +using the command: + +.. code-block:: none + + > git clone git://git.linphone.org/linphone-cmake-builder.git + +Then follow the instructions in the *README.python* file. + +Running some code +^^^^^^^^^^^^^^^^^ + +Here is a sample source code using PyQt4 that enables you to register on a SIP +server in just a few lines of code. This is a very basic example, but it shows +how to create a linphone.Core object that is the main object of Linphone. From +there, you can use the API reference below to use more advanced feature and +perform some SIP calls, use text messaging and more... + +.. literalinclude:: pyqt_linphone_example.py + +In the Linphone Python module package you installed previously you will also +find some unit tests that you can run. These unit tests will be located in the +*site-packages/linphone/unittests/* directory of Python installation where you +installed the Linphone Python module package. To run these unit tests, follow +the instructions contained in the README.txt file of this *unittests/* +directory. + +API reference +------------- + +.. toctree:: + :maxdepth: 2 + +.. automodule:: linphone + :members: + :undoc-members: + +.. autoattribute:: linphone.__version__ + + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`search` + diff --git a/tools/python/doc/source/pyqt_linphone_example.py b/tools/python/doc/source/pyqt_linphone_example.py new file mode 100644 index 000000000..9c214c0be --- /dev/null +++ b/tools/python/doc/source/pyqt_linphone_example.py @@ -0,0 +1,47 @@ +import linphone +import logging +import sys +from PyQt4.QtCore import QTimer +from PyQt4.QtGui import QApplication + + +def main(): + logging.basicConfig(level=logging.INFO) + + app = QApplication(sys.argv) + + def log_handler(level, msg): + method = getattr(logging, level) + method(msg) + + def global_state_changed(*args, **kwargs): + logging.warning("global_state_changed: %r %r" % (args, kwargs)) + + def registration_state_changed(core, call, state, message): + logging.warning("registration_state_changed: " + str(state) + ", " + message) + + callbacks = { + 'global_state_changed': global_state_changed, + 'registration_state_changed': registration_state_changed, + } + + linphone.set_log_handler(log_handler) + core = linphone.Core.new(callbacks, None, None) + proxy_cfg = core.create_proxy_config() + proxy_cfg.identity = "sip:toto@test.linphone.org" + proxy_cfg.server_addr = "sip:test.linphone.org" + proxy_cfg.register_enabled = True + core.add_proxy_config(proxy_cfg) + + iterate_timer = QTimer() + iterate_timer.timeout.connect(core.iterate) + stop_timer = QTimer() + stop_timer.timeout.connect(app.quit) + iterate_timer.start(20) + stop_timer.start(5000) + + exitcode = app.exec_() + sys.exit(exitcode) + + +main() diff --git a/tools/python/linphone-daemon.py b/tools/python/linphone-daemon.py index 547aba918..a923c3ee9 100644 --- a/tools/python/linphone-daemon.py +++ b/tools/python/linphone-daemon.py @@ -3,7 +3,7 @@ import sys import threading import time -from linphone import linphone +import linphone class Response: diff --git a/tools/python/setup.py b/tools/python/setup.py deleted file mode 100644 index bcd5dc419..000000000 --- a/tools/python/setup.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/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]) diff --git a/tools/python/unittests/README.txt b/tools/python/unittests/README.txt new file mode 100644 index 000000000..f0f57a2b3 --- /dev/null +++ b/tools/python/unittests/README.txt @@ -0,0 +1,14 @@ +*************************************** +** Linphone Python module unit tests ** +*************************************** + +To run these unit tests, you need to have installed the Python module for Linphone +and to have install the nose unit tests framework. +Then use this command to run the tests: + nosetests -v --nologcapture + +The logs from the tests are put in some .log files. + +A single test file can be run by specifying it at the command line. For example, +to run only the message unit tests use: + nosetests -v --nologcapture test_message.py diff --git a/tools/python/unittests/linphonetester.py b/tools/python/unittests/linphonetester.py new file mode 100644 index 000000000..fcd485c79 --- /dev/null +++ b/tools/python/unittests/linphonetester.py @@ -0,0 +1,512 @@ +from datetime import timedelta, datetime +from nose.tools import assert_equals +from copy import deepcopy +import linphone +import logging +import os +import time + + +test_username = "liblinphone_tester" +test_password = "secret" +test_route = "sip2.linphone.org" +if os.path.isdir(os.path.join(os.path.dirname(__file__), "rcfiles")): + # Running unit tests from an installed package + tester_resources_path = os.path.abspath(os.path.dirname(__file__)) +else: + # Running unit tests from the linphone sources + tester_resources_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../tester/")) + + +def create_address(domain): + addr = linphone.Address.new(None) + assert addr != None + addr.username = test_username + assert_equals(addr.username, test_username) + if domain is None: + domain = test_route + addr.domain = domain + assert_equals(addr.domain, domain) + addr.display_name = None + addr.display_name = "Mr Tester" + assert_equals(addr.display_name, "Mr Tester") + return addr + + +class Logger(logging.Logger): + + def __init__(self, filename): + logging.Logger.__init__(self, filename) + handler = logging.FileHandler(filename) + handler.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s.%(msecs)03d %(levelname)s: %(message)s', '%H:%M:%S') + handler.setFormatter(formatter) + self.addHandler(handler) + linphone.set_log_handler(self.log_handler) + + def log_handler(self, level, msg): + method = getattr(self, level) + if not msg.strip().startswith('[PYLINPHONE]'): + msg = '[CORE] ' + msg + method(msg) + + +class CoreManagerStats: + def __init__(self): + self.reset() + + def reset(self): + self.number_of_LinphoneRegistrationNone = 0 + self.number_of_LinphoneRegistrationProgress = 0 + self.number_of_LinphoneRegistrationOk = 0 + self.number_of_LinphoneRegistrationCleared = 0 + self.number_of_LinphoneRegistrationFailed = 0 + self.number_of_auth_info_requested = 0 + + self.number_of_LinphoneCallIncomingReceived = 0 + self.number_of_LinphoneCallOutgoingInit = 0 + self.number_of_LinphoneCallOutgoingProgress = 0 + self.number_of_LinphoneCallOutgoingRinging = 0 + self.number_of_LinphoneCallOutgoingEarlyMedia = 0 + self.number_of_LinphoneCallConnected = 0 + self.number_of_LinphoneCallStreamsRunning = 0 + self.number_of_LinphoneCallPausing = 0 + self.number_of_LinphoneCallPaused = 0 + self.number_of_LinphoneCallResuming = 0 + self.number_of_LinphoneCallRefered = 0 + self.number_of_LinphoneCallError = 0 + self.number_of_LinphoneCallEnd = 0 + self.number_of_LinphoneCallPausedByRemote = 0 + self.number_of_LinphoneCallUpdatedByRemote = 0 + self.number_of_LinphoneCallIncomingEarlyMedia = 0 + self.number_of_LinphoneCallUpdating = 0 + self.number_of_LinphoneCallReleased = 0 + + self.number_of_LinphoneTransferCallOutgoingInit = 0 + self.number_of_LinphoneTransferCallOutgoingProgress = 0 + self.number_of_LinphoneTransferCallOutgoingRinging = 0 + self.number_of_LinphoneTransferCallOutgoingEarlyMedia = 0 + self.number_of_LinphoneTransferCallConnected = 0 + self.number_of_LinphoneTransferCallStreamsRunning = 0 + self.number_of_LinphoneTransferCallError = 0 + + self.number_of_LinphoneMessageReceived = 0 + self.number_of_LinphoneMessageReceivedWithFile = 0 + self.number_of_LinphoneMessageReceivedLegacy = 0 + self.number_of_LinphoneMessageExtBodyReceived = 0 + self.number_of_LinphoneMessageInProgress = 0 + self.number_of_LinphoneMessageDelivered = 0 + self.number_of_LinphoneMessageNotDelivered = 0 + self.number_of_LinphoneIsComposingActiveReceived = 0 + self.number_of_LinphoneIsComposingIdleReceived = 0 + self.progress_of_LinphoneFileTransfer = 0 + + self.number_of_IframeDecoded = 0 + + self.number_of_NewSubscriptionRequest =0 + self.number_of_NotifyReceived = 0 + self.number_of_LinphonePresenceActivityOffline = 0 + self.number_of_LinphonePresenceActivityOnline = 0 + self.number_of_LinphonePresenceActivityAppointment = 0 + self.number_of_LinphonePresenceActivityAway = 0 + self.number_of_LinphonePresenceActivityBreakfast = 0 + self.number_of_LinphonePresenceActivityBusy = 0 + self.number_of_LinphonePresenceActivityDinner = 0 + self.number_of_LinphonePresenceActivityHoliday = 0 + self.number_of_LinphonePresenceActivityInTransit = 0 + self.number_of_LinphonePresenceActivityLookingForWork = 0 + self.number_of_LinphonePresenceActivityLunch = 0 + self.number_of_LinphonePresenceActivityMeal = 0 + self.number_of_LinphonePresenceActivityMeeting = 0 + self.number_of_LinphonePresenceActivityOnThePhone = 0 + self.number_of_LinphonePresenceActivityOther = 0 + self.number_of_LinphonePresenceActivityPerformance = 0 + self.number_of_LinphonePresenceActivityPermanentAbsence = 0 + self.number_of_LinphonePresenceActivityPlaying = 0 + self.number_of_LinphonePresenceActivityPresentation = 0 + self.number_of_LinphonePresenceActivityShopping = 0 + self.number_of_LinphonePresenceActivitySleeping = 0 + self.number_of_LinphonePresenceActivitySpectator = 0 + self.number_of_LinphonePresenceActivitySteering = 0 + self.number_of_LinphonePresenceActivityTravel = 0 + self.number_of_LinphonePresenceActivityTV = 0 + self.number_of_LinphonePresenceActivityUnknown = 0 + self.number_of_LinphonePresenceActivityVacation = 0 + self.number_of_LinphonePresenceActivityWorking = 0 + self.number_of_LinphonePresenceActivityWorship = 0 + self.last_received_presence = None + + self.number_of_inforeceived = 0 + + self.number_of_LinphoneSubscriptionIncomingReceived = 0 + self.number_of_LinphoneSubscriptionOutgoingInit = 0 + self.number_of_LinphoneSubscriptionPending = 0 + self.number_of_LinphoneSubscriptionActive = 0 + self.number_of_LinphoneSubscriptionTerminated = 0 + self.number_of_LinphoneSubscriptionError = 0 + self.number_of_LinphoneSubscriptionExpiring = 0 + + self.number_of_LinphonePublishProgress = 0 + self.number_of_LinphonePublishOk = 0 + self.number_of_LinphonePublishExpiring = 0 + self.number_of_LinphonePublishError = 0 + self.number_of_LinphonePublishCleared = 0 + + self.number_of_LinphoneConfiguringSkipped = 0 + self.number_of_LinphoneConfiguringFailed = 0 + self.number_of_LinphoneConfiguringSuccessful = 0 + + self.number_of_LinphoneCallEncryptedOn = 0 + self.number_of_LinphoneCallEncryptedOff = 0 + + +class CoreManager: + + @classmethod + def wait_for_until(cls, manager1, manager2, func, timeout): + managers = [] + if manager1 is not None: + managers.append(manager1) + if manager2 is not None: + managers.append(manager2) + return cls.wait_for_list(managers, func, timeout) + + @classmethod + def wait_for_list(cls, managers, func, timeout): + start = datetime.now() + end = start + timedelta(milliseconds = timeout) + res = func(*managers) + while not res and datetime.now() < end: + for manager in managers: + manager.lc.iterate() + time.sleep(0.02) + res = func(*managers) + return res + + @classmethod + def wait_for(cls, manager1, manager2, func): + return cls.wait_for_until(manager1, manager2, func, 10000) + + @classmethod + def call(cls, caller_manager, callee_manager, caller_params = None, callee_params = None, build_callee_params = False): + initial_caller_stats = deepcopy(caller_manager.stats) + initial_callee_stats = deepcopy(callee_manager.stats) + + # Use playfile for callee to avoid locking on capture card + callee_manager.lc.use_files = True + callee_manager.lc.play_file = os.path.join(tester_resources_path, 'sounds', 'hello8000.wav') + + if caller_params is None: + call = caller_manager.lc.invite_address(callee_manager.identity) + else: + call = caller_manager.lc.invite_address_with_params(callee_manager.identity, caller_params) + assert call is not None + + assert_equals(CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: callee_manager.stats.number_of_LinphoneCallIncomingReceived == initial_callee_stats.number_of_LinphoneCallIncomingReceived + 1), True) + assert_equals(callee_manager.lc.incoming_invite_pending, True) + assert_equals(caller_manager.stats.number_of_LinphoneCallOutgoingProgress, initial_caller_stats.number_of_LinphoneCallOutgoingProgress + 1) + + retry = 0 + while (caller_manager.stats.number_of_LinphoneCallOutgoingRinging != initial_caller_stats.number_of_LinphoneCallOutgoingRinging + 1) and \ + (caller_manager.stats.number_of_LinphoneCallOutgoingEarlyMedia != initial_caller_stats.number_of_LinphoneCallOutgoingEarlyMedia + 1) and \ + retry < 20: + retry += 1 + caller_manager.lc.iterate() + callee_manager.lc.iterate() + time.sleep(0.1) + assert ((caller_manager.stats.number_of_LinphoneCallOutgoingRinging == initial_caller_stats.number_of_LinphoneCallOutgoingRinging + 1) or \ + (caller_manager.stats.number_of_LinphoneCallOutgoingEarlyMedia == initial_caller_stats.number_of_LinphoneCallOutgoingEarlyMedia + 1)) == True + + assert callee_manager.lc.current_call_remote_address is not None + if caller_manager.lc.current_call is None or callee_manager.lc.current_call is None or callee_manager.lc.current_call_remote_address is None: + return False + callee_from_address = caller_manager.identity.clone() + callee_from_address.port = 0 # Remove port because port is never present in from header + assert_equals(callee_from_address.weak_equal(callee_manager.lc.current_call_remote_address), True) + + if callee_params is not None: + callee_manager.lc.accept_call_with_params(callee_manager.lc.current_call, callee_params) + elif build_callee_params: + default_params = callee_manager.lc.create_call_params(callee_manager.lc.current_call) + callee_manager.lc.accept_call_with_params(callee_manager.lc.current_call, default_params) + else: + callee_manager.lc.accept_call(callee_manager.lc.current_call) + assert_equals(CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: (callee_manager.stats.number_of_LinphoneCallConnected == initial_callee_stats.number_of_LinphoneCallConnected + 1) and \ + (caller_manager.stats.number_of_LinphoneCallConnected == initial_caller_stats.number_of_LinphoneCallConnected + 1)), True) + # Just to sleep + result = CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: (callee_manager.stats.number_of_LinphoneCallStreamsRunning == initial_callee_stats.number_of_LinphoneCallStreamsRunning + 1) and \ + (caller_manager.stats.number_of_LinphoneCallStreamsRunning == initial_caller_stats.number_of_LinphoneCallStreamsRunning + 1)) + + if caller_manager.lc.media_encryption != linphone.MediaEncryption.MediaEncryptionNone and callee_manager.lc.media_encryption != linphone.MediaEncryption.MediaEncryptionNone: + # Wait for encryption to be on, in case of zrtp, it can take a few seconds + if caller_manager.lc.media_encryption == linphone.MediaEncryption.MediaEncryptionZRTP: + CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: caller_manager.stats.number_of_LinphoneCallEncryptedOn == initial_caller_stats.number_of_LinphoneCallEncryptedOn + 1) + if callee_manager.lc.media_encryption == linphone.MediaEncryption.MediaEncryptionZRTP: + CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: callee_manager.stats.number_of_LinphoneCallEncryptedOn == initial_callee_stats.number_of_LinphoneCallEncryptedOn + 1) + assert_equals(callee_manager.lc.current_call.current_params.media_encryption, caller_manager.lc.media_encryption) + assert_equals(caller_manager.lc.current_call.current_params.media_encryption, callee_manager.lc.media_encryption) + + return result + + @classmethod + def end_call(cls, caller_manager, callee_manager): + caller_manager.lc.terminate_all_calls() + assert_equals(CoreManager.wait_for(caller_manager, callee_manager, + lambda caller_manager, callee_manager: caller_manager.stats.number_of_LinphoneCallEnd == 1 and callee_manager.stats.number_of_LinphoneCallEnd == 1), True) + + @classmethod + def registration_state_changed(cls, lc, cfg, state, message): + manager = lc.user_data + if manager.logger is not None: + manager.logger.info("[TESTER] New registration state {state} for user id [{identity}] at proxy [{addr}]".format( + state=linphone.RegistrationState.string(state), identity=cfg.identity, addr=cfg.server_addr)) + if state == linphone.RegistrationState.RegistrationNone: + manager.stats.number_of_LinphoneRegistrationNone += 1 + elif state == linphone.RegistrationState.RegistrationProgress: + manager.stats.number_of_LinphoneRegistrationProgress += 1 + elif state == linphone.RegistrationState.RegistrationOk: + manager.stats.number_of_LinphoneRegistrationOk += 1 + elif state == linphone.RegistrationState.RegistrationCleared: + manager.stats.number_of_LinphoneRegistrationCleared += 1 + elif state == linphone.RegistrationState.RegistrationFailed: + manager.stats.number_of_LinphoneRegistrationFailed += 1 + else: + raise Exception("Unexpected registration state") + + @classmethod + def auth_info_requested(cls, lc, realm, username, domain): + manager = lc.user_data + if manager.logger is not None: + manager.logger.info("[TESTER] Auth info requested for user id [{username}] at realm [{realm}]".format( + username=username, realm=realm)) + manager.stats.number_of_auth_info_requested +=1 + + @classmethod + def call_state_changed(cls, lc, call, state, msg): + manager = lc.user_data + to_address = call.call_log.to_address.as_string() + from_address = call.call_log.from_address.as_string() + direction = "Outgoing" + if call.call_log.dir == linphone.CallDir.CallIncoming: + direction = "Incoming" + if manager.logger is not None: + manager.logger.info("[TESTER] {direction} call from [{from_address}] to [{to_address}], new state is [{state}]".format( + direction=direction, from_address=from_address, to_address=to_address, state=linphone.CallState.string(state))) + if state == linphone.CallState.CallIncomingReceived: + manager.stats.number_of_LinphoneCallIncomingReceived += 1 + elif state == linphone.CallState.CallOutgoingInit: + manager.stats.number_of_LinphoneCallOutgoingInit += 1 + elif state == linphone.CallState.CallOutgoingProgress: + manager.stats.number_of_LinphoneCallOutgoingProgress += 1 + elif state == linphone.CallState.CallOutgoingRinging: + manager.stats.number_of_LinphoneCallOutgoingRinging += 1 + elif state == linphone.CallState.CallOutgoingEarlyMedia: + manager.stats.number_of_LinphoneCallOutgoingEarlyMedia += 1 + elif state == linphone.CallState.CallConnected: + manager.stats.number_of_LinphoneCallConnected += 1 + elif state == linphone.CallState.CallStreamsRunning: + manager.stats.number_of_LinphoneCallStreamsRunning += 1 + elif state == linphone.CallState.CallPausing: + manager.stats.number_of_LinphoneCallPausing += 1 + elif state == linphone.CallState.CallPaused: + manager.stats.number_of_LinphoneCallPaused += 1 + elif state == linphone.CallState.CallResuming: + manager.stats.number_of_LinphoneCallResuming += 1 + elif state == linphone.CallState.CallRefered: + manager.stats.number_of_LinphoneCallRefered += 1 + elif state == linphone.CallState.CallError: + manager.stats.number_of_LinphoneCallError += 1 + elif state == linphone.CallState.CallEnd: + manager.stats.number_of_LinphoneCallEnd += 1 + elif state == linphone.CallState.CallPausedByRemote: + manager.stats.number_of_LinphoneCallPausedByRemote += 1 + elif state == linphone.CallState.CallUpdatedByRemote: + manager.stats.number_of_LinphoneCallUpdatedByRemote += 1 + elif state == linphone.CallState.CallIncomingEarlyMedia: + manager.stats.number_of_LinphoneCallIncomingEarlyMedia += 1 + elif state == linphone.CallState.CallUpdating: + manager.stats.number_of_LinphoneCallUpdating += 1 + elif state == linphone.CallState.CallReleased: + manager.stats.number_of_LinphoneCallReleased += 1 + else: + raise Exception("Unexpected call state") + + @classmethod + def message_received(cls, lc, room, message): + manager = lc.user_data + from_str = message.from_address.as_string() + text_str = message.text + external_body_url = message.external_body_url + if manager.logger is not None: + manager.logger.info("[TESTER] Message from [{from_str}] is [{text_str}], external URL [{external_body_url}]".format( + from_str=from_str, text_str=text_str, external_body_url=external_body_url)) + manager.stats.number_of_LinphoneMessageReceived += 1 + + if message.external_body_url is not None: + manager.stats.number_of_LinphoneMessageExtBodyReceived += 1 + + @classmethod + def new_subscription_requested(cls, lc, lf, url): + manager = lc.user_data + if manager.logger is not None: + manager.logger.info("[TESTER] New subscription request: from [{from_str}], url [{url}]".format( + from_str=lf.address.as_string(), url=url)) + manager.stats.number_of_NewSubscriptionRequest += 1 + lc.add_friend(lf) # Accept subscription + + @classmethod + def notify_presence_received(cls, lc, lf): + manager = lc.user_data + if manager.logger is not None: + manager.logger.info("[TESTER] New notify request: from [{from_str}]".format( + from_str=lf.address.as_string())) + manager.stats.number_of_NotifyReceived += 1 + manager.stats.last_received_presence = lf.presence_model + acttype = manager.stats.last_received_presence.activity.type + if acttype == linphone.PresenceActivityType.PresenceActivityOffline: + manager.stats.number_of_LinphonePresenceActivityOffline += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityOnline: + manager.stats.number_of_LinphonePresenceActivityOnline += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityAppointment: + manager.stats.number_of_LinphonePresenceActivityAppointment += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityAway: + manager.stats.number_of_LinphonePresenceActivityAway += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityBreakfast: + manager.stats.number_of_LinphonePresenceActivityBreakfast += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityBusy: + manager.stats.number_of_LinphonePresenceActivityBusy += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityDinner: + manager.stats.number_of_LinphonePresenceActivityDinner += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityHoliday: + manager.stats.number_of_LinphonePresenceActivityHoliday += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityInTransit: + manager.stats.number_of_LinphonePresenceActivityInTransit += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityLookingForWork: + manager.stats.number_of_LinphonePresenceActivityLookingForWork += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityLunch: + manager.stats.number_of_LinphonePresenceActivityLunch += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityMeal: + manager.stats.number_of_LinphonePresenceActivityMeal += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityMeeting: + manager.stats.number_of_LinphonePresenceActivityMeeting += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityOnThePhone: + manager.stats.number_of_LinphonePresenceActivityOnThePhone += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityOther: + manager.stats.number_of_LinphonePresenceActivityOther += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityPerformance: + manager.stats.number_of_LinphonePresenceActivityPerformance += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityPermanentAbsence: + manager.stats.number_of_LinphonePresenceActivityPermanentAbsence += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityPlaying: + manager.stats.number_of_LinphonePresenceActivityPlaying += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityPresentation: + manager.stats.number_of_LinphonePresenceActivityPresentation += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityShopping: + manager.stats.number_of_LinphonePresenceActivityShopping += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivitySleeping: + manager.stats.number_of_LinphonePresenceActivitySleeping += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivitySpectator: + manager.stats.number_of_LinphonePresenceActivitySpectator += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivitySteering: + manager.stats.number_of_LinphonePresenceActivitySteering += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityTravel: + manager.stats.number_of_LinphonePresenceActivityTravel += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityTV: + manager.stats.number_of_LinphonePresenceActivityTV += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityUnknown: + manager.stats.number_of_LinphonePresenceActivityUnknown += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityVacation: + manager.stats.number_of_LinphonePresenceActivityVacation += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityWorking: + manager.stats.number_of_LinphonePresenceActivityWorking += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityWorship: + manager.stats.number_of_LinphonePresenceActivityWorship += 1 + + def __init__(self, rc_file = None, check_for_proxies = True, vtable = {}, logger=None): + self.logger = logger + if not vtable.has_key('registration_state_changed'): + vtable['registration_state_changed'] = CoreManager.registration_state_changed + if not vtable.has_key('auth_info_requested'): + vtable['auth_info_requested'] = CoreManager.auth_info_requested + if not vtable.has_key('call_state_changed'): + vtable['call_state_changed'] = CoreManager.call_state_changed + if not vtable.has_key('message_received'): + vtable['message_received'] = CoreManager.message_received + #if not vtable.has_key('file_transfer_recv'): + #vtable['file_transfer_recv'] = CoreManager.file_transfer_recv + #if not vtable.has_key('file_transfer_send'): + #vtable['file_transfer_send'] = CoreManager.file_transfer_send + #if not vtable.has_key('file_transfer_progress_indication'): + #vtable['file_transfer_progress_indication'] = CoreManager.file_transfer_progress_indication + #if not vtable.has_key('is_composing_received'): + #vtable['is_composing_received'] = CoreManager.is_composing_received + if not vtable.has_key('new_subscription_requested'): + vtable['new_subscription_requested'] = CoreManager.new_subscription_requested + if not vtable.has_key('notify_presence_received'): + vtable['notify_presence_received'] = CoreManager.notify_presence_received + #if not vtable.has_key('transfer_state_changed'): + #vtable['transfer_state_changed'] = CoreManager.transfer_state_changed + #if not vtable.has_key('info_received'): + #vtable['info_received'] = CoreManager.info_received + #if not vtable.has_key('subscription_state_changed'): + #vtable['subscription_state_changed'] = CoreManager.subscription_state_changed + #if not vtable.has_key('notify_received'): + #vtable['notify_received'] = CoreManager.notify_received + #if not vtable.has_key('publish_state_changed'): + #vtable['publish_state_changed'] = CoreManager.publish_state_changed + #if not vtable.has_key('configuring_status'): + #vtable['configuring_status'] = CoreManager.configuring_status + #if not vtable.has_key('call_encryption_changed'): + #vtable['call_encryption_changed'] = CoreManager.call_encryption_changed + self.identity = None + self.stats = CoreManagerStats() + rc_path = None + if rc_file is not None: + rc_path = os.path.join('rcfiles', rc_file) + self.lc = self.configure_lc_from(vtable, tester_resources_path, rc_path) + self.lc.user_data = self + if check_for_proxies and rc_file is not None: + proxy_count = len(self.lc.proxy_config_list) + else: + proxy_count = 0 + if proxy_count: + CoreManager.wait_for_until(self, None, lambda manager: manager.stats.number_of_LinphoneRegistrationOk == proxy_count, 5000 * proxy_count) + assert_equals(self.stats.number_of_LinphoneRegistrationOk, proxy_count) + self.enable_audio_codec("PCMU", 8000) + + if self.lc.default_proxy_config is not None: + self.identity = linphone.Address.new(self.lc.default_proxy_config.identity) + self.identity.clean() + + def stop(self): + self.lc = None + + def configure_lc_from(self, vtable, resources_path, rc_path): + filepath = None + if rc_path is not None: + filepath = os.path.join(resources_path, rc_path) + assert_equals(os.path.isfile(filepath), True) + lc = linphone.Core.new(vtable, None, filepath) + linphone.testing.set_dns_user_hosts_file(lc, os.path.join(resources_path, 'tester_hosts')) + lc.root_ca = os.path.join(resources_path, 'certificates', 'cn', 'cafile.pem') + lc.ring = os.path.join(resources_path, 'sounds', 'oldphone.wav') + lc.ringback = os.path.join(resources_path, 'sounds', 'ringback.wav') + lc.static_picture = os.path.join(resources_path, 'images', 'nowebcamCIF.jpg') + return lc + + def enable_audio_codec(self, mime, rate): + codecs = self.lc.audio_codecs + for codec in codecs: + self.lc.enable_payload_type(codec, False) + codec = self.lc.find_payload_type(mime, rate, 1) + assert codec is not None + if codec is not None: + self.lc.enable_payload_type(codec, True) + + def disable_all_audio_codecs_except_one(self, mime): + self.enable_audio_codec(mime, -1) diff --git a/tools/python/unittests/test_call.py b/tools/python/unittests/test_call.py new file mode 100644 index 000000000..93dfd1175 --- /dev/null +++ b/tools/python/unittests/test_call.py @@ -0,0 +1,116 @@ +from nose.tools import assert_equals +import linphone +from linphonetester import * +import os +import time + + +class TestCall: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def test_early_declined_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + marie.lc.max_calls = 0 + out_call = pauline.lc.invite('marie') + + # Wait until flexisip transfers the busy... + assert_equals(CoreManager.wait_for_until(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallError == 1, 33000), True) + assert_equals(pauline.stats.number_of_LinphoneCallError, 1) + assert_equals(out_call.reason, linphone.Reason.ReasonBusy) + if len(pauline.lc.call_logs) > 0: + out_call_log = pauline.lc.call_logs[0] + assert out_call_log is not None + assert_equals(out_call_log.status, linphone.CallStatus.CallAborted) + marie.stop() + pauline.stop() + + def test_declined_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + out_call = pauline.lc.invite_address(marie.identity) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallIncomingReceived == 1), True) + in_call = marie.lc.current_call + assert in_call is not None + if in_call is not None: + marie.lc.terminate_call(in_call) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallReleased == 1), True) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallReleased == 1), True) + assert_equals(marie.stats.number_of_LinphoneCallEnd, 1) + assert_equals(pauline.stats.number_of_LinphoneCallEnd, 1) + assert_equals(in_call.reason, linphone.Reason.ReasonDeclined) + assert_equals(out_call.reason, linphone.Reason.ReasonDeclined) + marie.stop() + pauline.stop() + + def test_cancelled_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + out_call = pauline.lc.invite('marie') + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallOutgoingInit == 1), True) + pauline.lc.terminate_call(out_call) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallEnd == 1), True) + assert_equals(pauline.stats.number_of_LinphoneCallEnd, 1) + assert_equals(marie.stats.number_of_LinphoneCallIncomingReceived, 0) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallReleased == 1), True) + marie.stop() + pauline.stop() + + def test_early_cancelled_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('empty_rc', check_for_proxies=False, logger=TestCall.logger) + out_call = pauline.lc.invite_address(marie.identity) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallOutgoingInit == 1), True) + pauline.lc.terminate_call(out_call) + + # Since everything is executed in a row, no response can be received from the server, thus the CANCEL cannot be sent. + # It will ring at Marie's side. + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallEnd == 1), True) + assert_equals(pauline.stats.number_of_LinphoneCallEnd, 1) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallIncomingReceived == 1), True) + + # Now the CANCEL should have been sent and the the call at marie's side should terminate + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallEnd == 1), True) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallReleased == 1), True) + marie.stop() + pauline.stop() + + def test_cancelled_ringing_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + out_call = pauline.lc.invite('marie') + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallIncomingReceived == 1), True) + pauline.lc.terminate_call(out_call) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: (pauline.stats.number_of_LinphoneCallReleased == 1) and (marie.stats.number_of_LinphoneCallReleased == 1)), True) + assert_equals(marie.stats.number_of_LinphoneCallEnd, 1) + assert_equals(pauline.stats.number_of_LinphoneCallEnd, 1) + marie.stop() + pauline.stop() + + def test_call_failed_because_of_codecs(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + marie.disable_all_audio_codecs_except_one('pcmu') + pauline.disable_all_audio_codecs_except_one('pcma') + out_call = pauline.lc.invite('marie') + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallOutgoingInit == 1), True) + + # flexisip will retain the 488 until the "urgent reply" timeout arrives. + assert_equals(CoreManager.wait_for_until(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallError == 1, 6000), True) + assert_equals(out_call.reason, linphone.Reason.ReasonNotAcceptable) + assert_equals(marie.stats.number_of_LinphoneCallIncomingReceived, 0) + marie.stop() + pauline.stop() + + def test_simple_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + assert_equals(CoreManager.call(pauline, marie), True) + #liblinphone_tester_check_rtcp(marie,pauline); + CoreManager.end_call(marie, pauline) + marie.stop() + pauline.stop() diff --git a/tools/python/unittests/test_message.py b/tools/python/unittests/test_message.py new file mode 100644 index 000000000..56a7e9e17 --- /dev/null +++ b/tools/python/unittests/test_message.py @@ -0,0 +1,46 @@ +from nose.tools import assert_equals +from copy import deepcopy +import linphone +from linphonetester import * +import os +import time + + +class TestMessage: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def wait_for_server_to_purge_messages(self, manager1, manager2): + # Wait a little bit just to have time to purge message stored in the server + CoreManager.wait_for_until(manager1, manager2, lambda manager1, manager2: False, 100) + manager1.stats.reset() + manager2.stats.reset() + + def test_text_message(self): + marie = CoreManager('marie_rc', logger=TestMessage.logger) + pauline = CoreManager('pauline_rc', logger=TestMessage.logger) + chat_room = pauline.lc.get_chat_room(marie.identity) + self.wait_for_server_to_purge_messages(marie, pauline) + msg = chat_room.create_message("Bla bla bla bla") + chat_room.send_message2(msg, None, None) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneMessageReceived == 1), True) + assert marie.lc.get_chat_room(pauline.identity) is not None + marie.stop() + pauline.stop() + + def test_text_message_within_dialog(self): + marie = CoreManager('marie_rc', logger=TestMessage.logger) + pauline = CoreManager('pauline_rc', logger=TestMessage.logger) + pauline.lc.config.set_int('sip', 'chat_use_call_dialogs', 1) + chat_room = pauline.lc.get_chat_room(marie.identity) + self.wait_for_server_to_purge_messages(marie, pauline) + assert_equals(CoreManager.call(marie, pauline), True) + msg = chat_room.create_message("Bla bla bla bla") + chat_room.send_message2(msg, None, None) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneMessageReceived == 1), True) + assert marie.lc.get_chat_room(pauline.identity) is not None + marie.stop() + pauline.stop() diff --git a/tools/python/unittests/test_presence.py b/tools/python/unittests/test_presence.py new file mode 100644 index 000000000..3de4e2e2a --- /dev/null +++ b/tools/python/unittests/test_presence.py @@ -0,0 +1,44 @@ +from nose.tools import assert_equals +from copy import deepcopy +import linphone +from linphonetester import * +import os +import time + + +class PresenceCoreManager(CoreManager): + + def __init__(self, username, logger = None): + CoreManager.__init__(self, 'empty_rc', False, logger=logger) + self.identity = self.lc.primary_contact_parsed + self.identity.username = username + self.lc.primary_contact = self.identity.as_string() + +class TestPresence: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def subscribe_to_callee_presence(self, caller_mgr, callee_mgr): + initial_caller_stats = deepcopy(caller_mgr.stats) + initial_callee_stats = deepcopy(callee_mgr.stats) + identity = callee_mgr.identity.as_string_uri_only() + friend = caller_mgr.lc.create_friend_with_address(identity) + friend.edit() + friend.subscribes_enabled = True + friend.done() + caller_mgr.lc.add_friend(friend) + result = CoreManager.wait_for(caller_mgr, callee_mgr, + lambda caller_mgr, callee_mgr: caller_mgr.stats.number_of_LinphonePresenceActivityOnline == initial_caller_stats.number_of_LinphonePresenceActivityOnline + 1) + assert_equals(callee_mgr.stats.number_of_NewSubscriptionRequest, initial_callee_stats.number_of_NewSubscriptionRequest + 1) + assert_equals(caller_mgr.stats.number_of_NotifyReceived, initial_caller_stats.number_of_NotifyReceived + 1) + return result + + def test_simple_subscribe(self): + marie = PresenceCoreManager('marie', logger=TestPresence.logger) + pauline = PresenceCoreManager('pauline', logger=TestPresence.logger) + assert_equals(self.subscribe_to_callee_presence(marie, pauline), True) + marie.stop() + pauline.stop() diff --git a/tools/python/unittests/test_register.py b/tools/python/unittests/test_register.py new file mode 100644 index 000000000..2660fbf1c --- /dev/null +++ b/tools/python/unittests/test_register.py @@ -0,0 +1,87 @@ +from nose.tools import assert_equals +import linphone +from linphonetester import * +import os +import time + +class RegisterCoreManager(CoreManager): + + @classmethod + def auth_info_requested(cls, lc, realm, username, domain): + CoreManager.auth_info_requested(cls, lc, realm, username, domain) + info = linphone.AuthInfo.new(test_username, None, test_password, None, realm, domain) # Create authentication structure from identity + lc.add_auth_info(info) # Add authentication info to LinphoneCore + + def __init__(self, with_auth = False, logger = None): + vtable = {} + if with_auth: + vtable['auth_info_requested'] = RegisterCoreManager.auth_info_requested + CoreManager.__init__(self, vtable=vtable, logger=logger) + + def register_with_refresh(self, refresh, domain, route, late_auth_info = False, expected_final_state = linphone.RegistrationState.RegistrationOk): + assert self.lc is not None + self.stats.reset() + proxy_cfg = self.lc.create_proxy_config() + from_address = create_address(domain) + proxy_cfg.identity = from_address.as_string() + server_addr = from_address.domain + proxy_cfg.register_enabled = True + proxy_cfg.expires = 1 + if route is None: + proxy_cfg.server_addr = server_addr + else: + proxy_cfg.route = route + proxy_cfg.server_addr = route + self.lc.add_proxy_config(proxy_cfg) + self.lc.default_proxy_config = proxy_cfg + + #linphone_core_set_sip_transports(lc,&transport); + + retry = 0 + expected_count = 1 + if refresh: + expected_count += 1 + max_retry = 110 + if expected_final_state == linphone.RegistrationState.RegistrationProgress: + max_retry += 200 + while self.stats.number_of_LinphoneRegistrationOk < expected_count and retry < max_retry: + retry += 1 + self.lc.iterate() + if self.stats.number_of_auth_info_requested > 0 and proxy_cfg.state == linphone.RegistrationState.RegistrationFailed and late_auth_info: + if len(self.lc.auth_info_list) == 0: + assert_equals(proxy_cfg.error, linphone.Reason.ReasonUnauthorized) + info = linphone.AuthInfo.new(test_username, None, test_password, None, None, None) # Create authentication structure from identity + self.lc.add_auth_info(info) + if proxy_cfg.error == linphone.Reason.ReasonForbidden or \ + (self.stats.number_of_auth_info_requested > 2 and proxy_cfg.error == linphone.Reason.ReasonUnauthorized): + break + time.sleep(0.1) + + assert_equals(proxy_cfg.state, expected_final_state) + assert_equals(self.stats.number_of_LinphoneRegistrationNone, 0) + assert self.stats.number_of_LinphoneRegistrationProgress >= 1 + if expected_final_state == linphone.RegistrationState.RegistrationOk: + assert_equals(self.stats.number_of_LinphoneRegistrationOk, expected_count) + expected_failed = 0 + if late_auth_info: + expected_failed = 1 + assert_equals(self.stats.number_of_LinphoneRegistrationFailed, expected_failed) + else: + assert_equals(self.stats.number_of_LinphoneRegistrationCleared, 0) + + self.stop() + # Not testable as the callbacks can not be called once the core destruction has started + #assert_equals(self.stats.number_of_LinphoneRegistrationCleared, 1) + + +class TestRegister: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def test_simple_register(self): + cm = RegisterCoreManager(logger=TestRegister.logger) + cm.register_with_refresh(False, None, None) + assert_equals(cm.stats.number_of_auth_info_requested, 0) diff --git a/tools/python/unittests/test_setup.py b/tools/python/unittests/test_setup.py new file mode 100644 index 000000000..ff710217f --- /dev/null +++ b/tools/python/unittests/test_setup.py @@ -0,0 +1,44 @@ +from nose.tools import assert_equals +import linphone +from linphonetester import * +import os + +class TestSetup: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def test_address(self): + create_address(None) + + def test_core_init(self): + lc = linphone.Core.new({}, None, None) + assert lc is not None + if lc is not None: + lc.verify_server_certificates(False) + + def test_interpret_url(self): + lc = linphone.Core.new({}, None, None) + assert lc is not None + sips_address = "sips:margaux@sip.linphone.org" + address = lc.interpret_url(sips_address) + assert address is not None + assert_equals(address.scheme, "sips") + assert_equals(address.username, "margaux") + assert_equals(address.domain, "sip.linphone.org") + + def test_lpconfig_from_buffer(self): + buffer = "[buffer]\ntest=ok" + buffer_linebreaks = "[buffer_linebreaks]\n\n\n\r\n\n\r\ntest=ok" + conf = linphone.LpConfig.new_from_buffer(buffer) + assert_equals(conf.get_string("buffer", "test", ""), "ok") + conf = linphone.LpConfig.new_from_buffer(buffer_linebreaks) + assert_equals(conf.get_string("buffer_linebreaks", "test", ""), "ok") + + def test_create_chat_room(self): + lc = linphone.Core.new({}, None, None) + assert lc is not None + cr = lc.get_chat_room_from_uri("sip:toto@titi.com") + assert cr is not None diff --git a/tools/software-desc.hh b/tools/software-desc.hh index 2d454e502..575f52fb0 100644 --- a/tools/software-desc.hh +++ b/tools/software-desc.hh @@ -294,7 +294,7 @@ private: class ConstField{ public: - ConstField(Type *type, const string &name, const string &value="") : mType(type), mName(name), mValue(value){ + ConstField(Type *type, const string &name, int value) : mType(type), mName(name), mValue(value){ } void setHelp(const string & help){ mHelp=help; @@ -308,7 +308,7 @@ public: Type *getType()const{ return mType; } - const string &getValue()const{ + int getValue()const{ return mValue; } static string getCommonPrefix(list fields){ @@ -338,7 +338,7 @@ public: private: Type *mType; string mName; - string mValue; + int mValue; string mHelp; }; diff --git a/tools/xml2lpc_test.c b/tools/xml2lpc_test.c index e99b90bd8..3bb5dbc31 100644 --- a/tools/xml2lpc_test.c +++ b/tools/xml2lpc_test.c @@ -43,17 +43,18 @@ void cb_function(void *ctx, xml2lpc_log_level level, const char *msg, va_list li void show_usage(int argc, char *argv[]) { fprintf(stderr, "usage %s convert \n" - " %s validate \n", + " %s validate \n", argv[0], argv[0]); } int main(int argc, char *argv[]) { + xml2lpc_context *ctx; if(argc != 4) { show_usage(argc, argv); return -1; } - - xml2lpc_context *ctx = xml2lpc_context_new(cb_function, NULL); + + ctx = xml2lpc_context_new(cb_function, NULL); xml2lpc_set_xml_file(ctx, argv[2]); if(strcmp("convert", argv[1]) == 0) { LpConfig *lpc = lp_config_new(argv[3]);