diff --git a/.gitignore b/.gitignore index 38beb5d7dae69d41a269a0fed6c93a4e2bab2ff9..9b50f67f10d2b6e59dfb4137d2c73babf22fa0db 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ *.Po *.Plo *.loT -*.m4 *.Tpo Makefile.in Makefile @@ -70,5 +69,9 @@ config_auto.h # Ignore temp files *~ +# Cscope/Ctags files +cscope.* +tags + # IDE stuffs nbproject diff --git a/NEWS b/NEWS index 622094a882577ce32fd05b19b2b1b09cd445b5ae..4adde3113d40d901a089d9e33b99de72a3448133 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ # SFLphone ################################################ +* 2012-05-17: 1.1.0 has been released + * 2011-11-18: 1.0.1 has been released * 2011-09-30: 1.0.0 has been released diff --git a/daemon/.gitignore b/daemon/.gitignore index 01bcf84a048c656b051dc1a8621adf1c628b4b83..33f0a2cc742f82740882b07dbd8c45d49cc824f3 100644 --- a/daemon/.gitignore +++ b/daemon/.gitignore @@ -1,3 +1,4 @@ +aclocal.m4 src/dbus/org.sflphone.SFLphone.service src/sflphoned diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 32969d246508245256c70601794bd3d035720f7a..34aed6bc2a5dfdfcd419d2804e8225cdc4ec9c47 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -21,8 +21,7 @@ endif ACLOCAL_AMFLAGS = -I m4 SUBDIRS = libs src ringtones man $(TESTS_DIR) doc -EXTRA_DIST = README.gentoo \ - m4/libtool.m4 \ +EXTRA_DIST = m4/libtool.m4 \ m4/lt~obsolete.m4 \ m4/ltoptions.m4 \ m4/ltsugar.m4 \ diff --git a/daemon/README b/daemon/README index 27f0b8d8f9677de1859bbcf9c07ce4bad27af6b8..fd222d45b4cdaefe6bee49c8f283bb1b2be574a6 100644 --- a/daemon/README +++ b/daemon/README @@ -51,8 +51,6 @@ Short description of content of source tree ------------------------------------------- - ringtones/ contains the different ringtones. -- stund/ is an implementation of the protocol STUN used when there is a NAT. -- utilspp/ allows to implement a singleton. - src/ is the core of SFLphone. It contains the main.cpp, managerimpl.cpp files, audio and gui directories, and files about signalisation SIP. Later, it should be better, when IAX will be implemented, that a directory groups diff --git a/daemon/README.gentoo b/daemon/README.gentoo deleted file mode 100644 index c17db2a1f46bb519e1d3a5fc7888c3e775050838..0000000000000000000000000000000000000000 --- a/daemon/README.gentoo +++ /dev/null @@ -1,23 +0,0 @@ -emerge commoncpp2 -# editer /usr/lib/pkgconfig/libccext2.pc pour le includedir -> /usr/include/ -ACCEPT_KEYWORDS=~x86 emerge ccrtp -emerge libosip -ACCEPT_KEYWORDS=~x86 emerge libeXosip -emerge libsamplerate -emerge cvs -emerge =qt-3.3.6-r1 - -cvs ... - -cd tools/ -portaudio.sh -cd portaudio -make install -cd ../../ -./tools/autotoolize.sh -./configure --with-qtdir=/usr/qt/3 PKG_CONFIG_PATH=/usr/local/lib/pkgconfig -make -make install - -sflphone - diff --git a/daemon/autogen.sh b/daemon/autogen.sh index 50318d74f720c3a7d5f2d14153199cb8352930ed..1f296b7bc3ef71192961c83c602cab088ab125a5 100755 --- a/daemon/autogen.sh +++ b/daemon/autogen.sh @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash # Workaround for http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=565663 mkdir -p m4 @@ -7,11 +7,14 @@ HOOKS_DIR="../.git/hooks" # install pre-commit hook for doing clean commits if [ -d "$HOOKS_DIR" ]; then - if test ! \( -x ${HOOKS_DIR}/pre-commit -a -L ${HOOKS_DIR}/pre-commit \); + pushd ${HOOKS_DIR} + if test ! \( -x pre-commit -a -L pre-commit \); then - rm -f ${HOOKS_DIR}/pre-commit - ln -s ${HOOKS_DIR}/pre-commit.sample ${HOOKS_DIR}/pre-commit + echo "Creating symbolic link for pre-commit hook..." + rm -f pre-commit + ln -s pre-commit.sample pre-commit fi + popd fi autoreconf --force --install --verbose -Wall -I m4 diff --git a/daemon/configure.ac b/daemon/configure.ac index b0c4d019ac33306c52496abe1c1749398b92a89f..b46104dfeb37e34a8341fc8c4f21a87bb801d91b 100644 --- a/daemon/configure.ac +++ b/daemon/configure.ac @@ -2,14 +2,10 @@ dnl SFLPhone - configure.ac for automake 1.9 and autoconf 2.59 dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.65]) -AC_INIT([sflphone],[1.0.2],[sflphoneteam@savoirfairelinux.com],[sflphone]) +AC_INIT([sflphone],[1.1.0],[sflphoneteam@savoirfairelinux.com],[sflphone]) AC_COPYRIGHT([[Copyright (c) Savoir-Faire Linux 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012]]) AC_REVISION([$Revision$]) -AC_CANONICAL_BUILD -AC_CANONICAL_HOST -AC_CANONICAL_TARGET - AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([config.h]) @@ -22,28 +18,6 @@ AC_PROG_MAKE_SET dnl Where to find configure files AC_CONFIG_MACRO_DIR([m4]) -dnl What to generate -AC_CONFIG_FILES([Makefile]) -AC_CONFIG_FILES([libs/Makefile \ - libs/utilspp/Makefile \ - libs/utilspp/singleton/Makefile \ - libs/iax2/Makefile]) - -AC_CONFIG_FILES([src/Makefile \ - src/sip/Makefile \ - src/im/Makefile \ - src/iax/Makefile \ - src/audio/Makefile \ - src/audio/audiortp/Makefile \ - src/audio/pulseaudio/Makefile \ - src/audio/alsa/Makefile \ - src/audio/sound/Makefile \ - src/audio/codecs/Makefile \ - src/config/Makefile \ - src/dbus/Makefile \ - src/hooks/Makefile \ - src/history/Makefile]) - dnl Unit tests section AC_CONFIG_FILES([test/Makefile]) @@ -72,7 +46,8 @@ AC_FUNC_ALLOCA AC_HEADER_STDC AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h malloc.h memory.h \ netdb.h netinet/in.h stdlib.h string.h strings.h \ - sys/ioctl.h sys/socket.h sys/time.h unistd.h utime.h ostream]) + sys/ioctl.h sys/socket.h sys/time.h unistd.h utime.h \ + ostream getopt.h]) dnl Check for typedefs, structures, and compiler characteristics AC_HEADER_STAT @@ -96,24 +71,21 @@ AC_FUNC_MALLOC AC_FUNC_MEMCMP AC_FUNC_REALLOC AC_FUNC_SELECT_ARGTYPES - AC_DIAGNOSE([obsolete],[your code may safely assume C89 semantics that RETSIGTYPE is void. +AC_DIAGNOSE([obsolete],[your code may safely assume C89 semantics that RETSIGTYPE is void. Remove this warning and the `AC_CACHE_CHECK' when you adjust the code.])dnl AC_CACHE_CHECK([return type of signal handlers],[ac_cv_type_signal],[AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([#include <sys/types.h> #include <signal.h> ], - [return *(signal (0, 0)) (0) == 1;])], - [ac_cv_type_signal=int], - [ac_cv_type_signal=void])]) + [return *(signal (0, 0)) (0) == 1;])], + [ac_cv_type_signal=int], + [ac_cv_type_signal=void])]) AC_DEFINE_UNQUOTED([RETSIGTYPE],[$ac_cv_type_signal],[Define as the return type of signal handlers - (`int' or `void').]) + (`int' or `void').]) AC_FUNC_STAT AC_FUNC_UTIME_NULL AC_FUNC_VPRINTF -AC_CHECK_FUNCS([bzero floor gethostbyname gethrtime gettimeofday \ - inet_ntoa memset mkdir pathconf pow regcomp select setlocale \ - socket strchr strdup strerror strrchr strstr strtol utime]) dnl Check for GNU ccRTP PKG_PROG_PKG_CONFIG @@ -122,6 +94,9 @@ dnl Check for uuid development package - name: uuid-dev UUID_MIN_VERSION=1.0 PKG_CHECK_MODULES(UUID, uuid >= ${UUID_MIN_VERSION}, HAVE_UUID=true, HAVE_UUID=false); +AC_SEARCH_LIBS([yaml_parser_initialize], [yaml], [AC_SUBST(YAML_LIBS, -lyaml)], [ + AC_MSG_ERROR([Unable to find yaml development files])]) + LIBCRYPTO_MIN_VERSION=1.0 PKG_CHECK_MODULES(LIBCRYPTO, libcrypto >= ${LIBCRYPTO_MIN_VERSION}, HAVE_LIBCRYPTO=true, HAVE_LIBCRYPTO=false); @@ -138,13 +113,15 @@ LIBSAMPLERATE_MIN_VERSION=0.1.2 PKG_CHECK_MODULES(SAMPLERATE, samplerate >= ${LIBSAMPLERATE_MIN_VERSION},, AC_MSG_ERROR([Missing libsamplerate development package: libsamplerate0-dev])) LIBCCGNU2_MIN_VERSION=1.3.1 -PKG_CHECK_MODULES(CCGNU2, libccgnu2 >= ${LIBCCGNU2_MIN_VERSION},, AC_MSG_ERROR([Missing common cpp development package: libcommoncpp2-dev])) +PKG_CHECK_MODULES([CCGNU2], [commoncpp] >= ${LIBCCGNU2_MIN_VERSION}, AC_DEFINE_UNQUOTED([COMMONCPP_PREFIX], [1], [Use commoncpp include prefix]), [ + PKG_CHECK_MODULES([CCGNU2], [libccgnu2] >= ${LIBCCGNU2_MIN_VERSION}, AC_DEFINE_UNQUOTED([CCPP_PREFIX], [1], [Use cc++ include prefix]), + AC_MSG_ERROR([Missing common cpp development package: libcommoncpp2-dev])) + ]) -LIBCCEXT2_MIN_VERSION=1.3.1 -PKG_CHECK_MODULES(CCEXT2, libccext2 >= ${LIBCCEXT2_MIN_VERSION}) - -LIBCCRT_MIN_VERSION=1.3.0 -PKG_CHECK_MODULES(CCRTP, libccrtp1 >= ${LIBCCRT_MIN_VERSION},, AC_MSG_ERROR([Missing ccrtp development package: libccrtp-dev])) +LIBCCRTP_MIN_VERSION=1.3.0 +PKG_CHECK_MODULES([CCRTP], [libccrtp] >= ${LIBCCRTP_MIN_VERSION},, [ + PKG_CHECK_MODULES([CCRTP], [libccrtp1] >= ${LIBCCRTP_MIN_VERSION},, AC_MSG_ERROR([Missing ccrtp development package: libccrtp-dev])) + ]) dnl Check for OpenSSL to link against pjsip and provide SIPS TLS support PKG_CHECK_MODULES([libssl], libssl,, AC_MSG_ERROR([Missing ssl development package: libssl-dev])) @@ -158,119 +135,56 @@ dnl pkg-config doesn't like 0.6.0-pre1 version number, it assumes that it is dnl more recent than (unreleased) 0.6.0 DBUS_CPP_REQUIRED_VERSION=0.6.0-pre1 PKG_CHECK_MODULES(DBUSCPP, dbus-c++-1,, - AC_MSG_ERROR([You need the DBus-c++ libraries (version $DBUS_CPP_REQUIRED_VERSION or better)])) - -CXXFLAGS="${CXXFLAGS} -g -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -Weffc++ -Wfatal-errors" - -AC_CHECK_LIB([expat], XML_ParserCreate_MM, - [AC_CHECK_HEADERS(expat.h, have_expat=true, have_expat=false)], - have_expat=false) - -test "$have_expat" = false && AC_MSG_ERROR([libexpat development files missing]) - -xml_CFLAGS= -xml_LIBS=-lexpat - -AC_SUBST(xml_CFLAGS) -AC_SUBST(xml_LIBS) - -AC_CHECK_LIB([yaml], yaml_parser_initialize, - [AC_CHECK_HEADERS(yaml.h, have_yaml=true, have_yaml=false)], - have_yaml=false) +AC_MSG_ERROR([You need the DBus-c++ libraries (version $DBUS_CPP_REQUIRED_VERSION or better)])) -test "$have_yaml" = "false" && AC_MSG_ERROR([libyaml development files missing]) +AX_LIB_EXPAT -yaml_CFLAGS= -yaml_LIBS=-lyaml -AC_SUBST(yaml_CFLAGS) -AC_SUBST(yaml_LIBS) +AX_PTHREAD -AC_CHECK_LIB([pthread], pthread_create, - [AC_CHECK_HEADERS(pthread.h, have_pthread=true, have_pthread=false)], - have_pthread=false) - -test "$have_pthread" = "false" && AC_MSG_ERROR([You need the POSIX Thread library (pthreads)]) - -AC_CHECK_LIB([pcre], pcre_free, - [AC_CHECK_HEADERS(pcre.h, have_pcre=true, have_pcre=false)], - have_pcre=false) - -test "$have_pcre" = "false" && AC_MSG_ERROR([You need the Perl-Compatible Regular Expressions library (pcre)]) - -PCRE_LIBS=-lpcre -PCRE_CFLAGS= -AC_SUBST(PCRE_LIBS) -AC_SUBST(PCRE_CFLAGS) +AX_PATH_LIB_PCRE dnl Check for libcppunit-dev CPPUNIT_MIN_VERSION=1.12 PKG_CHECK_MODULES(CPPUNIT, cppunit >= ${CPPUNIT_MIN_VERSION}, AM_CONDITIONAL(BUILD_TEST, test 1 = 1 ), AM_CONDITIONAL(BUILD_TEST, test 0 = 1 )) -# check for libgsm1 (doesn't use pkg-config) - dnl Check for libgsm +dnl check for libgsm1 (doesn't use pkg-config) +dnl Check for libgsm AC_ARG_WITH([gsm], [AS_HELP_STRING([--without-gsm], - [disable support for gsm codec])], [], [with_gsm=yes]) + [disable support for gsm codec])], [], [with_gsm=yes]) LIBGSM= AS_IF([test "x$with_gsm" != xno], - [AC_CHECK_HEADER([gsm/gsm.h], , AC_MSG_FAILURE([Unable to find the libgsm1 headers (you may need to install the dev package). You may use --without-gsm to compile without gsm codec support.]))] - [AC_CHECK_LIB([gsm], [gsm_decode], - [], - [AC_MSG_FAILURE( - [libgsm link test failed. You may use --without-gsm to compile without gsm codec support.])] - ) - ] - ) + [AC_CHECK_HEADER([gsm/gsm.h], , AC_MSG_FAILURE([Unable to find the libgsm1 headers (you may need to install the dev package). You may use --without-gsm to compile without gsm codec support.]))] + [AC_CHECK_LIB([gsm], [gsm_decode], [], [ + AC_MSG_FAILURE([libgsm link test failed. You may use --without-gsm to compile without gsm codec support.]) + ]) + ]) AC_DEFINE_UNQUOTED([HAVE_GSM], `if test "x$with_gsm" = "xyes"; then echo 1; else echo 0; fi`, [Define if you have libgsm]) AM_CONDITIONAL(BUILD_GSM, test "x$with_gsm" = "xyes" ) dnl Check for libspeex AC_ARG_WITH([speex], - [AS_HELP_STRING([--without-speex], - [disable support for speex codec])], - [], - [with_speex=yes]) + [AS_HELP_STRING([--without-speex], + [disable support for speex codec])], + [], + [with_speex=yes]) AS_IF([test "x$with_speex" != xno], - [AC_CHECK_HEADER([speex/speex.h], , AC_MSG_FAILURE([Unable to find the libspeex headers (you may need to install the dev package). You may use --without-speex to compile without speex codec support.]))] - [AC_CHECK_LIB([speex], [speex_decode_int], - [], - [AC_MSG_FAILURE([libspeex link test failed. You may use --without-speex to compile without speex codec support.])]) - ]) - + [AC_CHECK_HEADER([speex/speex.h], , AC_MSG_FAILURE([Unable to find the libspeex headers (you may need to install the dev package). You may use --without-speex to compile without speex codec support.]))] + [AC_CHECK_LIB([speex], [speex_decode_int], + [], + [AC_MSG_FAILURE([libspeex link test failed. You may use --without-speex to compile without speex codec support.])]) + ]) + AC_DEFINE_UNQUOTED([HAVE_SPEEX], `if test "x$with_speex" = "xyes"; then echo 1; else echo 0; fi`, [Define if you have libspeex]) AM_CONDITIONAL(BUILD_SPEEX, test "x$with_speex" = "xyes" ) dnl check in case the libspeexdsp is not installed AC_CHECK_HEADER([speex/speex_preprocess.h], , AC_MSG_FAILURE([Unable to find the libspeexdsp headers (you may need to install the libspeexdsp-dev package) used for Noise Suppression and Automatic Gain Control.])) -AC_CHECK_LIB(speexdsp, speex_preprocess_run, [], [], []) - -# check for libcelt -AC_ARG_WITH([celt], - [AS_HELP_STRING([--without-celt], - [disable support for celt codec])], - [], - [with_celt=yes]) - -AS_IF([test "x$with_celt" != xno], - [PKG_CHECK_MODULES(CELT, celt >= 0.9.1, - [ - with_celt_91=yes; AC_MSG_NOTICE([Using celt 0.9.1]) - ], - [ - PKG_CHECK_MODULES(CELT, celt >= 0.7.1, - [ - with_celt_71=yes; AC_MSG_NOTICE([Using celt 0.7.1]) - ], - [ - AC_MSG_FAILURE([libcelt link test failed. You may use --without-celt to compile without celt codec support.]) - ]) - ])] -) - -AM_CONDITIONAL(BUILD_CELT_91, test "x$with_celt_91" = "xyes" ) -AM_CONDITIONAL(BUILD_CELT_71, test "x$with_celt_71" = "xyes" ) +AC_SEARCH_LIBS([speex_preprocess_run], [speexdsp], [], [ + AC_MSG_ERROR([Unable to find speexdsp development files]) +]) dnl Check for IAX AC_ARG_WITH([iax2], [AS_HELP_STRING([--without-iax2], @@ -279,9 +193,9 @@ AC_ARG_WITH([iax2], [AS_HELP_STRING([--without-iax2], AC_DEFINE_UNQUOTED([HAVE_IAX], `if test "x$with_iax2" = "xyes"; then echo 1; else echo 0;fi`, [Define if you have libiax2]) AM_CONDITIONAL(USE_IAX, test "x$with_iax2" = "xyes" ) - dnl Check for network-manager + dnl Check for network-manager AC_ARG_WITH([networkmanager], [AS_HELP_STRING([--without-networkmanager], - [disable support for network-manager events])], [], + [disable support for network-manager events])], [], [with_networkmanager=yes]) AM_CONDITIONAL(USE_NETWORKMANAGER, test "x$with_networkmanager" = "xyes" ) @@ -298,11 +212,34 @@ AC_DEFUN([BB_ENABLE_DOXYGEN], AC_PATH_PROG(DOT, dot, , $PATH) test x$DOT = x -a "x$enable_dot" = xyes && AC_MSG_ERROR([could not find dot]) fi - AM_CONDITIONAL(ENABLE_DOXYGEN, test x$DOXYGEN = xyes) + AM_CONDITIONAL(ENABLE_DOXYGEN, test x$DOXYGEN = xyes) ]) # Acutally perform the doxygen check BB_ENABLE_DOXYGEN +CXXFLAGS="${CXXFLAGS} -g -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -Weffc++ -Wfatal-errors" + +dnl What to generate +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([libs/Makefile \ + libs/iax2/Makefile]) + +AC_CONFIG_FILES([src/Makefile \ + src/sip/Makefile \ + src/im/Makefile \ + src/iax/Makefile \ + src/audio/Makefile \ + src/audio/audiortp/Makefile \ + src/audio/pulseaudio/Makefile \ + src/audio/alsa/Makefile \ + src/audio/sound/Makefile \ + src/audio/codecs/Makefile \ + src/config/Makefile \ + src/dbus/Makefile \ + src/hooks/Makefile \ + src/history/Makefile]) + + # Go! AC_OUTPUT diff --git a/daemon/doc/doxygen/core-doc.cfg.in b/daemon/doc/doxygen/core-doc.cfg.in index 6c2f2d07c6925f53b36bb1b7880b402b614aa8ab..39c7185923c3de1635b203ec3afe0cdb88cbe7e9 100644 --- a/daemon/doc/doxygen/core-doc.cfg.in +++ b/daemon/doc/doxygen/core-doc.cfg.in @@ -1,231 +1,1716 @@ -# Doxyfile 1.5.3 +# Doxyfile 1.7.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = SFLphone Core -PROJECT_NUMBER = + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "SFLphone Daemon" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1.1.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + DISTRIBUTE_GROUP_DOC = YES + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + SHOW_INCLUDE_FILES = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + SORT_BRIEF_DOCS = YES + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + WARN_FORMAT = + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + WARN_LOGFILE = + #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = @-top_srcdir-@/src @-top_srcdir-@/src/audio @-top_srcdir-@/src/audio/codecs @-top_srcdir-@/src/dbus @-top_srcdir-@/src/config @-top_srcdir-@/src/zeroconf + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../../src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + INPUT_ENCODING = UTF-8 -FILE_PATTERNS = -RECURSIVE = NO -EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.cpp *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = libs/pjproject + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + VERBATIM_HEADERS = YES + #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + IGNORE_PREFIX = + #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + HTML_OUTPUT = @-html_dir-@ + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + HTML_FILE_EXTENSION = -HTML_HEADER = @-html_header-@ -HTML_FOOTER = @-html_footer-@ + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is adviced to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + DISABLE_INDEX = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + GENERATE_TREEVIEW = YES + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + LATEX_OUTPUT = + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + LATEX_CMD_NAME = + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + MAKEINDEX_CMD_NAME = + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + RTF_OUTPUT = + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + RTF_EXTENSIONS_FILE = + #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + MAN_EXTENSION = + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + MAN_LINKS = NO + #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + XML_PROGRAMLISTING = YES + #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + GENERATE_AUTOGEN_DEF = NO + #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + PERLMOD_MAKEVAR_PREFIX = + #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + SKIP_FUNCTION_MACROS = YES + #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + PERL_PATH = + #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. + DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/daemon/globals.mak b/daemon/globals.mak index a6c10a05f5df299160f9d3d18e99f17969e92bc0..c998688ca12182e1738d4011a1bdcaf7382fcf30 100644 --- a/daemon/globals.mak +++ b/daemon/globals.mak @@ -11,20 +11,8 @@ ASTYLERC="$(top_srcdir)/../astylerc" indent="/usr/bin/astyle" # for pjsip -PJSIP_LIBS= \ - -L$(src)/libs/pjproject/pjnath/lib/ \ - -L$(src)/libs/pjproject/pjsip/lib/ \ - -L$(src)/libs/pjproject/pjlib/lib/ \ - -L$(src)/libs/pjproject/pjlib-util/lib/ \ - -L$(src)/libs/pjproject/pjmedia/lib/ \ - -lpjnath-$(target) \ - -lpjsua-$(target) \ - -lpjsip-$(target) \ - -lpjmedia-$(target) \ - -lpjsip-simple-$(target) \ - -lpjsip-ua-$(target) \ - -lpjlib-util-$(target) \ - -lpj-$(target) +include $(src)/libs/pjproject/build.mak +PJSIP_LIBS=$(APP_LDFLAGS) $(APP_LDLIBS) SIP_CFLAGS=-I$(src)/libs/pjproject/pjsip/include \ -I$(src)/libs/pjproject/pjlib/include \ diff --git a/daemon/libs/Makefile.am b/daemon/libs/Makefile.am index da08ea625d6194b4d887ad36554994d3917bad7d..105bcd0231a42a82de43d0f493962f5c01bef334 100644 --- a/daemon/libs/Makefile.am +++ b/daemon/libs/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = utilspp iax2 +SUBDIRS = iax2 EXTRA_DIST=pjproject diff --git a/daemon/libs/pjproject/config.guess b/daemon/libs/pjproject/config.guess index dff9e481b70f9505b49ce999629a168a19976f4f..d622a44e551f209d5e8c5462b3fe53a162f7b330 100755 --- a/daemon/libs/pjproject/config.guess +++ b/daemon/libs/pjproject/config.guess @@ -1,9 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. -timestamp='2001-09-04' +timestamp='2012-02-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -16,23 +17,24 @@ timestamp='2001-09-04' # General Public License for more details. # # You 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. +# along with this program; if not, see <http://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. -# Written by Per Bothner <bothner@cygnus.com>. -# Please send patches to <config-patches@gnu.org>. + +# Originally written by Per Bothner. Please send patches (context +# diff format) to <config-patches@gnu.org> and include a ChangeLog +# entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` @@ -52,7 +54,8 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -65,11 +68,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -87,30 +90,42 @@ if test $# != 0; then exit 1 fi +trap 'exit 1' 1 2 15 -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. -# CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. -set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c ; - for c in cc gcc c89 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; - if test $? = 0 ; then +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; - rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac' +esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -127,32 +142,34 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-unknown ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. - case "${UNAME_MACHINE}" in - i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -162,124 +179,135 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd ;; esac # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" - exit 0 ;; + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then + case $UNAME_RELEASE in + *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - cat <<EOF >$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - 2-1307) - UNAME_MACHINE="alphaev68" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix - exit 0 ;; + exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 - exit 0 ;; + exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 - exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; *:OS/390:*:*) echo i370-ibm-openedition - exit 0 ;; + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp - exit 0;; + exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then @@ -287,25 +315,51 @@ EOF else echo pyramid-pyramid-bsd fi - exit 0 ;; + exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 - exit 0 ;; + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) @@ -314,12 +368,12 @@ EOF esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; + exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; + exit ;; sun*:*:4.2BSD:*) - UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) @@ -329,16 +383,10 @@ EOF echo sparc-sun-sunos${UNAME_RELEASE} ;; esac - exit 0 ;; + exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - sparc*:NetBSD:*) - echo `uname -p`-unknown-netbsd${UNAME_RELEASE} - exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -348,50 +396,41 @@ EOF # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; + exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 - exit 0 ;; + exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; + exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c @@ -415,30 +454,36 @@ EOF exit (-1); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; + exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax - exit 0 ;; + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix - exit 0 ;; + exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 - exit 0 ;; + exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 - exit 0 ;; + exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ @@ -451,29 +496,29 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit 0 ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 - exit 0 ;; + exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 - exit 0 ;; + exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd - exit 0 ;; + exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; + exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix - exit 0 ;; + exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` @@ -481,7 +526,7 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build @@ -496,17 +541,20 @@ EOF exit(0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else @@ -518,96 +566,114 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:*:*) echo rs6000-ibm-aix - exit 0 ;; + exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 - exit 0 ;; + exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 + exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx - exit 0 ;; + exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 - exit 0 ;; + exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd - exit 0 ;; + exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 - exit 0 ;; + exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) - case "${HPUX_REV}" in - 11.[0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - esac ;; - esac - fi ;; - esac - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c - #define _HPUX_SOURCE - #include <stdlib.h> - #include <unistd.h> + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy - fi ;; + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c @@ -635,158 +701,173 @@ EOF exit (0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 - exit 0 ;; + exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd - exit 0 ;; + exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd - exit 0 ;; + exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix - exit 0 ;; + exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf - exit 0 ;; + exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf - exit 0 ;; + exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi - exit 0 ;; + exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites - exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; + exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit 0 ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit 0 ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit 0 ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) + exit ;; + *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; + echo i586-pc-interix + exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin - exit 0 ;; + exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; *:GNU:*:*) + # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) + exit ;; + aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux - exit 0 ;; - m68*:Linux:*:*) + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in - big) echo mips-unknown-linux-gnu && exit 0 ;; - little) echo mipsel-unknown-linux-gnu && exit 0 ;; - esac - ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit 0 ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit 0 ;; + exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -796,11 +877,90 @@ EOF EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in @@ -808,92 +968,71 @@ EOF PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_supported_targets=`cd /; ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - cat >$dummy.c <<EOF -#include <features.h> -#ifdef __cplusplus -#include <stdio.h> /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-pc-linux-gnu\n", argv[1]); -# else - printf ("%s-pc-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-pc-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-pc-linux-gnuaout\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 - exit 0 ;; + exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. + # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then @@ -901,99 +1040,113 @@ EOF else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi - exit 0 ;; - i*86:*:5:[78]*) + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; + exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` echo ${UNAME_MACHINE}-pc-isc$UNAME_REL elif /bin/uname -X 2>/dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; + exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 - exit 0 ;; + exit ;; paragon:*:*:*) echo i860-intel-osf1 - exit 0 ;; + exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi - exit 0 ;; + exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; + exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` @@ -1001,82 +1154,123 @@ EOF else echo ns32k-sni-sysv fi - exit 0 ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says <Richard.M.Bartel@ccMail.Census.GOV> - echo i586-unisys-sysv4 - exit 0 ;; + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes <hewes@openmarket.com>. # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 - exit 0 ;; + exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 - exit 0 ;; + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos - exit 0 ;; + exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; + exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 - exit 0 ;; + exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit 0 ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos - exit 0 ;; + exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos - exit 0 ;; + exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos - exit 0 ;; + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx - exit 0 ;; + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; *:QNX:*:4*) echo i386-pc-qnx - exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux - exit 0 ;; + exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv - exit 0 ;; + exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 @@ -1087,36 +1281,53 @@ EOF UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; + exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 - exit 0 ;; + exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex - exit 0 ;; + exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 - exit 0 ;; + exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 - exit 0 ;; + exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 - exit 0 ;; + exit ;; *:ITS:*:*) echo pdp10-unknown-its - exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit 0 ;; + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1139,16 +1350,16 @@ main () #include <sys/param.h> printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); + printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) @@ -1237,12 +1448,12 @@ main () } EOF -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) @@ -1251,22 +1462,22 @@ then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd - exit 0 ;; + exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; c34*) echo c34-convex-bsd - exit 0 ;; + exit ;; c38*) echo c38-convex-bsd - exit 0 ;; + exit ;; c4*) echo c4-convex-bsd - exit 0 ;; + exit ;; esac fi @@ -1277,7 +1488,9 @@ This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from - ftp://ftp.gnu.org/pub/gnu/config/ + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD If the version you run ($0) is already up to date, please send the following data and any information you think might be diff --git a/daemon/libs/pjproject/config.sub b/daemon/libs/pjproject/config.sub index 746ee208a175a4f263cc9a186f5dc8f420524274..c894da45500c4af1bf5688e713a8895622d18182 100755 --- a/daemon/libs/pjproject/config.sub +++ b/daemon/libs/pjproject/config.sub @@ -1,9 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. -timestamp='2005-04-22' +timestamp='2012-02-10' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -20,23 +21,25 @@ timestamp='2005-04-22' # GNU General Public License for more details. # # You 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. - +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. + # Please send patches to <config-patches@gnu.org>. Submit a context -# diff and a properly formatted ChangeLog entry. +# diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -70,7 +73,8 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -83,11 +87,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -99,7 +103,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. echo $1 - exit 0;; + exit ;; * ) break ;; @@ -118,11 +122,18 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ - kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] @@ -145,10 +156,13 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) + -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -163,13 +177,17 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -186,6 +204,10 @@ case $os in # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -227,26 +249,36 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ + | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ + | epiphany \ + | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ - | mips64vr | mips64vrel \ + | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ @@ -255,31 +287,65 @@ case $basic_machine in | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | moxie \ + | mt \ | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ | ns16k | ns32k \ - | openrisc | or32 \ + | open8 \ + | or32 \ | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ - | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b \ - | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ - | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and @@ -295,32 +361,40 @@ case $basic_machine in # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ + | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ - | m32r-* | m32rle-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ + | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ @@ -329,27 +403,38 @@ case $basic_machine in | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ + | mt-* \ | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ | tron-* \ - | v850-* | v850e-* | vax-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ | ymp-* \ - | z8k-*) + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -367,7 +452,7 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; - abacus) + abacus) basic_machine=abacus-unknown ;; adobe68k) @@ -413,6 +498,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; aux) basic_machine=m68k-apple os=-aux @@ -421,10 +510,35 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; c90) basic_machine=c90-cray os=-unicos ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -453,8 +567,8 @@ case $basic_machine in basic_machine=craynv-cray os=-unicosmp ;; - cr16c) - basic_machine=cr16c-unknown + cr16 | cr16-*) + basic_machine=cr16-unknown os=-elf ;; crds | unos) @@ -492,6 +606,10 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp @@ -607,7 +725,6 @@ case $basic_machine in i370-ibm* | ibm*) basic_machine=i370-ibm ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 @@ -646,6 +763,14 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -657,10 +782,17 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze) + basic_machine=microblaze-xilinx + ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -686,10 +818,21 @@ case $basic_machine in basic_machine=i386-pc os=-msdos ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -754,6 +897,12 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -761,9 +910,8 @@ case $basic_machine in basic_machine=hppa1.1-oki os=-proelf ;; - or32 | or32-*) + openrisc | openrisc-*) basic_machine=or32-unknown - os=-coff ;; os400) basic_machine=powerpc-ibm @@ -785,6 +933,14 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; @@ -794,6 +950,12 @@ case $basic_machine in pc532 | pc532-*) basic_machine=ns32k-pc532 ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; @@ -823,9 +985,10 @@ case $basic_machine in ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown + ppc | ppcbe) basic_machine=powerpc-unknown ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown @@ -850,6 +1013,10 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; rom68k) basic_machine=m68k-rom68k os=-coff @@ -876,6 +1043,10 @@ case $basic_machine in sb1el) basic_machine=mipsisa64sb1el-unknown ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; sei) basic_machine=mips-sei os=-seiux @@ -887,6 +1058,9 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; + sh5el) + basic_machine=sh5le-unknown + ;; sh64) basic_machine=sh64-unknown ;; @@ -908,6 +1082,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -964,17 +1141,9 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown @@ -1043,6 +1212,9 @@ case $basic_machine in xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; ymp) basic_machine=ymp-cray os=-unicos @@ -1051,6 +1223,10 @@ case $basic_machine in basic_machine=z8k-unknown os=-sim ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -1089,13 +1265,10 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) @@ -1113,9 +1286,6 @@ case $basic_machine in pmac | pmac-mpw) basic_machine=powerpc-apple ;; - nios2*) - basic_machine=nios2-altera - ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; @@ -1142,9 +1312,12 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; @@ -1165,26 +1338,31 @@ case $os in # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1202,7 +1380,7 @@ case $os in os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) @@ -1223,7 +1401,7 @@ case $os in -opened*) os=-openedition ;; - -os400*) + -os400*) os=-os400 ;; -wince*) @@ -1272,7 +1450,7 @@ case $os in -sinix*) os=-sysv4 ;; - -tpf*) + -tpf*) os=-tpf ;; -triton*) @@ -1314,6 +1492,11 @@ case $os in -zvmoe) os=-zvmoe ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; -none) ;; *) @@ -1336,6 +1519,12 @@ else # system, and we'll never get to this point. case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; *-acorn) os=-riscix1.2 ;; @@ -1345,9 +1534,18 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff - ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 @@ -1366,13 +1564,13 @@ case $basic_machine in ;; m68000-sun) os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 ;; m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; @@ -1391,10 +1589,13 @@ case $basic_machine in *-be) os=-beos ;; + *-haiku) + os=-haiku + ;; *-ibm) os=-aix ;; - *-knuth) + *-knuth) os=-mmixware ;; *-wec) @@ -1499,7 +1700,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) @@ -1562,7 +1763,7 @@ case $basic_machine in esac echo $basic_machine$os -exit 0 +exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) diff --git a/daemon/libs/utilspp/Makefile.am b/daemon/libs/utilspp/Makefile.am deleted file mode 100644 index 403b7fc158899e61b14337c92505efb4f8e6b2ba..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -SUBDIRS = singleton - -noinst_LTLIBRARIES = libutilspp.la - -libutilspp_la_SOURCES = \ - null_type.hpp \ - singleton.hpp \ - threading_single.hpp threading_single.inl - -libutilspp_la_LIBADD = ./singleton/libsingleton.la diff --git a/daemon/libs/utilspp/null_type.hpp b/daemon/libs/utilspp/null_type.hpp deleted file mode 100644 index 0ba1208ad44028f147ecbbd0840d299771d7e88a..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/null_type.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef UTILSPP_NULLTYPE_HPP -#define UTILSPP_NULLTYPE_HPP - -namespace utilspp -{ - struct NullType; -} - -#endif diff --git a/daemon/libs/utilspp/singleton.hpp b/daemon/libs/utilspp/singleton.hpp deleted file mode 100644 index 649394f938addcb72c6cb317953dd20b4cf6c3a8..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/singleton.hpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "threading_single.hpp" -#include "singleton/singleton_holder.hpp" diff --git a/daemon/libs/utilspp/singleton/Makefile.am b/daemon/libs/utilspp/singleton/Makefile.am deleted file mode 100644 index d494c4c5e8f963fd9a25b28abd8e576bbb0e78d9..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/singleton/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -noinst_LTLIBRARIES = libsingleton.la - -libsingleton_la_SOURCES = \ - creation_using_new.hpp creation_using_new.inl \ - lifetime_default.hpp lifetime_default.inl \ - singleton_holder.hpp singleton_holder.inl diff --git a/daemon/libs/utilspp/singleton/creation_using_new.hpp b/daemon/libs/utilspp/singleton/creation_using_new.hpp deleted file mode 100644 index fe94f128528572979518adbf753436e8338a2b83..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/singleton/creation_using_new.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __CREATION_USING_NEW_HPP__ -#define __CREATION_USING_NEW_HPP__ - -/** - * This class is a creation policy for the utilspp::singleton_holder. The - * policy is creating the singleton by a "new" call. - */ -namespace utilspp -{ - template< typename T > - struct CreationUsingNew - { - static T *create(); - static void destroy( T *obj ); - }; -} - -#include "creation_using_new.inl" -#endif // __CREATION_USING_NEW_HPP__ diff --git a/daemon/libs/utilspp/singleton/creation_using_new.inl b/daemon/libs/utilspp/singleton/creation_using_new.inl deleted file mode 100644 index 5c9ae88eb8d07084494879f7849ef0d994015f78..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/singleton/creation_using_new.inl +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef CREATION_USING_NEW_INL -#define CREATION_USING_NEW_INL - -template< typename T > -T * -utilspp::CreationUsingNew< T >::create() -{ - return new T; -} - -template< typename T > -void -utilspp::CreationUsingNew< T >::destroy( T *obj ) -{ - delete obj; -} - - -#endif diff --git a/daemon/libs/utilspp/singleton/lifetime_default.hpp b/daemon/libs/utilspp/singleton/lifetime_default.hpp deleted file mode 100644 index ba0208c0a2fbf4e5a7fcb0c5ce10fe7873140078..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/singleton/lifetime_default.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef LIFETIME_DEFAULT_HPP -#define LIFETIME_DEFAULT_HPP - -namespace utilspp -{ - template< typename T > - class LifetimeDefault - { - public: - static void scheduleDestruction( T *obj, void (*func)() ); - static void onDeadReference(); - }; -} - -#include "lifetime_default.inl" - -#endif diff --git a/daemon/libs/utilspp/singleton/lifetime_default.inl b/daemon/libs/utilspp/singleton/lifetime_default.inl deleted file mode 100644 index 6760ececcd6d07376fc9b33df7556d1b4d092063..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/singleton/lifetime_default.inl +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __LIFETIME_DEFAULT_INL__ -#define __LIFETIME_DEFAULT_INL__ - -#include <cstdlib> -#include <stdexcept> - -template< typename T > -void -utilspp::LifetimeDefault< T >::scheduleDestruction( T *, void (*func)() ) -{ - std::atexit(func); -} - -template< typename T > -void -utilspp::LifetimeDefault< T >::onDeadReference() -{ - throw std::logic_error("Dead reference detected"); -} - -#endif // __LIFETIME_DEFAULT_INL__ diff --git a/daemon/libs/utilspp/singleton/singleton_holder.hpp b/daemon/libs/utilspp/singleton/singleton_holder.hpp deleted file mode 100644 index 6b0fcf47b1503620c1f12c59fc256ff065e2c83d..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/singleton/singleton_holder.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __SINGLETON_HOLDER_HPP__ -#define __SINGLETON_HOLDER_HPP__ - -#include "creation_using_new.hpp" -#include "lifetime_default.hpp" -#include "../threading_single.hpp" - -namespace utilspp -{ - template - < class T, - template < class > class CreationPolicy = utilspp::CreationUsingNew, - template < class > class LifetimePolicy = utilspp::LifetimeDefault, - template < class > class ThreadingModel = utilspp::ThreadingSingle > - class SingletonHolder - { - public: - //the accessor method. - static T& instance(); - static void makeInstance(); - static void terminate(); - - protected: - //protected to be sure that nobody may create one by himself. - SingletonHolder(); - - private: - static void destroySingleton(); - - private: - typedef typename ThreadingModel< T * >::VolatileType InstanceType; - static InstanceType mInstance; - static bool mDestroyed; - }; - -} - -#include "singleton_holder.inl" - -#endif diff --git a/daemon/libs/utilspp/singleton/singleton_holder.inl b/daemon/libs/utilspp/singleton/singleton_holder.inl deleted file mode 100644 index 5fb9fab7f480e13a2243d95f572e77a9d93fa0c0..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/singleton/singleton_holder.inl +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __SINGLETON_HOLDER_INL__ -#define __SINGLETON_HOLDER_INL__ - -#include <cassert> -template -< -class T, -template < class > class CreationPolicy, -template < class > class LifetimePolicy, -template < class > class ThreadingModel -> -T& -utilspp::SingletonHolder -< -T, -CreationPolicy, -LifetimePolicy, -ThreadingModel -> -::instance() -{ - if ( mInstance == NULL ) - { - makeInstance(); - } - - return ( *mInstance ); -} - -template -< -class T, -template < class > class CreationPolicy, -template < class > class LifetimePolicy, -template < class > class ThreadingModel -> -void -utilspp::SingletonHolder -< -T, -CreationPolicy, -LifetimePolicy, -ThreadingModel ->::makeInstance() -{ - if ( mInstance == NULL ) - { - typename ThreadingModel< T >::lock guard; - (void)guard; - - if ( mInstance == NULL ) { - if ( mDestroyed ) - { - LifetimePolicy< T >::onDeadReference(); - mDestroyed = false; - } - - mInstance = CreationPolicy< T >::create(); - LifetimePolicy< T >::scheduleDestruction( mInstance, &destroySingleton ); - } - } -} - -template -< -class T, -template < class > class CreationPolicy, -template < class > class LifetimePolicy, -template < class > class ThreadingModel -> -void -utilspp::SingletonHolder -< -T, -CreationPolicy, -LifetimePolicy, -ThreadingModel -> -::destroySingleton() -{ - assert( !mDestroyed ); - CreationPolicy< T >::destroy( mInstance ); - mInstance = NULL; - mDestroyed = true; -} - -template < class T, -template < class > class C, -template < class > class L, -template < class > class M -> -typename utilspp::SingletonHolder< T, C, L, M>::InstanceType -utilspp::SingletonHolder< T, C, L, M >::mInstance; - -template -< -class T, -template < class > class C, -template < class > class L, -template < class > class M -> -bool utilspp::SingletonHolder< T, C, L, M >::mDestroyed; - -#endif // __SINGLETON_HOLDER_INL__ diff --git a/daemon/libs/utilspp/threading_single.hpp b/daemon/libs/utilspp/threading_single.hpp deleted file mode 100644 index 81c023402c5dd18dc9e107b48653ee33df80dbcd..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/threading_single.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __THREADING_SINGLE_HPP__ -#define __THREADING_SINGLE_HPP__ - -#include "null_type.hpp" - -namespace utilspp -{ - template < typename T = utilspp::NullType > - struct ThreadingSingle - { - struct mutex - { - void lock(); - void unlock(); - }; - - struct lock - { - lock(); - lock( mutex &m ); - }; - - typedef T VolatileType; - }; -} - -#include "threading_single.inl" - -#endif // __THREADING_SINGLE_HPP__ diff --git a/daemon/libs/utilspp/threading_single.inl b/daemon/libs/utilspp/threading_single.inl deleted file mode 100644 index 4d26c4ff1dab7593a37761e024d7537d3857e99a..0000000000000000000000000000000000000000 --- a/daemon/libs/utilspp/threading_single.inl +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (cURLpp), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __THREADING_SINGLE_INL__ -#define __THREADING_SINGLE_INL__ - -template< typename T > -inline -utilspp::ThreadingSingle< T >::lock::lock() -{} - -template< typename T > -inline -utilspp::ThreadingSingle< T >::lock::lock( - utilspp::ThreadingSingle< T >::mutex & ) -{} - -template< typename T > -inline -void -utilspp::ThreadingSingle< T >::mutex::lock() -{} - -template< typename T > -inline -void -utilspp::ThreadingSingle< T >::mutex::unlock() -{} - -#endif // __THREADING_SINGLE_INL__ diff --git a/daemon/m4/.gitignore b/daemon/m4/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..464ba5caa6814008d91053646b3d634a4323f2e9 --- /dev/null +++ b/daemon/m4/.gitignore @@ -0,0 +1,5 @@ +libtool.m4 +lt~obsolete.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 diff --git a/daemon/m4/ax_lib_expat.m4 b/daemon/m4/ax_lib_expat.m4 new file mode 100644 index 0000000000000000000000000000000000000000..16e66de5d79b39884772eafaa66266ea267e7ee2 --- /dev/null +++ b/daemon/m4/ax_lib_expat.m4 @@ -0,0 +1,275 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_lib_expat.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_LIB_EXPAT([MINIMUM-VERSION]) +# +# DESCRIPTION +# +# This macro provides tests of availability of Expat XML Parser of +# particular version or newer. This macro checks for Expat XML Parser +# headers and libraries and defines compilation flags +# +# Macro supports following options and their values: +# +# 1) Single-option usage: +# +# --with-expat -- yes, no, or path to Expat XML Parser +# installation prefix +# +# 2) Three-options usage (all options are required): +# +# --with-expat=yes +# --with-expat-inc -- path to base directory with Expat headers +# --with-expat-lib -- linker flags for Expat +# +# This macro calls: +# +# AC_SUBST(EXPAT_CFLAGS) +# AC_SUBST(EXPAT_LIBS) +# AC_SUBST(EXPAT_VERSION) -- only if version requirement is used +# +# And sets: +# +# HAVE_EXPAT +# +# LICENSE +# +# Copyright (c) 2008 Mateusz Loskot <mateusz@loskot.net> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 9 + +AC_DEFUN([AX_LIB_EXPAT], +[ + AC_ARG_WITH([expat], + AS_HELP_STRING([--with-expat=@<:@ARG@:>@], + [use Expat XML Parser from given prefix (ARG=path); check standard prefixes (ARG=yes); disable (ARG=no)] + ), + [ + if test "$withval" = "yes"; then + if test -f /usr/local/include/expat.h ; then + expat_prefix=/usr/local + elif test -f /usr/include/expat.h ; then + expat_prefix=/usr + else + expat_prefix="" + fi + expat_requested="yes" + elif test -d "$withval"; then + expat_prefix="$withval" + expat_requested="yes" + else + expat_prefix="" + expat_requested="no" + fi + ], + [ + dnl Default behavior is implicit yes + if test -f /usr/local/include/expat.h ; then + expat_prefix=/usr/local + elif test -f /usr/include/expat.h ; then + expat_prefix=/usr + else + expat_prefix="" + fi + ] + ) + + AC_ARG_WITH([expat-inc], + AS_HELP_STRING([--with-expat-inc=@<:@DIR@:>@], + [path to Expat XML Parser headers] + ), + [expat_include_dir="$withval"], + [expat_include_dir=""] + ) + AC_ARG_WITH([expat-lib], + AS_HELP_STRING([--with-expat-lib=@<:@ARG@:>@], + [link options for Expat XML Parser libraries] + ), + [expat_lib_flags="$withval"], + [expat_lib_flags=""] + ) + + EXPAT_CFLAGS="" + EXPAT_LIBS="" + EXPAT_VERSION="" + + dnl + dnl Collect include/lib paths and flags + dnl + run_expat_test="no" + + if test -n "$expat_prefix"; then + expat_include_dir="$expat_prefix/include" + expat_lib_flags="-L$expat_prefix/lib -lexpat" + run_expat_test="yes" + elif test "$expat_requested" = "yes"; then + if test -n "$expat_include_dir" -a -n "$expat_lib_flags"; then + run_expat_test="yes" + fi + else + run_expat_test="no" + fi + + dnl + dnl Check Expat XML Parser files + dnl + if test "$run_expat_test" = "yes"; then + + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I$expat_include_dir" + + saved_LDFLAGS="$LDFLAGS" + LIBS="$LDFLAGS $expat_lib_flags" + + dnl + dnl Check Expat headers + dnl + AC_MSG_CHECKING([for Expat XML Parser headers in $expat_include_dir]) + + AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [[ +@%:@include <expat.h> + ]], + [[]] + )], + [ + EXPAT_CFLAGS="-I$expat_include_dir" + expat_header_found="yes" + AC_MSG_RESULT([found]) + ], + [ + expat_header_found="no" + AC_MSG_RESULT([not found]) + ] + ) + AC_LANG_POP([C++]) + + dnl + dnl Check Expat libraries + dnl + if test "$expat_header_found" = "yes"; then + + AC_MSG_CHECKING([for Expat XML Parser libraries]) + + AC_LANG_PUSH([C++]) + AC_LINK_IFELSE([ + AC_LANG_PROGRAM( + [[ +@%:@include <expat.h> + ]], + [[ +XML_Parser p = XML_ParserCreate(NULL); +XML_ParserFree(p); +p = NULL; + ]] + )], + [ + EXPAT_LIBS="$expat_lib_flags" + expat_lib_found="yes" + AC_MSG_RESULT([found]) + ], + [ + expat_lib_found="no" + AC_MSG_RESULT([not found]) + ] + ) + AC_LANG_POP([C++]) + fi + + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + + AC_MSG_CHECKING([for Expat XML Parser]) + + if test "$run_expat_test" = "yes"; then + if test "$expat_header_found" = "yes" -a "$expat_lib_found" = "yes"; then + + AC_SUBST([EXPAT_CFLAGS]) + AC_SUBST([EXPAT_LIBS]) + + HAVE_EXPAT="yes" + else + HAVE_EXPAT="no" + fi + + AC_MSG_RESULT([$HAVE_EXPAT]) + + dnl + dnl Check Expat version + dnl + if test "$HAVE_EXPAT" = "yes"; then + + expat_version_req=ifelse([$1], [], [], [$1]) + + if test -n "$expat_version_req"; then + + AC_MSG_CHECKING([if Expat XML Parser version is >= $expat_version_req]) + + if test -f "$expat_include_dir/expat.h"; then + + expat_major=`cat $expat_include_dir/expat.h | \ + grep '^#define.*XML_MAJOR_VERSION.*[0-9]$' | \ + sed -e 's/#define XML_MAJOR_VERSION.//'` + + expat_minor=`cat $expat_include_dir/expat.h | \ + grep '^#define.*XML_MINOR_VERSION.*[0-9]$' | \ + sed -e 's/#define XML_MINOR_VERSION.//'` + + expat_revision=`cat $expat_include_dir/expat.h | \ + grep '^#define.*XML_MICRO_VERSION.*[0-9]$' | \ + sed -e 's/#define XML_MICRO_VERSION.//'` + + EXPAT_VERSION="$expat_major.$expat_minor.$expat_revision" + AC_SUBST([EXPAT_VERSION]) + + dnl Decompose required version string and calculate numerical representation + expat_version_req_major=`expr $expat_version_req : '\([[0-9]]*\)'` + expat_version_req_minor=`expr $expat_version_req : '[[0-9]]*\.\([[0-9]]*\)'` + expat_version_req_revision=`expr $expat_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` + if test "x$expat_version_req_revision" = "x"; then + expat_version_req_revision="0" + fi + + expat_version_req_number=`expr $expat_version_req_major \* 10000 \ + \+ $expat_version_req_minor \* 100 \ + \+ $expat_version_req_revision` + + dnl Calculate numerical representation of detected version + expat_version_number=`expr $expat_major \* 10000 \ + \+ $expat_minor \* 100 \ + \+ $expat_revision` + + expat_version_check=`expr $expat_version_number \>\= $expat_version_req_number` + if test "$expat_version_check" = "1"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_WARN([Found Expat XML Parser $EXPAT_VERSION, which is older than required. Possible compilation failure.]) + fi + else + AC_MSG_RESULT([no]) + AC_MSG_WARN([Missing expat.h header. Unable to determine Expat version.]) + fi + fi + fi + + else + HAVE_EXPAT="no" + AC_MSG_RESULT([$HAVE_EXPAT]) + + if test "$expat_requested" = "yes"; then + AC_MSG_WARN([Expat XML Parser support requested but headers or library not found. Specify valid prefix of Expat using --with-expat=@<:@DIR@:>@ or provide include directory and linker flags using --with-expat-inc and --with-expat-lib]) + fi + fi +]) diff --git a/daemon/m4/ax_path_lib_pcre.m4 b/daemon/m4/ax_path_lib_pcre.m4 new file mode 100644 index 0000000000000000000000000000000000000000..926e69d272d8288761c21163a96121f9e3691b0d --- /dev/null +++ b/daemon/m4/ax_path_lib_pcre.m4 @@ -0,0 +1,90 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_path_lib_pcre.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PATH_LIB_PCRE [(A/NA)] +# +# DESCRIPTION +# +# check for pcre lib and set PCRE_LIBS and PCRE_CFLAGS accordingly. +# +# also provide --with-pcre option that may point to the $prefix of the +# pcre installation - the macro will check $pcre/include and $pcre/lib to +# contain the necessary files. +# +# the usual two ACTION-IF-FOUND / ACTION-IF-NOT-FOUND are supported and +# they can take advantage of the LIBS/CFLAGS additions. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 7 + +AC_DEFUN([AX_PATH_LIB_PCRE],[dnl +AC_MSG_CHECKING([lib pcre]) +AC_ARG_WITH(pcre, +[ --with-pcre[[=prefix]] compile xmlpcre part (via libpcre check)],, + with_pcre="yes") +if test ".$with_pcre" = ".no" ; then + AC_MSG_RESULT([disabled]) + m4_ifval($2,$2) +else + AC_MSG_RESULT([(testing)]) + AC_CHECK_LIB(pcre, pcre_study) + if test "$ac_cv_lib_pcre_pcre_study" = "yes" ; then + PCRE_LIBS="-lpcre" + AC_MSG_CHECKING([lib pcre]) + AC_MSG_RESULT([$PCRE_LIBS]) + m4_ifval($1,$1) + else + OLDLDFLAGS="$LDFLAGS" ; LDFLAGS="$LDFLAGS -L$with_pcre/lib" + OLDCPPFLAGS="$CPPFLAGS" ; CPPFLAGS="$CPPFLAGS -I$with_pcre/include" + AC_CHECK_LIB(pcre, pcre_compile) + CPPFLAGS="$OLDCPPFLAGS" + LDFLAGS="$OLDLDFLAGS" + if test "$ac_cv_lib_pcre_pcre_compile" = "yes" ; then + AC_MSG_RESULT(.setting PCRE_LIBS -L$with_pcre/lib -lpcre) + PCRE_LIBS="-L$with_pcre/lib -lpcre" + test -d "$with_pcre/include" && PCRE_CFLAGS="-I$with_pcre/include" + AC_MSG_CHECKING([lib pcre]) + AC_MSG_RESULT([$PCRE_LIBS]) + m4_ifval($1,$1) + else + AC_MSG_CHECKING([lib pcre]) + AC_MSG_RESULT([no, (WARNING)]) + m4_ifval($2,$2) + fi + fi +fi +AC_SUBST([PCRE_LIBS]) +AC_SUBST([PCRE_CFLAGS]) +]) diff --git a/daemon/m4/ax_pthread.m4 b/daemon/m4/ax_pthread.m4 new file mode 100644 index 0000000000000000000000000000000000000000..e20a388ca869b2bf1be9946ef93c37146a9db387 --- /dev/null +++ b/daemon/m4/ax_pthread.m4 @@ -0,0 +1,309 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also link it with them as well. e.g. you should link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threads programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name +# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu> +# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.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 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 17 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) + AC_MSG_RESULT($ax_pthread_ok) + if test x"$ax_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" + ;; + + *-darwin*) + ax_pthread_flags="-pthread $ax_pthread_flags" + ;; +esac + +if test x"$ax_pthread_ok" = xno; then +for flag in $ax_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) + if test x"$ax_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h> + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($ax_pthread_ok) + if test "x$ax_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>], + [int attr = $attr; return attr /* ; */])], + [attr_name=$attr; break], + []) + done + AC_MSG_RESULT($attr_name) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *-osf* | *-hpux*) flag="-D_REENTRANT";; + *solaris*) + if test "$GCC" = "yes"; then + flag="-D_REENTRANT" + else + flag="-mt -D_REENTRANT" + fi + ;; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + ax_cv_PTHREAD_PRIO_INHERIT, [ + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], + AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) + else + PTHREAD_CC=$CC + fi +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$ax_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/daemon/src/Makefile.am b/daemon/src/Makefile.am index 271c3902d446362786f1df58e1c45fa4cba10767..b7bfeab1a3175a9b5f4b7ec209378af802aea1c5 100644 --- a/daemon/src/Makefile.am +++ b/daemon/src/Makefile.am @@ -30,7 +30,7 @@ sflphoned_CXXFLAGS = \ # libsflphone -sflphoned_LDADD = ./libsflphone.la $(libssl_LIBS) -lcrypto +sflphoned_LDADD = ./libsflphone.la $(libssl_LIBS) -lcrypto $(YAML_LIBS) noinst_LTLIBRARIES = libsflphone.la noinst_HEADERS = \ @@ -48,10 +48,13 @@ noinst_HEADERS = \ logger.h \ numbercleaner.h \ fileutils.h \ - noncopyable.h + noncopyable.h \ + cc_thread.h \ + cc_config.h \ + sfl_types.h \ + array_size.h libsflphone_la_LIBADD = \ - $(top_builddir)/libs/utilspp/libutilspp.la \ $(top_builddir)/libs/iax2/libiax2.la \ $(IAX_LIB) \ ./im/libim.la \ @@ -73,8 +76,6 @@ libsflphone_la_LDFLAGS = \ @SAMPLERATE_LIBS@ \ @libssl_LIBS@ \ @UUID_LIBS@ \ - @yaml_LIBS@ \ - @xml_LIBS@ \ @DBUSCPP_LIBS@ libsflphone_la_CFLAGS = \ @@ -87,14 +88,13 @@ libsflphone_la_CFLAGS = \ @PULSEAUDIO_CFLAGS@ \ @SAMPLERATE_CFLAGS@ \ @libssl_CFLAGS@ \ - @UUID_CFLAGS@ \ - @yaml_CFLAGS@ \ - @xml_CFLAGS@ + @UUID_CFLAGS@ libsflphone_la_SOURCES = conference.cpp \ voiplink.cpp \ preferences.cpp \ managerimpl.cpp \ + manager.cpp \ managerimpl_registration.cpp \ eventthread.cpp \ call.cpp \ diff --git a/daemon/src/account.cpp b/daemon/src/account.cpp index af0b0689d7505b4b951704dce1c1919a00c85029..8c24b7144e023a8e4653ea10a3446e354acf5e9a 100644 --- a/daemon/src/account.cpp +++ b/daemon/src/account.cpp @@ -32,8 +32,9 @@ #include "account.h" #include "manager.h" +#include "dbus/configurationmanager.h" -Account::Account(const std::string& accountID, const std::string &type) : +Account::Account(const std::string &accountID, const std::string &type) : accountID_(accountID) , username_() , hostname_() @@ -54,8 +55,7 @@ Account::Account(const std::string& accountID, const std::string &type) : } Account::~Account() -{ -} +{} void Account::setRegistrationState(const RegistrationState &state) { @@ -63,7 +63,8 @@ void Account::setRegistrationState(const RegistrationState &state) registrationState_ = state; // Notify the client - Manager::instance().connectionStatusNotification(); + ConfigurationManager *c(Manager::instance().getDbusManager()->getConfigurationManager()); + c->registrationStateChanged(accountID_, registrationState_); } } @@ -87,21 +88,21 @@ void Account::loadDefaultCodecs() -void Account::setActiveCodecs(const std::vector <std::string> &list) +void Account::setActiveCodecs(const std::vector<std::string> &list) { // first clear the previously stored codecs codecOrder_.clear(); // list contains the ordered payload of active codecs picked by the user for this account // we used the CodecOrder vector to save the order. - for (std::vector<std::string>::const_iterator iter = list.begin(); iter != list.end(); - ++iter) { + for (std::vector<std::string>::const_iterator iter = list.begin(); + iter != list.end(); ++iter) { int payload = std::atoi(iter->c_str()); - codecOrder_.push_back((int) payload); + codecOrder_.push_back(payload); } // update the codec string according to new codec selection - codecStr_ = ManagerImpl::serialize(list); + codecStr_ = ManagerImpl::join_string(list); } std::string Account::mapStateNumberToString(RegistrationState state) diff --git a/daemon/src/account.h b/daemon/src/account.h index 7d3216ee32d4724f567820dc89a7490eea728cbc..8e66bb97017080852dab8dd05aee97ba22814bb3 100644 --- a/daemon/src/account.h +++ b/daemon/src/account.h @@ -37,7 +37,7 @@ #include "global.h" #include "noncopyable.h" -#include "config/config.h" +#include "config/sfl_config.h" #include "config/serializable.h" class VoIPLink; @@ -59,12 +59,12 @@ enum RegistrationState { ErrorNetwork , ErrorHost, ErrorExistStun, - ErrorConfStun, + ErrorNotAcceptable, NumberOfStates }; // Account identifier -static const char *const ACCOUNT_ID = "Account.id"; +static const char *const CONFIG_ACCOUNT_ID = "Account.id"; // Common account parameters static const char *const CONFIG_ACCOUNT_TYPE = "Account.type"; @@ -72,77 +72,77 @@ static const char *const CONFIG_ACCOUNT_ALIAS = "Account.alias"; static const char *const CONFIG_ACCOUNT_MAILBOX = "Account.mailbox"; static const char *const CONFIG_ACCOUNT_ENABLE = "Account.enable"; static const char *const CONFIG_ACCOUNT_REGISTRATION_EXPIRE = "Account.registrationExpire"; +static const char *const CONFIG_ACCOUNT_REGISTRATION_STATUS = "Account.registrationStatus"; +static const char *const CONFIG_ACCOUNT_REGISTRATION_STATE_CODE = "Account.registrationCode"; +static const char *const CONFIG_ACCOUNT_REGISTRATION_STATE_DESC = "Account.registrationDescription"; static const char *const CONFIG_CREDENTIAL_NUMBER = "Credential.count"; -static const char *const ACCOUNT_DTMF_TYPE = "Account.dtmfType"; +static const char *const CONFIG_ACCOUNT_DTMF_TYPE = "Account.dtmfType"; static const char *const CONFIG_RINGTONE_PATH = "Account.ringtonePath"; static const char *const CONFIG_RINGTONE_ENABLED = "Account.ringtoneEnabled"; +static const char *const CONFIG_KEEP_ALIVE_ENABLED = "Account.keepAliveEnabled"; -static const char *const HOSTNAME = "hostname"; -static const char *const USERNAME = "username"; -static const char *const ROUTESET = "routeset"; -static const char *const PASSWORD = "password"; -static const char *const REALM = "realm"; -static const char *const DEFAULT_REALM = "*"; -static const char *const USERAGENT = "useragent"; +static const char *const CONFIG_ACCOUNT_HOSTNAME = "Account.hostname"; +static const char *const CONFIG_ACCOUNT_USERNAME = "Account.username"; +static const char *const CONFIG_ACCOUNT_ROUTESET = "Account.routeset"; +static const char *const CONFIG_ACCOUNT_PASSWORD = "Account.password"; +static const char *const CONFIG_ACCOUNT_REALM = "Account.realm"; +static const char *const CONFIG_ACCOUNT_DEFAULT_REALM = "*"; +static const char *const CONFIG_ACCOUNT_USERAGENT = "Account.useragent"; -static const char *const LOCAL_INTERFACE = "Account.localInterface"; -static const char *const PUBLISHED_SAMEAS_LOCAL = "Account.publishedSameAsLocal"; -static const char *const LOCAL_PORT = "Account.localPort"; -static const char *const PUBLISHED_PORT = "Account.publishedPort"; -static const char *const PUBLISHED_ADDRESS = "Account.publishedAddress"; +static const char *const CONFIG_LOCAL_INTERFACE = "Account.localInterface"; +static const char *const CONFIG_PUBLISHED_SAMEAS_LOCAL = "Account.publishedSameAsLocal"; +static const char *const CONFIG_LOCAL_PORT = "Account.localPort"; +static const char *const CONFIG_PUBLISHED_PORT = "Account.publishedPort"; +static const char *const CONFIG_PUBLISHED_ADDRESS = "Account.publishedAddress"; -static const char *const DISPLAY_NAME = "Account.displayName"; -static const char *const DEFAULT_ADDRESS = "0.0.0.0"; +static const char *const CONFIG_DISPLAY_NAME = "Account.displayName"; +static const char *const CONFIG_DEFAULT_ADDRESS = "0.0.0.0"; // SIP specific parameters -static const char *const SIP_PROXY = "SIP.proxy"; -static const char *const STUN_SERVER = "STUN.server"; -static const char *const STUN_ENABLE = "STUN.enable"; +static const char *const CONFIG_SIP_PROXY = "SIP.proxy"; +static const char *const CONFIG_STUN_SERVER = "STUN.server"; +static const char *const CONFIG_STUN_ENABLE = "STUN.enable"; // SRTP specific parameters -static const char *const SRTP_ENABLE = "SRTP.enable"; -static const char *const SRTP_KEY_EXCHANGE = "SRTP.keyExchange"; -static const char *const SRTP_ENCRYPTION_ALGO = "SRTP.encryptionAlgorithm"; // Provided by ccRTP,0=NULL,1=AESCM,2=AESF8 -static const char *const SRTP_RTP_FALLBACK = "SRTP.rtpFallback"; -static const char *const ZRTP_HELLO_HASH = "ZRTP.helloHashEnable"; -static const char *const ZRTP_DISPLAY_SAS = "ZRTP.displaySAS"; -static const char *const ZRTP_NOT_SUPP_WARNING = "ZRTP.notSuppWarning"; -static const char *const ZRTP_DISPLAY_SAS_ONCE = "ZRTP.displaySasOnce"; - -static const char *const TLS_LISTENER_PORT = "TLS.listenerPort"; -static const char *const TLS_ENABLE = "TLS.enable"; -static const char *const TLS_CA_LIST_FILE = "TLS.certificateListFile"; -static const char *const TLS_CERTIFICATE_FILE = "TLS.certificateFile"; -static const char *const TLS_PRIVATE_KEY_FILE = "TLS.privateKeyFile"; -static const char *const TLS_PASSWORD = "TLS.password"; -static const char *const TLS_METHOD = "TLS.method"; -static const char *const TLS_CIPHERS = "TLS.ciphers"; -static const char *const TLS_SERVER_NAME = "TLS.serverName"; -static const char *const TLS_VERIFY_SERVER = "TLS.verifyServer"; -static const char *const TLS_VERIFY_CLIENT = "TLS.verifyClient"; -static const char *const TLS_REQUIRE_CLIENT_CERTIFICATE = "TLS.requireClientCertificate"; -static const char *const TLS_NEGOTIATION_TIMEOUT_SEC = "TLS.negotiationTimeoutSec"; -static const char *const TLS_NEGOTIATION_TIMEOUT_MSEC = "TLS.negotiationTimemoutMsec"; - -static const char *const REGISTRATION_STATUS = "Status"; -static const char *const REGISTRATION_STATE_CODE = "Registration.code"; -static const char *const REGISTRATION_STATE_DESCRIPTION = "Registration.description"; +static const char *const CONFIG_SRTP_ENABLE = "SRTP.enable"; +static const char *const CONFIG_SRTP_KEY_EXCHANGE = "SRTP.keyExchange"; +static const char *const CONFIG_SRTP_ENCRYPTION_ALGO = "SRTP.encryptionAlgorithm"; // Provided by ccRTP,0=NULL,1=AESCM,2=AESF8 +static const char *const CONFIG_SRTP_RTP_FALLBACK = "SRTP.rtpFallback"; +static const char *const CONFIG_ZRTP_HELLO_HASH = "ZRTP.helloHashEnable"; +static const char *const CONFIG_ZRTP_DISPLAY_SAS = "ZRTP.displaySAS"; +static const char *const CONFIG_ZRTP_NOT_SUPP_WARNING = "ZRTP.notSuppWarning"; +static const char *const CONFIG_ZRTP_DISPLAY_SAS_ONCE = "ZRTP.displaySasOnce"; + +static const char *const CONFIG_TLS_LISTENER_PORT = "TLS.listenerPort"; +static const char *const CONFIG_TLS_ENABLE = "TLS.enable"; +static const char *const CONFIG_TLS_CA_LIST_FILE = "TLS.certificateListFile"; +static const char *const CONFIG_TLS_CERTIFICATE_FILE = "TLS.certificateFile"; +static const char *const CONFIG_TLS_PRIVATE_KEY_FILE = "TLS.privateKeyFile"; +static const char *const CONFIG_TLS_PASSWORD = "TLS.password"; +static const char *const CONFIG_TLS_METHOD = "TLS.method"; +static const char *const CONFIG_TLS_CIPHERS = "TLS.ciphers"; +static const char *const CONFIG_TLS_SERVER_NAME = "TLS.serverName"; +static const char *const CONFIG_TLS_VERIFY_SERVER = "TLS.verifyServer"; +static const char *const CONFIG_TLS_VERIFY_CLIENT = "TLS.verifyClient"; +static const char *const CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE = "TLS.requireClientCertificate"; +static const char *const CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC = "TLS.negotiationTimeoutSec"; +static const char *const CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC = "TLS.negotiationTimemoutMsec"; // General configuration keys for accounts -static const char * const aliasKey = "alias"; -static const char * const typeKey = "type"; -static const char * const idKey = "id"; -static const char * const usernameKey = "username"; -static const char * const authenticationUsernameKey = "authenticationUsername"; -static const char * const passwordKey = "password"; -static const char * const hostnameKey = "hostname"; -static const char * const accountEnableKey = "enable"; -static const char * const mailboxKey = "mailbox"; - -static const char * const codecsKey = "codecs"; // 0/9/110/111/112/ -static const char * const ringtonePathKey = "ringtonePath"; -static const char * const ringtoneEnabledKey = "ringtoneEnabled"; -static const char * const displayNameKey = "displayName"; +static const char * const ALIAS_KEY = "alias"; +static const char * const TYPE_KEY = "type"; +static const char * const ID_KEY = "id"; +static const char * const USERNAME_KEY = "username"; +static const char * const AUTHENTICATION_USERNAME_KEY = "authenticationUsername"; +static const char * const PASSWORD_KEY = "password"; +static const char * const HOSTNAME_KEY = "hostname"; +static const char * const ACCOUNT_ENABLE_KEY = "enable"; +static const char * const MAILBOX_KEY = "mailbox"; + +static const char * const CODECS_KEY = "codecs"; // 0/9/110/111/112/ +static const char * const RINGTONE_PATH_KEY = "ringtonePath"; +static const char * const RINGTONE_ENABLED_KEY = "ringtoneEnabled"; +static const char * const DISPLAY_NAME_KEY = "displayName"; class Account : public Serializable { @@ -155,18 +155,6 @@ class Account : public Serializable { */ virtual ~Account(); - /** - * Method called by the configuration engine to serialize instance's information - * into configuration file. - */ - virtual void serialize(Conf::YamlEmitter *emitter) = 0; - - /** - * Method called by the configuration engine to restore instance internal state - * from configuration file. - */ - virtual void unserialize(Conf::MappingNode *map) = 0; - virtual void setAccountDetails(std::map<std::string, std::string> details) = 0; virtual std::map<std::string, std::string> getAccountDetails() const = 0; @@ -240,13 +228,6 @@ class Account : public Serializable { alias_ = alias; } - std::string getType() const { - return type_; - } - void setType(const std::string &type) { - type_ = type; - } - /** * Accessor to data structures * @return CodecOrder& The list that reflects the user's choice diff --git a/daemon/src/array_size.h b/daemon/src/array_size.h new file mode 100644 index 0000000000000000000000000000000000000000..9bca08aadb5aa4b6d88f3ad49c71816e063eb7f5 --- /dev/null +++ b/daemon/src/array_size.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef ARRAY_SIZE_H_ +#define ARRAY_SIZE_H_ + +// Returns the number of elements in a, calculated at compile-time +#define ARRAYSIZE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) + +#endif // ARRAY_SIZE_H_ diff --git a/daemon/src/audio/Makefile.am b/daemon/src/audio/Makefile.am index 3e623cbae44c5621a165fe3b1df3c76046c266ef..de8950ed4a11f11d71ea43ce4baf17acae4b5bf3 100644 --- a/daemon/src/audio/Makefile.am +++ b/daemon/src/audio/Makefile.am @@ -22,7 +22,6 @@ libaudio_la_SOURCES = \ noinst_HEADERS = \ audioloop.h \ - common.h \ ringbuffer.h \ mainbuffer.h \ audiorecord.h \ @@ -43,6 +42,3 @@ libaudio_la_LIBADD = \ ./alsa/libalsalayer.la \ ./pulseaudio/libpulselayer.la \ ./sound/libsound.la - - - diff --git a/daemon/src/audio/alsa/alsalayer.cpp b/daemon/src/audio/alsa/alsalayer.cpp index f8d7b915bf5ee2034e1e9b7ee173c9cfc9ef821e..70d51237ed150d8446cf158206ec48c85ed8464d 100644 --- a/daemon/src/audio/alsa/alsalayer.cpp +++ b/daemon/src/audio/alsa/alsalayer.cpp @@ -33,17 +33,17 @@ #include "audio/dcblocker.h" #include "eventthread.h" #include "audio/samplerateconverter.h" -#include "managerimpl.h" +#include "logger.h" +#include "manager.h" #include "noncopyable.h" #include "dbus/configurationmanager.h" +#include <ctime> class AlsaThread : public ost::Thread { public: AlsaThread(AlsaLayer *alsa); - ~AlsaThread() { - terminate(); - } + ~AlsaThread() { terminate(); } virtual void run(); @@ -53,17 +53,15 @@ class AlsaThread : public ost::Thread { }; AlsaThread::AlsaThread(AlsaLayer *alsa) - : Thread(), alsa_(alsa) -{ - setCancel(cancelDeferred); -} + : ost::Thread(), alsa_(alsa) +{} /** * Reimplementation of run() */ void AlsaThread::run() { - while (!testCancel()) { + while (alsa_->isStarted_) { alsa_->audioCallback(); Thread::sleep(20); } @@ -87,11 +85,14 @@ AlsaLayer::AlsaLayer() , is_capture_open_(false) , audioThread_(NULL) { + setCaptureGain(Manager::instance().audioPreference.getVolumemic()); + setPlaybackGain(Manager::instance().audioPreference.getVolumespkr()); } // Destructor AlsaLayer::~AlsaLayer() { + isStarted_ = false; delete audioThread_; /* Then close the audio devices */ @@ -107,7 +108,8 @@ bool AlsaLayer::openDevice(snd_pcm_t **pcm, const std::string &dev, snd_pcm_stre // Retry if busy, since dmix plugin may not have released the device yet for (int tries = 0; tries < MAX_RETRIES and err == -EBUSY; ++tries) { - usleep(10000); + const struct timespec req = {0, 10000000}; + nanosleep(&req, 0); err = snd_pcm_open(pcm, dev.c_str(), stream, 0); } @@ -217,7 +219,7 @@ AlsaLayer::stopStream() #define ALSA_CALL(call, error) ({ \ int err_code = call; \ if (err_code < 0) \ - ERROR("ALSA: "error": %s", snd_strerror(err_code)); \ + ERROR(error ": %s", snd_strerror(err_code)); \ err_code; \ }) @@ -312,16 +314,16 @@ bool AlsaLayer::alsa_set_params(snd_pcm_t *pcm_handle) TRY(snd_pcm_hw_params_any(HW), "hwparams init"); TRY(snd_pcm_hw_params_set_access(HW, SND_PCM_ACCESS_RW_INTERLEAVED), "access type"); TRY(snd_pcm_hw_params_set_format(HW, SND_PCM_FORMAT_S16_LE), "sample format"); - TRY(snd_pcm_hw_params_set_rate_near(HW, &audioSampleRate_, NULL), "sample rate"); + TRY(snd_pcm_hw_params_set_rate_near(HW, &sampleRate_, NULL), "sample rate"); TRY(snd_pcm_hw_params_set_channels(HW, 1), "channel count"); TRY(snd_pcm_hw_params_set_period_size_near(HW, &periodSize, NULL), "period time"); TRY(snd_pcm_hw_params_set_periods_near(HW, &periods, NULL), "periods number"); TRY(snd_pcm_hw_params(HW), "hwparams"); #undef HW - DEBUG("ALSA: %s using sampling rate %dHz", + DEBUG("%s using sampling rate %dHz", (snd_pcm_stream(pcm_handle) == SND_PCM_STREAM_PLAYBACK) ? "playback" : "capture", - audioSampleRate_); + sampleRate_); snd_pcm_sw_params_t *swparams = NULL; snd_pcm_sw_params_alloca(&swparams); @@ -368,7 +370,7 @@ AlsaLayer::write(void* buffer, int length, snd_pcm_t * handle) } default: - ERROR("ALSA: unknown write error, dropping frames: %s", snd_strerror(err)); + ERROR("Unknown write error, dropping frames: %s", snd_strerror(err)); stopPlaybackStream(); break; } @@ -403,12 +405,12 @@ AlsaLayer::read(void* buffer, int toCopy) startCaptureStream(); } - ERROR("ALSA: XRUN capture ignored (%s)", snd_strerror(err)); + ERROR("XRUN capture ignored (%s)", snd_strerror(err)); break; } case EPERM: - ERROR("ALSA: Can't capture, EPERM (%s)", snd_strerror(err)); + ERROR("Can't capture, EPERM (%s)", snd_strerror(err)); prepareCaptureStream(); startCaptureStream(); break; @@ -434,14 +436,12 @@ AlsaLayer::buildDeviceTopo(const std::string &plugin, int card) std::vector<std::string> AlsaLayer::getAudioDeviceList(AudioStreamDirection dir) const { - std::vector<HwIDPair> deviceMap; - std::vector<std::string> audioDeviceList; + std::vector<HwIDPair> deviceMap(getAudioDeviceIndexMap(dir)); - deviceMap = getAudioDeviceIndexMap(dir); - - for(std::vector<HwIDPair>::const_iterator iter = deviceMap.begin(); iter != deviceMap.end(); iter++) { + std::vector<std::string> audioDeviceList; + for (std::vector<HwIDPair>::const_iterator iter = deviceMap.begin(); + iter != deviceMap.end(); ++iter) audioDeviceList.push_back(iter->second); - } return audioDeviceList; } @@ -456,7 +456,7 @@ AlsaLayer::getAudioDeviceIndexMap(AudioStreamDirection dir) const snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); - int numCard = -1 ; + int numCard = -1; std::vector<HwIDPair> audioDevice; @@ -538,19 +538,10 @@ AlsaLayer::getAudioDeviceIndex(const std::string &description) const return 0; } -namespace { -void adjustVolume(SFLDataFormat *src , int samples, int volumePercentage) -{ - if (volumePercentage != 100) - for (int i = 0 ; i < samples; i++) - src[i] = src[i] * volumePercentage * 0.01; -} -} - void AlsaLayer::capture() { unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - bool resample = audioSampleRate_ != mainBufferSampleRate; + bool resample = sampleRate_ != mainBufferSampleRate; int toGetSamples = snd_pcm_avail_update(captureHandle_); @@ -565,41 +556,39 @@ void AlsaLayer::capture() if (toGetSamples > framesPerBufferAlsa) toGetSamples = framesPerBufferAlsa; - int toGetBytes = toGetSamples * sizeof(SFLDataFormat); - SFLDataFormat* in = (SFLDataFormat*) malloc(toGetBytes); + std::vector<SFLDataFormat> in(toGetSamples); - if (read(in, toGetBytes) != toGetBytes) { + const int toGetBytes = in.size() * sizeof(in[0]); + if (read(&(*in.begin()), toGetBytes) != toGetBytes) { ERROR("ALSA MIC : Couldn't read!"); - goto end; + return; } - adjustVolume(in, toGetSamples, Manager::instance().getSpkrVolume()); + AudioLayer::applyGain(&(*in.begin()), toGetSamples, getCaptureGain()); if (resample) { - int outSamples = toGetSamples * ((double) audioSampleRate_ / mainBufferSampleRate); - int outBytes = outSamples * sizeof(SFLDataFormat); - SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc(outBytes); - converter_->resample((SFLDataFormat*) in, rsmpl_out, mainBufferSampleRate, audioSampleRate_, toGetSamples); - dcblocker_.process(rsmpl_out, rsmpl_out, outSamples); - Manager::instance().getMainBuffer()->putData(rsmpl_out, outBytes); - free(rsmpl_out); + int outSamples = toGetSamples * ((double) sampleRate_ / mainBufferSampleRate); + std::vector<SFLDataFormat> rsmpl_out(outSamples); + converter_.resample(&(*in.begin()), &(*rsmpl_out.begin()), + rsmpl_out.size(), mainBufferSampleRate, sampleRate_, + toGetSamples); + dcblocker_.process(&(*rsmpl_out.begin()), &(*rsmpl_out.begin()), outSamples); + Manager::instance().getMainBuffer()->putData(&(*rsmpl_out.begin()), + rsmpl_out.size() * sizeof(rsmpl_out[0]), MainBuffer::DEFAULT_ID); } else { - dcblocker_.process(in, in, toGetSamples); - Manager::instance().getMainBuffer()->putData(in, toGetBytes); + dcblocker_.process(&(*in.begin()), &(*in.begin()), toGetSamples); + Manager::instance().getMainBuffer()->putData(&(*in.begin()), + toGetBytes, MainBuffer::DEFAULT_ID); } - -end: - free(in); } void AlsaLayer::playback(int maxSamples) { - unsigned short spkrVolume = Manager::instance().getSpkrVolume(); unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - bool resample = audioSampleRate_ != mainBufferSampleRate; + bool resample = sampleRate_ != mainBufferSampleRate; - int toGet = Manager::instance().getMainBuffer()->availForGet(); + int toGet = Manager::instance().getMainBuffer()->availForGet(MainBuffer::DEFAULT_ID); int toPut = maxSamples * sizeof(SFLDataFormat); if (toGet <= 0) { // no audio available, play tone or silence @@ -608,10 +597,12 @@ void AlsaLayer::playback(int maxSamples) SFLDataFormat *out = (SFLDataFormat *) malloc(toPut); - if (tone) - tone->getNext(out, maxSamples, spkrVolume); - else if (file_tone && !ringtoneHandle_) - file_tone->getNext(out, maxSamples, spkrVolume); + if (tone) { + tone->getNext(out, maxSamples, getPlaybackGain()); + } + else if (file_tone && !ringtoneHandle_) { + file_tone->getNext(out, maxSamples, getPlaybackGain()); + } else memset(out, 0, toPut); @@ -627,7 +618,7 @@ void AlsaLayer::playback(int maxSamples) double resampleFactor = 1.0; if (resample) { - resampleFactor = (double) audioSampleRate_ / mainBufferSampleRate; + resampleFactor = (double) sampleRate_ / mainBufferSampleRate; maxNbBytesToGet = (double) toGet / resampleFactor; } @@ -635,16 +626,16 @@ void AlsaLayer::playback(int maxSamples) toGet = maxNbBytesToGet; SFLDataFormat *out = (SFLDataFormat*) malloc(toGet); - Manager::instance().getMainBuffer()->getData(out, toGet); - adjustVolume(out, toGet / sizeof(SFLDataFormat), spkrVolume); + Manager::instance().getMainBuffer()->getData(out, toGet, MainBuffer::DEFAULT_ID); + AudioLayer::applyGain(out, toGet / sizeof(SFLDataFormat), getPlaybackGain()); if (resample) { int inSamples = toGet / sizeof(SFLDataFormat); int outSamples = inSamples * resampleFactor; - SFLDataFormat *rsmpl_out = (SFLDataFormat*) malloc(outSamples * sizeof(SFLDataFormat)); - converter_->resample(out, rsmpl_out, mainBufferSampleRate, audioSampleRate_, inSamples); - write(rsmpl_out, outSamples * sizeof(SFLDataFormat), playbackHandle_); - free(rsmpl_out); + std::vector<SFLDataFormat> rsmpl_out(outSamples); + converter_.resample(out, &(*rsmpl_out.begin()), rsmpl_out.size(), + mainBufferSampleRate, sampleRate_, inSamples); + write(&(*rsmpl_out.begin()), outSamples * sizeof(SFLDataFormat), playbackHandle_); } else { write(out, toGet, playbackHandle_); } @@ -657,16 +648,14 @@ void AlsaLayer::audioCallback() if (!playbackHandle_ or !captureHandle_) return; - notifyincomingCall(); - - unsigned short spkrVolume = Manager::instance().getSpkrVolume(); + notifyIncomingCall(); snd_pcm_wait(playbackHandle_, 20); int playbackAvailSmpl = snd_pcm_avail_update(playbackHandle_); int playbackAvailBytes = playbackAvailSmpl * sizeof(SFLDataFormat); - int toGet = urgentRingBuffer_.AvailForGet(); + int toGet = urgentRingBuffer_.AvailForGet(MainBuffer::DEFAULT_ID); if (toGet > 0) { // Urgent data (dtmf, incoming call signal) come first. @@ -674,13 +663,13 @@ void AlsaLayer::audioCallback() toGet = playbackAvailBytes; SFLDataFormat *out = (SFLDataFormat*) malloc(toGet); - urgentRingBuffer_.Get(out, toGet); - adjustVolume(out, toGet / sizeof(SFLDataFormat), spkrVolume); + urgentRingBuffer_.Get(out, toGet, MainBuffer::DEFAULT_ID); + AudioLayer::applyGain(out, toGet / sizeof(SFLDataFormat), getPlaybackGain()); write(out, toGet, playbackHandle_); free(out); // Consume the regular one as well (same amount of bytes) - Manager::instance().getMainBuffer()->discard(toGet); + Manager::instance().getMainBuffer()->discard(toGet, MainBuffer::DEFAULT_ID); } else { // regular audio data playback(playbackAvailSmpl); @@ -689,17 +678,17 @@ void AlsaLayer::audioCallback() if (ringtoneHandle_) { AudioLoop *file_tone = Manager::instance().getTelephoneFile(); int ringtoneAvailSmpl = snd_pcm_avail_update(ringtoneHandle_); - int ringtoneAvailBytes = ringtoneAvailSmpl*sizeof(SFLDataFormat); + int ringtoneAvailBytes = ringtoneAvailSmpl * sizeof(SFLDataFormat); - SFLDataFormat *out = (SFLDataFormat *) malloc(ringtoneAvailBytes); + std::vector<SFLDataFormat> out(ringtoneAvailSmpl, 0); - if (file_tone) - file_tone->getNext(out, ringtoneAvailSmpl, spkrVolume); - else - memset(out, 0, ringtoneAvailBytes); + if (file_tone) { + DEBUG("playback gain %d", getPlaybackGain()); + file_tone->getNext(&(*out.begin()), ringtoneAvailSmpl, + getPlaybackGain()); + } - write(out, ringtoneAvailBytes, ringtoneHandle_); - free(out); + write(&(*out.begin()), ringtoneAvailBytes, ringtoneHandle_); } // Additionally handle the mic's audio stream diff --git a/daemon/src/audio/alsa/alsalayer.h b/daemon/src/audio/alsa/alsalayer.h index f15d0d333a5a3d9592ff6397df5f1ee5d30f22bf..76a84e2b69388ae2eea461f85ef418abf2de205b 100644 --- a/daemon/src/audio/alsa/alsalayer.h +++ b/daemon/src/audio/alsa/alsalayer.h @@ -115,7 +115,7 @@ class AlsaLayer : public AudioLayer { * @return int Its index */ int getAudioDeviceIndex(const std::string &description) const; - + void playback(int maxSamples); void capture(); @@ -149,7 +149,7 @@ class AlsaLayer : public AudioLayer { } private: - + friend class AlsaThread; /** * Calls snd_pcm_open and retries if device is busy, since dmix plugin @@ -241,7 +241,7 @@ class AlsaLayer : public AudioLayer { bool is_playback_open_; bool is_capture_open_; - AlsaThread* audioThread_; + AlsaThread *audioThread_; }; #endif // _ALSA_LAYER_H_ diff --git a/daemon/src/audio/audiolayer.cpp b/daemon/src/audio/audiolayer.cpp index 285f31978bc3864374dca74f8a7940b8b462d717..ab7c34284bfa61dd7d549acf122be821604cfff7 100644 --- a/daemon/src/audio/audiolayer.cpp +++ b/daemon/src/audio/audiolayer.cpp @@ -34,23 +34,20 @@ #include "audio/dcblocker.h" #include "manager.h" +unsigned int AudioLayer::captureGain_ = 100; +unsigned int AudioLayer::playbackGain_ = 100; + AudioLayer::AudioLayer() : isStarted_(false) - , urgentRingBuffer_(SIZEBUF, Call::DEFAULT_ID) - , audioSampleRate_(Manager::instance().getMainBuffer()->getInternalSamplingRate()) + , urgentRingBuffer_(SIZEBUF, MainBuffer::DEFAULT_ID) + , sampleRate_(Manager::instance().getMainBuffer()->getInternalSamplingRate()) , mutex_() , dcblocker_() , audioPref(Manager::instance().audioPreference) - , converter_(new SamplerateConverter(audioSampleRate_)) + , converter_(sampleRate_) , lastNotificationTime_(0) { - urgentRingBuffer_.createReadPointer(); -} - - -AudioLayer::~AudioLayer() -{ - delete converter_; + urgentRingBuffer_.createReadPointer(MainBuffer::DEFAULT_ID); } void AudioLayer::flushMain() @@ -72,8 +69,15 @@ void AudioLayer::putUrgent(void* buffer, int toCopy) urgentRingBuffer_.Put(buffer, toCopy); } +void AudioLayer::applyGain(SFLDataFormat *src , int samples, int gain) +{ + if (gain != 100) + for (int i = 0 ; i < samples; i++) + src[i] = src[i] * gain* 0.01; +} + // Notify (with a beep) an incoming call when there is already a call in progress -void AudioLayer::notifyincomingCall() +void AudioLayer::notifyIncomingCall() { if (!Manager::instance().incomingCallWaiting()) return; diff --git a/daemon/src/audio/audiolayer.h b/daemon/src/audio/audiolayer.h index 573002e9b5e09e571d36b5b929cb77948c9a4794..a09090d4022d72eaf24cb5d377c4087b7ad6ecfb 100644 --- a/daemon/src/audio/audiolayer.h +++ b/daemon/src/audio/audiolayer.h @@ -31,13 +31,12 @@ * as that of the covered work. */ -#ifndef __AUDIO_LAYER_H__ -#define __AUDIO_LAYER_H__ +#ifndef AUDIO_LAYER_H_ +#define AUDIO_LAYER_H_ -#include <cc++/thread.h> // for ost::Mutex +#include "cc_thread.h" // for ost::Mutex #include <sys/time.h> - -#include "manager.h" +#include <vector> #include "ringbuffer.h" #include "dcblocker.h" #include "samplerateconverter.h" @@ -49,6 +48,7 @@ */ class MainBuffer; +class AudioPreference; namespace ost { class Time; @@ -62,7 +62,7 @@ class AudioLayer { public: AudioLayer(); - virtual ~AudioLayer(); + virtual ~AudioLayer() {} virtual std::vector<std::string> getAudioDeviceList(AudioStreamDirection dir) const = 0; @@ -105,7 +105,52 @@ class AudioLayer { */ void flushUrgent(); + /** + * Apply gain to audio frame + */ + static void applyGain(SFLDataFormat *src , int samples, int gain); + + /** + * Convert audio amplitude value from linear value to dB + */ + static double amplitudeLinearToDB(double value) { + return 20.0 * log10(value); + } + + /** + * Convert audio amplitude from dB to Linear value + */ + static double ampluitudeDBToLinear(double value) { + return pow(10.0, value / 20.0); + } + + /** + * Set capture stream gain (microphone) + */ + void setCaptureGain(unsigned int gain) { + captureGain_ = gain; + } + + /** + * Set capture stream gain (microphone) + */ + unsigned int getCaptureGain(void) { + return captureGain_; + } + + /** + * Set playback stream gain (speaker) + */ + void setPlaybackGain(unsigned int gain) { + playbackGain_ = gain; + } + /** + * Get playback stream gain (speaker) + */ + unsigned int getPlaybackGain(void) { + return playbackGain_; + } /** * Get the sample rate of the audio layer @@ -113,7 +158,7 @@ class AudioLayer { * default: 44100 HZ */ unsigned int getSampleRate() const { - return audioSampleRate_; + return sampleRate_; } /** @@ -126,7 +171,17 @@ class AudioLayer { /** * Emit an audio notification on incoming calls */ - void notifyincomingCall(); + void notifyIncomingCall(); + + /** + * Gain applied to mic signal + */ + static unsigned int captureGain_; + + /** + * Gain applied to playback signal + */ + static unsigned int playbackGain_; protected: @@ -144,15 +199,27 @@ class AudioLayer { * Sample Rate SFLphone should send sound data to the sound card * The value can be set in the user config file- now: 44100HZ */ - unsigned int audioSampleRate_; + unsigned int sampleRate_; /** * Lock for the entire audio layer */ ost::Mutex mutex_; + + /** + * Remove audio offset that can be introduced by certain cheap audio device + */ DcBlocker dcblocker_; + + /** + * Configuration file for this + */ AudioPreference &audioPref; - SamplerateConverter *converter_; + + /** + * Manage sampling rate conversion + */ + SamplerateConverter converter_; private: /** diff --git a/daemon/src/audio/audioloop.cpp b/daemon/src/audio/audioloop.cpp index 8c34366b7feddd47bd0a2ae74a7a66f10d749ef0..024d2cfe64876fdc3bfd90b785a48a8595b50cfc 100644 --- a/daemon/src/audio/audioloop.cpp +++ b/daemon/src/audio/audioloop.cpp @@ -37,6 +37,7 @@ #include <numeric> #include <cstring> #include <cassert> +#include "logger.h" AudioLoop::AudioLoop() : buffer_(0), size_(0), pos_(0), sampleRate_(0) {} @@ -52,10 +53,10 @@ AudioLoop::getNext(SFLDataFormat* output, size_t total_samples, short volume) size_t pos = pos_; if (size_ == 0) { - ERROR("AudioLoop: Error: Audio loop size is 0"); + ERROR("Audio loop size is 0"); return; } else if (pos >= size_) { - ERROR("AudioLoop: Error: Invalid loop position %d", pos); + ERROR("Invalid loop position %d", pos); return; } diff --git a/daemon/src/audio/audioloop.h b/daemon/src/audio/audioloop.h index cc6cc653fbe85e4df52c35e415667f70f497c20f..b7d54a7e0e2a499f22a79170b9654c7c7d1c3eb5 100644 --- a/daemon/src/audio/audioloop.h +++ b/daemon/src/audio/audioloop.h @@ -33,7 +33,8 @@ #ifndef __AUDIOLOOP_H__ #define __AUDIOLOOP_H__ -#include "global.h" // for SFLDataFormat +#include "sfl_types.h" +#include <cstring> #include "noncopyable.h" /** diff --git a/daemon/src/audio/audiorecord.cpp b/daemon/src/audio/audiorecord.cpp index 4b85829cc089332ddf0702a94b93f381e5e7dca5..33f2ae2c2bc7cc5e8cea2fd855c5a5b69c49744a 100644 --- a/daemon/src/audio/audiorecord.cpp +++ b/daemon/src/audio/audiorecord.cpp @@ -28,9 +28,16 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "audiorecord.h" #include <unistd.h> #include <sstream> // for stringstream +#include <cstdio> +#include "logger.h" +#include "fileutils.h" // structure for the wave header @@ -57,55 +64,54 @@ AudioRecord::AudioRecord() : fileHandle_(NULL) , sndSmplRate_(8000) , nbSamplesMic_(0) , nbSamplesSpk_(0) - , nbSamplesMax_(3000) , recordingEnabled_(false) - , mixBuffer_(new SFLDataFormat[nbSamplesMax_]) - , micBuffer_(new SFLDataFormat[nbSamplesMax_]) - , spkBuffer_(new SFLDataFormat[nbSamplesMax_]) + , mixBuffer_() + , micBuffer_() + , spkBuffer_() , filename_() , savePath_() { createFilename(); } -AudioRecord::~AudioRecord() -{ - delete [] mixBuffer_; - delete [] micBuffer_; - delete [] spkBuffer_; -} - void AudioRecord::setSndSamplingRate(int smplRate) { sndSmplRate_ = smplRate; } -int AudioRecord::getSndSamplingRate() const -{ - return sndSmplRate_; -} - void AudioRecord::setRecordingOption(FILE_TYPE type, int sndSmplRate, const std::string &path) { + std::stringstream s; + std::string filePath; + + // use HOME directory if path is empty, or if path does not exist + if (path.empty() || !fileutils::check_dir(path.c_str())) { + s << getenv("HOME"); + filePath = s.str(); + } + else { + filePath = path; + } + fileType_ = type; channels_ = 1; sndSmplRate_ = sndSmplRate; - savePath_ = path + "/"; + savePath_ = (*filePath.rbegin() == '/') ? filePath : filePath + "/"; } void AudioRecord::initFilename(const std::string &peerNumber) { std::string fName(filename_); - fName.append("-" + peerNumber); + fName.append("-" + peerNumber + "-" PACKAGE); if (fileType_ == FILE_RAW) { if (filename_.find(".raw") == std::string::npos) { - DEBUG("AudioRecord: concatenate .raw file extension: name : %s", filename_.c_str()); + DEBUG("Concatenate .raw file extension: name : %s", filename_.c_str()); fName.append(".raw"); } } else if (fileType_ == FILE_WAV) { if (filename_.find(".wav") == std::string::npos) { - DEBUG("AudioRecord: concatenate .wav file extension: name : %s", filename_.c_str()); + DEBUG("Concatenate .wav file extension: name : %s", filename_.c_str()); fName.append(".wav"); } } @@ -122,10 +128,8 @@ bool AudioRecord::openFile() { bool result = false; - DEBUG("AudioRecord: Open file()"); - if (not fileExists()) { - DEBUG("AudioRecord: Filename does not exist, creating one"); + DEBUG("Filename does not exist, creating one"); byteCounter_ = 0; if (fileType_ == FILE_RAW) @@ -133,7 +137,7 @@ bool AudioRecord::openFile() else if (fileType_ == FILE_WAV) result = setWavFile(); } else { - DEBUG("AudioRecord: Filename already exists, opening it"); + DEBUG("Filename already exists, opening it"); if (fileType_ == FILE_RAW) result = openExistingRawFile(); else if (fileType_ == FILE_WAV) @@ -168,40 +172,26 @@ bool AudioRecord::isRecording() const return recordingEnabled_; } -bool AudioRecord::setRecording() +void AudioRecord::setRecording() { if (isOpenFile()) { - if (!recordingEnabled_) { - DEBUG("AudioRecording: Start recording"); - recordingEnabled_ = true; - } else { - DEBUG("AudioRecording: Stop recording"); - recordingEnabled_ = false; - } + recordingEnabled_ = !recordingEnabled_; } else { openFile(); recordingEnabled_ = true; // once opend file, start recording } - - // WARNING: Unused return value - return true; - } void AudioRecord::stopRecording() { - DEBUG("AudioRecording: Stop recording"); + DEBUG("Stop recording"); recordingEnabled_ = false; } void AudioRecord::createFilename() { - time_t rawtime; - - struct tm * timeinfo; - - rawtime = time(NULL); - timeinfo = localtime(&rawtime); + time_t rawtime = time(NULL); + struct tm * timeinfo = localtime(&rawtime); std::stringstream out; @@ -241,7 +231,7 @@ void AudioRecord::createFilename() out << timeinfo->tm_sec; filename_ = out.str(); - DEBUG("AudioRecord: create filename for this call %s ", filename_.c_str()); + DEBUG("Generate filename for this call %s ", filename_.c_str()); } bool AudioRecord::setRawFile() @@ -249,54 +239,73 @@ bool AudioRecord::setRawFile() fileHandle_ = fopen(savePath_.c_str(), "wb"); if (!fileHandle_) { - WARN("AudioRecord: Could not create RAW file!"); + WARN("Could not create RAW file!"); return false; } - DEBUG("AudioRecord:setRawFile() : created RAW file."); + DEBUG("created RAW file."); return true; } +namespace { + std::string header_to_string(const wavhdr &hdr) + { + std::stringstream ss; + ss << hdr.riff << "\0 " + << hdr.file_size << " " + << hdr.wave << "\0 " + << hdr.fmt << "\0 " + << hdr.chunk_size << " " + << hdr.format_tag << " " + << hdr.num_chans << " " + << hdr.sample_rate << " " + << hdr.bytes_per_sec << " " + << hdr.bytes_per_samp << " " + << hdr.bits_per_samp << " " + << hdr.data << "\0 " + << hdr.data_length; + return ss.str(); + } +} + bool AudioRecord::setWavFile() { - DEBUG("AudioRecord: Create new wave file %s, sampling rate: %d", savePath_.c_str(), sndSmplRate_); + DEBUG("Create new wave file %s, sampling rate: %d", savePath_.c_str(), sndSmplRate_); fileHandle_ = fopen(savePath_.c_str(), "wb"); if (!fileHandle_) { - WARN("AudioRecord: Error: could not create WAV file."); + WARN("Could not create WAV file."); return false; } - struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1, - sndSmplRate_, 0, 2, 16, "dat", 0 - }; - - hdr.riff[3] = 'F'; - - hdr.wave[3] = 'E'; - - hdr.fmt[3] = ' '; - - hdr.data[3] = 'a'; - - hdr.num_chans = channels_; - - hdr.bits_per_samp = 16; - - hdr.bytes_per_samp = (SINT16)(channels_ * hdr.bits_per_samp / 8); - - hdr.bytes_per_sec = (SINT32)(hdr.sample_rate * hdr.bytes_per_samp); - + /* The text fields are NOT supposed to be null terminated, so we have to + * write them as arrays since strings enclosed in quotes include a + * null character */ + wavhdr hdr = {{'R', 'I', 'F', 'F'}, + 44, + {'W', 'A', 'V', 'E'}, + {'f','m', 't', ' '}, + 16, + 1, + channels_, + sndSmplRate_, + -1, /* initialized below */ + -1, /* initialized below */ + 16, + {'d', 'a', 't', 'a'}, + 0}; + + hdr.bytes_per_samp = channels_ * hdr.bits_per_samp / 8; + hdr.bytes_per_sec = hdr.sample_rate * hdr.bytes_per_samp; if (fwrite(&hdr, 4, 11, fileHandle_) != 11) { - WARN("AudioRecord: Error: could not write WAV header for file. "); + WARN("Could not write WAV header for file. "); return false; } - DEBUG("AudioRecord: created WAV file successfully."); - + DEBUG("Wrote wave header \"%s\"", header_to_string(hdr).c_str()); return true; } @@ -305,7 +314,7 @@ bool AudioRecord::openExistingRawFile() fileHandle_ = fopen(filename_.c_str(), "ab+"); if (!fileHandle_) { - WARN("AudioRecord: could not create RAW file!"); + WARN("could not create RAW file!"); return false; } @@ -314,37 +323,37 @@ bool AudioRecord::openExistingRawFile() bool AudioRecord::openExistingWavFile() { - DEBUG("%s(%s)\n", __PRETTY_FUNCTION__, filename_.c_str()); + DEBUG("Opening %s", filename_.c_str()); fileHandle_ = fopen(filename_.c_str(), "rb+"); if (!fileHandle_) { - WARN("AudioRecord: Error: could not open WAV file!"); + WARN("Could not open WAV file!"); return false; } if (fseek(fileHandle_, 40, SEEK_SET) != 0) // jump to data length - WARN("AudioRecord: Error: Couldn't seek offset 40 in the file "); + WARN("Couldn't seek offset 40 in the file "); if (fread(&byteCounter_, 4, 1, fileHandle_)) - WARN("AudioRecord: Error: bytecounter Read successfully "); + WARN("bytecounter Read successfully "); if (fseek(fileHandle_, 0 , SEEK_END) != 0) - WARN("AudioRecord: Error: Couldn't seek at the en of the file "); + WARN("Couldn't seek at the en of the file "); if (fclose(fileHandle_) != 0) - WARN("AudioRecord: Error: Can't close file r+ "); + WARN("Can't close file r+ "); fileHandle_ = fopen(filename_.c_str(), "ab+"); if (!fileHandle_) { - WARN("AudioRecord: Error: Could not createopen WAV file ab+!"); + WARN("Could not createopen WAV file ab+!"); return false; } if (fseek(fileHandle_, 4 , SEEK_END) != 0) - WARN("AudioRecord: Error: Couldn't seek at the en of the file "); + WARN("Couldn't seek at the en of the file "); return true; @@ -353,97 +362,53 @@ bool AudioRecord::openExistingWavFile() void AudioRecord::closeWavFile() { if (fileHandle_ == 0) { - DEBUG("AudioRecord: Can't closeWavFile, a file has not yet been opened!"); + DEBUG("Can't closeWavFile, a file has not yet been opened!"); return; } - DEBUG("AudioRecord: Close wave file"); + DEBUG("Close wave file"); SINT32 bytes = byteCounter_ * channels_; fseek(fileHandle_, 40, SEEK_SET); // jump to data length if (ferror(fileHandle_)) - WARN("AudioRecord: Error: can't reach offset 40 while closing"); + WARN("Can't reach offset 40 while closing"); fwrite(&bytes, sizeof(SINT32), 1, fileHandle_); if (ferror(fileHandle_)) - WARN("AudioRecord: Error: can't write bytes for data length "); + WARN("Can't write bytes for data length "); bytes = byteCounter_ * channels_ + 44; // + 44 for the wave header fseek(fileHandle_, 4, SEEK_SET); // jump to file size if (ferror(fileHandle_)) - WARN("AudioRecord: Error: can't reach offset 4"); + WARN("Can't reach offset 4"); fwrite(&bytes, 4, 1, fileHandle_); if (ferror(fileHandle_)) - WARN("AudioRecord: Error: can't reach offset 4"); + WARN("Can't reach offset 4"); if (fclose(fileHandle_) != 0) - WARN("AudioRecord: Error: can't close file"); -} - -void AudioRecord::recSpkrData(SFLDataFormat* buffer, int nSamples) -{ - if (recordingEnabled_) { - nbSamplesMic_ = nSamples; - - for (int i = 0; i < nbSamplesMic_; i++) - micBuffer_[i] = buffer[i]; - } -} - -void AudioRecord::recMicData(SFLDataFormat* buffer, int nSamples) -{ - if (recordingEnabled_) { - nbSamplesSpk_ = nSamples; - - for (int i = 0; i < nbSamplesSpk_; i++) - spkBuffer_[i] = buffer[i]; - - } + WARN("Can't close file"); } -void AudioRecord::recData(SFLDataFormat* buffer, int nSamples) +void AudioRecord::recData(SFLDataFormat* buffer, size_t nSamples) { if (recordingEnabled_) { if (fileHandle_ == 0) { - DEBUG("AudioRecord: Can't record data, a file has not yet been opened!"); + DEBUG("Can't record data, a file has not yet been opened!"); return; } - if (fwrite(buffer, sizeof(SFLDataFormat), nSamples, fileHandle_) != (unsigned int) nSamples) - WARN("AudioRecord: Could not record data! "); + if (fwrite(buffer, sizeof(SFLDataFormat), nSamples, fileHandle_) != nSamples) + WARN("Could not record data! "); else { fflush(fileHandle_); - byteCounter_ += (unsigned long)(nSamples*sizeof(SFLDataFormat)); - } - } -} - -void AudioRecord::recData(SFLDataFormat* buffer_1, SFLDataFormat* buffer_2, - int nSamples_1, int /*nSamples_2*/) -{ - if (recordingEnabled_) { - if (fileHandle_ == 0) { - DEBUG("AudioRecord: Can't record data, a file has not yet been opened!"); - return; + byteCounter_ += nSamples * sizeof(SFLDataFormat); } - - for (int k = 0; k < nSamples_1; k++) { - mixBuffer_[k] = (buffer_1[k]+buffer_2[k]); - - if (fwrite(&mixBuffer_[k], 2, 1, fileHandle_) != 1) - WARN("AudioRecord: Could not record data!"); - else - fflush(fileHandle_); - } - - byteCounter_ += (unsigned long)(nSamples_1 * sizeof(SFLDataFormat)); } } - diff --git a/daemon/src/audio/audiorecord.h b/daemon/src/audio/audiorecord.h index 03a9f6a7d3d274ea4976b30674165d804471f756..47bfa28ac303771cc0d47eb73a8d2458e65d1c2e 100644 --- a/daemon/src/audio/audiorecord.h +++ b/daemon/src/audio/audiorecord.h @@ -33,8 +33,9 @@ #include <string> #include <cstdlib> +#include <memory> -#include "global.h" +#include "sfl_types.h" #include "noncopyable.h" class AudioRecord { @@ -44,14 +45,7 @@ class AudioRecord { AudioRecord(); - ~AudioRecord(); - void setSndSamplingRate(int smplRate); - /** - * Get the recrding sampling rate - */ - int getSndSamplingRate() const; - void setRecordingOption(FILE_TYPE type, int sndSmplRate, const std::string &path); /** @@ -96,44 +90,19 @@ class AudioRecord { /** * Set recording flag */ - bool setRecording(); + void setRecording(); /** * Stop recording flag */ void stopRecording(); - - /** - * Record a chunk of data in an internal buffer - * @param buffer The data chunk to be recorded - * @param nSamples Number of samples (number of bytes) to be recorded - */ - void recSpkrData(SFLDataFormat* buffer, int nSamples); - - /** - * Record a chunk of data in an internal buffer - * @param buffer The data chunk to be recorded - * @param nSamples Number of samples (number of bytes) to be recorded - */ - void recMicData(SFLDataFormat* buffer, int nSamples); - /** * Record a chunk of data in an openend file * @param buffer The data chunk to be recorded * @param nSamples Number of samples (number of bytes) to be recorded */ - void recData(SFLDataFormat* buffer, int nSamples); - - /** - * Record a chunk of data in an openend file, Mix two differnet buffer - * @param buffer_1 The first data chunk to be recorded - * @param buffer_2 The second data chunk to be recorded - * @param nSamples_1 Number of samples (number of bytes) of buffer_1 - * @param nSamples_2 Number of samples (number of bytes) of buffer_2 - */ - void recData(SFLDataFormat* buffer_1, SFLDataFormat* buffer_2, int nSamples_1, int nSamples_2); - + void recData(SFLDataFormat* buffer, size_t nSamples); protected: @@ -206,7 +175,7 @@ class AudioRecord { /** * Maximum number of samples */ - int nbSamplesMax_; + static const int NB_SAMPLES_MAX = 3000; /** * Recording flage @@ -216,17 +185,17 @@ class AudioRecord { /** * Buffer used for mixing two channels */ - SFLDataFormat* mixBuffer_; + SFLDataFormat mixBuffer_[NB_SAMPLES_MAX]; /** * Buffer used to copy mic info */ - SFLDataFormat* micBuffer_; + SFLDataFormat micBuffer_[NB_SAMPLES_MAX]; /** * Buffer used to copy spkr info */ - SFLDataFormat* spkBuffer_; + SFLDataFormat spkBuffer_[NB_SAMPLES_MAX]; /** * Filename for this recording diff --git a/daemon/src/audio/audiorecorder.cpp b/daemon/src/audio/audiorecorder.cpp index 462c32165b74342434d0ebff8e44d25e469476c7..54a742179ae0e45943f65fffa50b92ac2756bd69 100644 --- a/daemon/src/audio/audiorecorder.cpp +++ b/daemon/src/audio/audiorecorder.cpp @@ -30,15 +30,17 @@ #include "audiorecorder.h" #include "mainbuffer.h" +#include "logger.h" +#include <sstream> #include <cassert> +#include <tr1/array> int AudioRecorder::count_ = 0; -AudioRecorder::AudioRecorder(AudioRecord *arec, MainBuffer *mb) : Thread(), - recorderId_(), mbuffer_(mb), arecord_(arec) +AudioRecorder::AudioRecorder(AudioRecord *arec, MainBuffer *mb) : ost::Thread(), + recorderId_(), mbuffer_(mb), arecord_(arec), running_(true) { assert(mb); - setCancel(cancelDeferred); ++count_; @@ -46,7 +48,7 @@ AudioRecorder::AudioRecorder(AudioRecord *arec, MainBuffer *mb) : Thread(), // convert count into string std::string s; - std::stringstream out; + std::ostringstream out; out << count_; s = out.str(); @@ -58,18 +60,17 @@ AudioRecorder::AudioRecorder(AudioRecord *arec, MainBuffer *mb) : Thread(), */ void AudioRecorder::run() { - int bufferLength = 10000; - SFLDataFormat buffer[bufferLength]; + const size_t BUFFER_LENGTH = 10000; + std::tr1::array<SFLDataFormat, BUFFER_LENGTH> buffer; + buffer.assign(0); - while (true) { - int availBytes = mbuffer_->availForGet(recorderId_); - int toGet = (availBytes < bufferLength) ? availBytes : bufferLength; - - mbuffer_->getData(buffer, toGet, recorderId_); + while (running_) { + size_t availBytes = mbuffer_->availForGet(recorderId_); + mbuffer_->getData(buffer.data(), std::min(availBytes, buffer.size()), recorderId_); if (availBytes > 0) - arecord_->recData(buffer, availBytes / sizeof(SFLDataFormat)); + arecord_->recData(buffer.data(), availBytes / sizeof(SFLDataFormat)); - sleep(20); + Thread::sleep(20); } } diff --git a/daemon/src/audio/audiorecorder.h b/daemon/src/audio/audiorecorder.h index eb7ccf1fe146b4d763befce1afdabe8eff9e8856..c417b4cc7bd8aaaf9969643fbdfa5f49e84b69eb 100644 --- a/daemon/src/audio/audiorecorder.h +++ b/daemon/src/audio/audiorecorder.h @@ -28,11 +28,11 @@ * as that of the covered work. */ -#ifndef __AUDIORECORDER_H_ -#define __AUDIORECORDER_H_ +#ifndef AUDIORECORDER_H_ +#define AUDIORECORDER_H_ #include <string> -#include <cc++/thread.h> +#include "cc_thread.h" #include "audiorecord.h" #include "noncopyable.h" @@ -44,6 +44,7 @@ class AudioRecorder : public ost::Thread { AudioRecorder(AudioRecord *arec, MainBuffer *mb); ~AudioRecorder() { + running_ = false; terminate(); } @@ -61,6 +62,7 @@ class AudioRecorder : public ost::Thread { std::string recorderId_; MainBuffer *mbuffer_; AudioRecord *arecord_; + bool running_; }; #endif diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.cpp b/daemon/src/audio/audiortp/audio_rtp_factory.cpp index 5ce37ce1f53c08fc342d4b60daff3beefc3173dd..c723f812528b5ec30057c3fb1ad6a1917b704cef 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_factory.cpp @@ -28,24 +28,26 @@ * as that of the covered work. */ - - #include "audio_rtp_factory.h" #include "audio_zrtp_session.h" -#include "audio_srtp_session.h" #include "audio_symmetric_rtp_session.h" #include "manager.h" #include "sip/sdp.h" #include "sip/sipcall.h" #include "sip/sipaccount.h" #include "sip/sdes_negotiator.h" +#include "logger.h" namespace sfl { AudioRtpFactory::AudioRtpFactory(SIPCall *ca) : rtpSession_(NULL), - audioRtpThreadMutex_(), srtpEnabled_(false), - keyExchangeProtocol_(Symmetric), helloHashEnabled_(false), - remoteContext_(NULL), localContext_(NULL), ca_(ca) + audioRtpThreadMutex_(), srtpEnabled_(false), helloHashEnabled_(false), + cachedLocalMasterKey_(MAX_MASTER_KEY_LENGTH), + cachedLocalMasterSalt_(MAX_MASTER_SALT_LENGTH), + cachedRemoteMasterKey_(MAX_MASTER_KEY_LENGTH), + cachedRemoteMasterSalt_(MAX_MASTER_SALT_LENGTH), + remoteOfferIsSet_(false), ca_(ca), + keyExchangeProtocol_(NONE) {} AudioRtpFactory::~AudioRtpFactory() @@ -53,8 +55,9 @@ AudioRtpFactory::~AudioRtpFactory() delete rtpSession_; } -void AudioRtpFactory::initAudioRtpConfig() +void AudioRtpFactory::initConfig() { + DEBUG("AudioRtpFactory: init config"); if (rtpSession_ != NULL) stop(); @@ -65,75 +68,64 @@ void AudioRtpFactory::initAudioRtpConfig() if (account) { srtpEnabled_ = account->getSrtpEnabled(); std::string key(account->getSrtpKeyExchange()); - - if (key == "sdes") - keyExchangeProtocol_ = Sdes; - else if (key == "zrtp") - keyExchangeProtocol_ = Zrtp; - else - keyExchangeProtocol_ = Symmetric; - + if (srtpEnabled_) { + if (key == "sdes") + keyExchangeProtocol_ = SDES; + else if (key == "zrtp") + keyExchangeProtocol_ = ZRTP; + } else { + keyExchangeProtocol_ = NONE; + } helloHashEnabled_ = account->getZrtpHelloHash(); } else { srtpEnabled_ = false; - keyExchangeProtocol_ = Symmetric; + keyExchangeProtocol_ = NONE; helloHashEnabled_ = false; } } -void AudioRtpFactory::initAudioSymmetricRtpSession() +void AudioRtpFactory::initSession() { + DEBUG("AudioRtpFactory: init session"); ost::MutexLock m(audioRtpThreadMutex_); if (srtpEnabled_) { - std::string zidFilename(Manager::instance().voipPreferences.getZidFile()); + const std::string zidFilename(Manager::instance().voipPreferences.getZidFile()); switch (keyExchangeProtocol_) { - case Zrtp: - rtpSession_ = new AudioZrtpSession(ca_, zidFilename); + case ZRTP: + rtpSession_ = new AudioZrtpSession(*ca_, zidFilename); // TODO: be careful with that. The hello hash is computed asynchronously. Maybe it's // not even available at that point. if (helloHashEnabled_) ca_->getLocalSDP()->setZrtpHash(static_cast<AudioZrtpSession *>(rtpSession_)->getHelloHash()); break; - case Sdes: - rtpSession_ = new AudioSrtpSession(ca_); + case SDES: + rtpSession_ = new AudioSrtpSession(*ca_); break; default: throw UnsupportedRtpSessionType("Unsupported Rtp Session Exception Type!"); } } else - rtpSession_ = new AudioSymmetricRtpSession(ca_); + rtpSession_ = new AudioSymmetricRtpSession(*ca_); } -void AudioRtpFactory::start(AudioCodec* audiocodec) +void sfl::AudioRtpFactory::start(AudioCodec* audiocodec) { if (rtpSession_ == NULL) - throw AudioRtpFactoryException("AudioRtpFactory: Error: RTP session was null when trying to start audio thread"); - - if (rtpSession_->getAudioRtpType() == Sdes) - if (localContext_ and remoteContext_) - static_cast<AudioSrtpSession *>(rtpSession_)->restoreCryptoContext(localContext_, remoteContext_); + throw AudioRtpFactoryException("RTP session was null when trying to start audio thread"); - if (rtpSession_->startRtpThread(audiocodec) != 0) - throw AudioRtpFactoryException("AudioRtpFactory: Error: Failed to start AudioZrtpSession thread"); + if (rtpSession_->startRtpThread(*audiocodec) != 0) + throw AudioRtpFactoryException("Failed to start AudioRtpSession thread"); } void AudioRtpFactory::stop() { ost::MutexLock mutex(audioRtpThreadMutex_); - if (rtpSession_ == NULL) - return; - - if (rtpSession_->getAudioRtpType() == Sdes) { - localContext_ = static_cast<AudioSrtpSession*>(rtpSession_)->localCryptoCtx_; - remoteContext_ = static_cast<AudioSrtpSession*>(rtpSession_)->remoteCryptoCtx_; - } - delete rtpSession_; rtpSession_ = NULL; } @@ -141,7 +133,7 @@ void AudioRtpFactory::stop() int AudioRtpFactory::getSessionMedia() { if (rtpSession_ == NULL) - throw AudioRtpFactoryException("AudioRtpFactory: Error: RTP session was null when trying to get session media type"); + throw AudioRtpFactoryException("RTP session was null when trying to get session media type"); return rtpSession_->getCodecPayloadType(); } @@ -149,9 +141,9 @@ int AudioRtpFactory::getSessionMedia() void AudioRtpFactory::updateSessionMedia(AudioCodec *audiocodec) { if (rtpSession_ == NULL) - throw AudioRtpFactoryException("AudioRtpFactory: Error: rtpSession_ was null when trying to update IP address"); + throw AudioRtpFactoryException("rtpSession_ was NULL when trying to update IP address"); - rtpSession_->updateSessionMedia(audiocodec); + rtpSession_->updateSessionMedia(*audiocodec); } void AudioRtpFactory::updateDestinationIpAddress() @@ -162,25 +154,41 @@ void AudioRtpFactory::updateDestinationIpAddress() sfl::AudioZrtpSession * AudioRtpFactory::getAudioZrtpSession() { - if (rtpSession_->getAudioRtpType() == Zrtp) + if (keyExchangeProtocol_ == ZRTP) return static_cast<AudioZrtpSession *>(rtpSession_); else - throw AudioRtpFactoryException("RTP: Error: rtpSession_ is NULL in getAudioZrtpSession"); + throw AudioRtpFactoryException("rtpSession_ is NULL in getAudioZrtpSession"); } void sfl::AudioRtpFactory::initLocalCryptoInfo() { - if (rtpSession_ && rtpSession_->getAudioRtpType() == Sdes) { - static_cast<AudioSrtpSession *>(rtpSession_)->initLocalCryptoInfo(); - ca_->getLocalSDP()->setLocalSdpCrypto(static_cast<AudioSrtpSession *>(rtpSession_)->getLocalCryptoInfo()); + DEBUG("AudioRtpFactory: Init local crypto info"); + if (rtpSession_ && keyExchangeProtocol_ == SDES) { + AudioSrtpSession *srtp = static_cast<AudioSrtpSession*>(rtpSession_); + // the context is invalidated and deleted by the call to initLocalCryptoInfo + srtp->initLocalCryptoInfo(); + ca_->getLocalSDP()->setLocalSdpCrypto(srtp->getLocalCryptoInfo()); + } +} + +void sfl::AudioRtpFactory::initLocalCryptoInfoOnOffHold() +{ + DEBUG("AudioRtpFactory: Init local crypto info"); + if (rtpSession_ && keyExchangeProtocol_ == SDES) { + AudioSrtpSession *srtp = static_cast<AudioSrtpSession*>(rtpSession_); + // the context is invalidated and deleted by the call to initLocalCryptoInfo + srtp->initLocalCryptoInfoOnOffhold(); + ca_->getLocalSDP()->setLocalSdpCrypto(srtp->getLocalCryptoInfo()); } } + void AudioRtpFactory::setRemoteCryptoInfo(sfl::SdesNegotiator& nego) { - if (rtpSession_ && rtpSession_->getAudioRtpType() == Sdes) - static_cast<AudioSrtpSession *>(rtpSession_)->setRemoteCryptoInfo(nego); - else + if (rtpSession_ and keyExchangeProtocol_ == SDES) { + AudioSrtpSession *srtp = static_cast<AudioSrtpSession *>(rtpSession_); + srtp->setRemoteCryptoInfo(nego); + } else throw AudioRtpFactoryException("RTP: Error: rtpSession_ is NULL in setRemoteCryptoInfo"); } @@ -195,4 +203,23 @@ void AudioRtpFactory::sendDtmfDigit(int digit) rtpSession_->putDtmfEvent(digit); } +void sfl::AudioRtpFactory::saveLocalContext() +{ + if (rtpSession_ and keyExchangeProtocol_ == SDES) { + AudioSrtpSession *srtp = dynamic_cast<AudioSrtpSession *>(rtpSession_); + assert(srtp); + cachedLocalMasterKey_ = srtp->getLocalMasterKey(); + cachedLocalMasterSalt_ = srtp->getLocalMasterSalt(); + } +} + +void sfl::AudioRtpFactory::restoreLocalContext() +{ + if (rtpSession_ and keyExchangeProtocol_ == SDES) { + AudioSrtpSession *srtp = dynamic_cast<AudioSrtpSession *>(rtpSession_); + assert(srtp); + srtp->setLocalMasterKey(cachedLocalMasterKey_); + srtp->setLocalMasterSalt(cachedLocalMasterSalt_); + } +} } diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.h b/daemon/src/audio/audiortp/audio_rtp_factory.h index 9e8ca514ceb67216b48bb6408de2f1eb88d0f89d..172cd1eaddf6bb656674c43a2ce2f281d982ba72 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.h +++ b/daemon/src/audio/audiortp/audio_rtp_factory.h @@ -31,10 +31,12 @@ #ifndef __AUDIO_RTP_FACTORY_H__ #define __AUDIO_RTP_FACTORY_H__ -#include <stdexcept> -#include <cc++/thread.h> #include <ccrtp/CryptoContext.h> +#include <stdexcept> +#include <tr1/array> +#include "cc_thread.h" #include "audio_rtp_session.h" +#include "audio_srtp_session.h" #include "noncopyable.h" #include "sip/sdes_negotiator.h" @@ -62,15 +64,15 @@ class AudioRtpFactory { AudioRtpFactory(SIPCall *ca); ~AudioRtpFactory(); - void initAudioRtpConfig(); + void initConfig(); /** * Lazy instantiation method. Create a new RTP session of a given * type according to the content of the configuration file. * @param ca A pointer on a SIP call - * @return A new AudioSymmetricRtpSession object + * @return A new AudioRtpSession object */ - void initAudioSymmetricRtpSession(); + void initSession(); /** * Start the audio rtp thread of the type specified in the configuration @@ -103,7 +105,7 @@ class AudioRtpFactory { void updateDestinationIpAddress(); bool isSdesEnabled() const { - return srtpEnabled_ and keyExchangeProtocol_ == sfl::Sdes; + return srtpEnabled_ and keyExchangeProtocol_ == SDES; } /** @@ -121,6 +123,7 @@ class AudioRtpFactory { sfl::AudioZrtpSession * getAudioZrtpSession(); void initLocalCryptoInfo(); + void initLocalCryptoInfoOnOffHold(); /** * Set remote cryptographic info. Should be called after negotiation in SDP @@ -138,30 +141,41 @@ class AudioRtpFactory { */ void sendDtmfDigit(int digit); + void saveLocalContext(); + + void restoreLocalContext(); + private: NON_COPYABLE(AudioRtpFactory); + enum KeyExchangeProtocol { NONE, SDES, ZRTP }; AudioRtpSession *rtpSession_; ost::Mutex audioRtpThreadMutex_; - // Field used when initializinga udio rtp session + // Field used when initializing audio rtp session // May be set manually or from config using initAudioRtpConfig bool srtpEnabled_; - // Field used when initializinga udio rtp session - // May be set manually or from config using initAudioRtpConfig - RtpMethod keyExchangeProtocol_; - // Field used when initializinga udio rtp session // May be set manually or from config using initAudioRtpConfig bool helloHashEnabled_; - /** Remote srtp crypto context to be set into incoming data queue. */ - ost::CryptoContext *remoteContext_; + /** local master key for outgoing packet encryption **/ + std::vector<uint8> cachedLocalMasterKey_; + + /** local master salt for outgoing packet encryption **/ + std::vector<uint8> cachedLocalMasterSalt_; + + /** remote master key for incoming packet decryption **/ + std::vector<uint8> cachedRemoteMasterKey_; + + /** remote master salt for incoming packet decryption **/ + std::vector<uint8> cachedRemoteMasterSalt_; - /** Local srtp crypto context to be set into outgoing data queue. */ - ost::CryptoContext *localContext_; + /** Used to make sure remote crypto context not initialized twice. */ + bool remoteOfferIsSet_; SIPCall *ca_; + KeyExchangeProtocol keyExchangeProtocol_; }; } #endif // __AUDIO_RTP_FACTORY_H__ diff --git a/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp b/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp index 8ce03be48914e6902196162e5b23d51cba85c0d1..041181db39407afebfc2e400a658076f4897fb1d 100644 --- a/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp @@ -29,51 +29,72 @@ #include "audio_rtp_record_handler.h" #include <fstream> +#include <algorithm> +#include "logger.h" #include "sip/sipcall.h" #include "audio/audiolayer.h" #include "manager.h" +#include <fstream> + namespace sfl { -static const SFLDataFormat initFadeinFactor = 32000; +static const SFLDataFormat INIT_FADE_IN_FACTOR = 32000; + +#ifdef RECTODISK +std::ofstream rtpResampled ("testRtpOutputResampled.raw", std::ifstream::binary); +std::ofstream rtpNotResampled("testRtpOutput.raw", std::ifstream::binary); +#endif AudioRtpRecord::AudioRtpRecord() : audioCodec_(0) , audioCodecMutex_() , codecPayloadType_(0) , hasDynamicPayloadType_(false) - , converter_(0) + , decData_() // std::tr1::arrays will be 0-initialized + , resampledData_() + , encodedData_() + , converterEncode_(0) + , converterDecode_(0) , codecSampleRate_(0) , codecFrameSize_(0) , converterSamplingRate_(0) , dtmfQueue_() - , micAmplFactor_(initFadeinFactor) - , noiseSuppress_(0) + , fadeFactor_(INIT_FADE_IN_FACTOR) + , noiseSuppressEncode_(0) + , noiseSuppressDecode_(0) , audioProcessMutex_() , callId_("") , dtmfPayloadType_(101) // same as Asterisk -{ - memset(decData_, 0x0, sizeof decData_); - memset(resampledData_, 0x0, sizeof resampledData_); - memset(encodedData_, 0x0, sizeof encodedData_); -} +{} AudioRtpRecord::~AudioRtpRecord() { - delete converter_; +#ifdef RECTODISK + rtpResampled.close(); + rtpNotResampled.close(); +#endif + + delete converterEncode_; + delete converterDecode_; delete audioCodec_; - delete noiseSuppress_; + delete noiseSuppressEncode_; + delete noiseSuppressDecode_; } -AudioRtpRecordHandler::AudioRtpRecordHandler(SIPCall *ca) : audioRtpRecord_(), id_(ca->getCallId()), echoCanceller(ca->getMemoryPool()), gainController(8000, -10.0) +AudioRtpRecordHandler::AudioRtpRecordHandler(SIPCall &call) : + audioRtpRecord_(), + id_(call.getCallId()), + echoCanceller(call.getMemoryPool()), + gainController(8000, -10.0) {} AudioRtpRecordHandler::~AudioRtpRecordHandler() {} -void AudioRtpRecordHandler::setRtpMedia(AudioCodec* audioCodec) +void AudioRtpRecordHandler::setRtpMedia(AudioCodec *audioCodec) { ost::MutexLock lock(audioRtpRecord_.audioCodecMutex_); @@ -93,15 +114,19 @@ void AudioRtpRecordHandler::initBuffers() // initialize SampleRate converter using AudioLayer's sampling rate // (internal buffers initialized with maximal sampling rate and frame size) - delete audioRtpRecord_.converter_; - audioRtpRecord_.converter_ = new SamplerateConverter(getCodecSampleRate()); + delete audioRtpRecord_.converterEncode_; + audioRtpRecord_.converterEncode_ = new SamplerateConverter(getCodecSampleRate()); + delete audioRtpRecord_.converterDecode_; + audioRtpRecord_.converterDecode_ = new SamplerateConverter(getCodecSampleRate()); } void AudioRtpRecordHandler::initNoiseSuppress() { ost::MutexLock lock(audioRtpRecord_.audioProcessMutex_); - delete audioRtpRecord_.noiseSuppress_; - audioRtpRecord_.noiseSuppress_ = new NoiseSuppress(getCodecFrameSize(), getCodecSampleRate()); + delete audioRtpRecord_.noiseSuppressEncode_; + audioRtpRecord_.noiseSuppressEncode_ = new NoiseSuppress(getCodecFrameSize(), getCodecSampleRate()); + delete audioRtpRecord_.noiseSuppressDecode_; + audioRtpRecord_.noiseSuppressDecode_ = new NoiseSuppress(getCodecFrameSize(), getCodecSampleRate()); } void AudioRtpRecordHandler::putDtmfEvent(int digit) @@ -109,20 +134,12 @@ void AudioRtpRecordHandler::putDtmfEvent(int digit) audioRtpRecord_.dtmfQueue_.push_back(digit); } -#ifdef DUMP_PROCESS_DATA_ENCODE -std::ofstream teststream("test_process_data_encode.raw"); -#endif - int AudioRtpRecordHandler::processDataEncode() { - SFLDataFormat *micData = audioRtpRecord_.decData_; - unsigned char *micDataEncoded = audioRtpRecord_.encodedData_; - SFLDataFormat *micDataConverted = audioRtpRecord_.resampledData_; - int codecSampleRate = getCodecSampleRate(); int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - double resampleFactor = (double)mainBufferSampleRate / codecSampleRate; + double resampleFactor = (double) mainBufferSampleRate / codecSampleRate; // compute nb of byte to get coresponding to 1 audio frame int samplesToGet = resampleFactor * getCodecFrameSize(); @@ -131,65 +148,78 @@ int AudioRtpRecordHandler::processDataEncode() if (Manager::instance().getMainBuffer()->availForGet(id_) < bytesToGet) return 0; + SFLDataFormat *micData = audioRtpRecord_.decData_.data(); int bytes = Manager::instance().getMainBuffer()->getData(micData, bytesToGet, id_); +#ifdef RECTODISK + rtpNotResampled.write((const char *)micData, bytes); +#endif + if (bytes != bytesToGet) { - ERROR("%s : asked %d bytes from mainbuffer, got %d", __PRETTY_FUNCTION__, bytesToGet, bytes); + ERROR("Asked for %d bytes from mainbuffer, got %d", bytesToGet, bytes); return 0; } int samples = bytesToGet / sizeof(SFLDataFormat); - fadeIn(micData, samples, &audioRtpRecord_.micAmplFactor_); + audioRtpRecord_.fadeInDecodedData(samples); if (Manager::instance().getEchoCancelState()) echoCanceller.getData(micData); -#ifdef DUMP_PROCESS_DATA_ENCODE - teststream.write(reinterpret_cast<char *>(micData), bytesToGet); -#endif - SFLDataFormat *out = micData; if (codecSampleRate != mainBufferSampleRate) { - out = micDataConverted; - audioRtpRecord_.converter_->resample(micData, micDataConverted, codecSampleRate, mainBufferSampleRate, samplesToGet); + assert(audioRtpRecord_.converterEncode_); + + audioRtpRecord_.converterEncode_->resample(micData, + audioRtpRecord_.resampledData_.data(), + audioRtpRecord_.resampledData_.size(), + mainBufferSampleRate, codecSampleRate, + samplesToGet); + +#ifdef RECTODISK + rtpResampled.write((const char *)audioRtpRecord_.resampledData_.data(), samplesToGet*sizeof(SFLDataFormat)/2 ); +#endif + + out = audioRtpRecord_.resampledData_.data(); } if (Manager::instance().audioPreference.getNoiseReduce()) { ost::MutexLock lock(audioRtpRecord_.audioProcessMutex_); - audioRtpRecord_.noiseSuppress_->process(micData, getCodecFrameSize()); + assert(audioRtpRecord_.noiseSuppressEncode_); + audioRtpRecord_.noiseSuppressEncode_->process(micData, getCodecFrameSize()); } - int compSize; { ost::MutexLock lock(audioRtpRecord_.audioCodecMutex_); - compSize = audioRtpRecord_.audioCodec_->encode(micDataEncoded, out, getCodecFrameSize()); + unsigned char *micDataEncoded = audioRtpRecord_.encodedData_.data(); + return audioRtpRecord_.audioCodec_->encode(micDataEncoded, out, getCodecFrameSize()); } - - return compSize; } -void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, unsigned int size, int payloadType) +void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, size_t size, int payloadType) { if (getCodecPayloadType() != payloadType) return; - int codecSampleRate = getCodecSampleRate(); - - SFLDataFormat *spkrDataDecoded = audioRtpRecord_.decData_; - SFLDataFormat *spkrDataConverted = audioRtpRecord_.resampledData_; - - int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - - int inSamples; + int inSamples = 0; + size = std::min(size, audioRtpRecord_.decData_.size()); + SFLDataFormat *spkrDataDecoded = audioRtpRecord_.decData_.data(); { ost::MutexLock lock(audioRtpRecord_.audioCodecMutex_); // Return the size of data in samples - inSamples = audioRtpRecord_.audioCodec_->decode(spkrDataDecoded , spkrData , size); + inSamples = audioRtpRecord_.audioCodec_->decode(spkrDataDecoded, spkrData, size); + } + + if (Manager::instance().audioPreference.getNoiseReduce()) { + ost::MutexLock lock(audioRtpRecord_.audioProcessMutex_); + assert(audioRtpRecord_.noiseSuppressDecode_); + audioRtpRecord_.noiseSuppressDecode_->process(spkrDataDecoded, getCodecFrameSize()); } - fadeIn(spkrDataDecoded, inSamples, &audioRtpRecord_.micAmplFactor_); + + audioRtpRecord_.fadeInDecodedData(inSamples); // Normalize incomming signal gainController.process(spkrDataDecoded, inSamples); @@ -197,12 +227,17 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, unsigned SFLDataFormat *out = spkrDataDecoded; int outSamples = inSamples; + int codecSampleRate = getCodecSampleRate(); + int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); + // test if resampling is required if (codecSampleRate != mainBufferSampleRate) { + out = audioRtpRecord_.resampledData_.data(); // Do sample rate conversion outSamples = ((float) inSamples * ((float) mainBufferSampleRate / (float) codecSampleRate)); - audioRtpRecord_.converter_->resample(spkrDataDecoded, spkrDataConverted, codecSampleRate, mainBufferSampleRate, inSamples); - out = spkrDataConverted; + audioRtpRecord_.converterDecode_->resample(spkrDataDecoded, out, + audioRtpRecord_.resampledData_.size(), codecSampleRate, + mainBufferSampleRate, inSamples); } if (Manager::instance().getEchoCancelState()) @@ -211,15 +246,17 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, unsigned Manager::instance().getMainBuffer()->putData(out, outSamples * sizeof(SFLDataFormat), id_); } -void AudioRtpRecordHandler::fadeIn(SFLDataFormat *audio, int size, SFLDataFormat *factor) +void AudioRtpRecord::fadeInDecodedData(size_t size) { - // if factor reach 0, this function should have no effect - if (*factor <= 0) + // if factor reaches 0, this function should have no effect + if (fadeFactor_ <= 0 or size > decData_.size()) return; - while (size) - audio[--size] /= *factor; + std::transform(decData_.begin(), decData_.begin() + size, decData_.begin(), + std::bind1st(std::divides<double>(), fadeFactor_)); - *factor /= FADEIN_STEP_SIZE; + // Factor used to increase volume in fade in + const SFLDataFormat FADEIN_STEP_SIZE = 4; + fadeFactor_ /= FADEIN_STEP_SIZE; } } diff --git a/daemon/src/audio/audiortp/audio_rtp_record_handler.h b/daemon/src/audio/audiortp/audio_rtp_record_handler.h index 9012049a133d1b279448835ba31e3c5d7bcb4a75..3f3a7ec649c69c5fdf2cb76e354580e1299c36f3 100644 --- a/daemon/src/audio/audiortp/audio_rtp_record_handler.h +++ b/daemon/src/audio/audiortp/audio_rtp_record_handler.h @@ -34,6 +34,7 @@ using std::ptrdiff_t; #include <ccrtp/rtp.h> +#include <tr1/array> #include <list> class SIPCall; @@ -50,9 +51,6 @@ namespace sfl { // Frequency (in packet number) #define RTP_TIMESTAMP_RESET_FREQ 100 -// Factor use to increase volume in fade in -#define FADEIN_STEP_SIZE 4; - static const int schedulingTimeout = 4000; static const int expireTimeout = 1000000; @@ -72,7 +70,7 @@ timeval2microtimeout(const timeval& t) /** * Class meant to store internal data in order to encode/decode, * resample, process, and packetize audio streams. This class should not be - * handled directly. Use AudioRtpRecorrdHandeler + * handled directly. Use AudioRtpRecordHandler */ class AudioRtpRecord { public: @@ -83,27 +81,36 @@ class AudioRtpRecord { ost::Mutex audioCodecMutex_; int codecPayloadType_; bool hasDynamicPayloadType_; - SFLDataFormat decData_[DEC_BUFFER_SIZE]; - SFLDataFormat resampledData_[DEC_BUFFER_SIZE]; - unsigned char encodedData_[DEC_BUFFER_SIZE]; - SamplerateConverter *converter_; + std::tr1::array<SFLDataFormat, DEC_BUFFER_SIZE> decData_; +// FIXME: resampledData should be resized as needed + std::tr1::array<SFLDataFormat, DEC_BUFFER_SIZE * 4> resampledData_; + std::tr1::array<unsigned char, DEC_BUFFER_SIZE> encodedData_; + SamplerateConverter *converterEncode_; + SamplerateConverter *converterDecode_; int codecSampleRate_; int codecFrameSize_; int converterSamplingRate_; std::list<int> dtmfQueue_; - SFLDataFormat micAmplFactor_; - NoiseSuppress *noiseSuppress_; + SFLDataFormat fadeFactor_; + NoiseSuppress *noiseSuppressEncode_; + NoiseSuppress *noiseSuppressDecode_; ost::Mutex audioProcessMutex_; std::string callId_; unsigned int dtmfPayloadType_; + private: + friend class AudioRtpRecordHandler; + /** + * Ramp In audio data to avoid audio click from peer + */ + void fadeInDecodedData(size_t size); NON_COPYABLE(AudioRtpRecord); }; class AudioRtpRecordHandler { public: - AudioRtpRecordHandler(SIPCall *); + AudioRtpRecordHandler(SIPCall &); virtual ~AudioRtpRecordHandler(); /** @@ -132,11 +139,11 @@ class AudioRtpRecordHandler { } int DtmfPending() const { - return audioRtpRecord_.dtmfQueue_.size() > 0; + return not audioRtpRecord_.dtmfQueue_.empty(); } const unsigned char *getMicDataEncoded() const { - return audioRtpRecord_.encodedData_; + return audioRtpRecord_.encodedData_.data(); } void initBuffers(); @@ -151,12 +158,7 @@ class AudioRtpRecordHandler { /** * Decode audio data received from peer */ - void processDataDecode(unsigned char * spkrData, unsigned int size, int payloadType); - - /** - * Ramp In audio data to avoid audio click from peer - */ - void fadeIn(SFLDataFormat *audio, int size, SFLDataFormat *factor); + void processDataDecode(unsigned char * spkrData, size_t size, int payloadType); void setDtmfPayloadType(unsigned int payloadType) { audioRtpRecord_.dtmfPayloadType_ = payloadType; @@ -169,7 +171,7 @@ class AudioRtpRecordHandler { void putDtmfEvent(int digit); protected: - AudioRtpRecord audioRtpRecord_; + AudioRtpRecord audioRtpRecord_; private: diff --git a/daemon/src/audio/audiortp/audio_rtp_session.cpp b/daemon/src/audio/audiortp/audio_rtp_session.cpp index 2a6bea42e7e2f404cbe47751b1a2c1e3fb857a22..6d70bcd0c6d9fb7040e010c29e66b3a2a201fc07 100644 --- a/daemon/src/audio/audiortp/audio_rtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_session.cpp @@ -33,39 +33,34 @@ */ #include "audio_rtp_session.h" -#include "audio_symmetric_rtp_session.h" - +#include "logger.h" #include "sip/sdp.h" #include "sip/sipcall.h" -#include "audio/audiolayer.h" -#include <ccrtp/rtp.h> #include <ccrtp/oqueue.h> #include "manager.h" namespace sfl { -AudioRtpSession::AudioRtpSession(SIPCall * sipcall, RtpMethod type, ost::RTPDataQueue *queue, ost::Thread *thread) : - AudioRtpRecordHandler(sipcall) - , ca_(sipcall) - , type_(type) - , remote_ip_() - , remote_port_(0) +AudioRtpSession::AudioRtpSession(SIPCall &call, ost::RTPDataQueue &queue, ost::Thread &thread) : + AudioRtpRecordHandler(call) + , call_(call) , timestamp_(0) , timestampIncrement_(0) - , timestampCount_(0) - , isStarted_(false) , queue_(queue) + , isStarted_(false) + , remote_ip_() + , remote_port_(0) + , timestampCount_(0) , thread_(thread) { - assert(ca_); - queue_->setTypeOfService(ost::RTPDataQueue::tosEnhanced); + queue_.setTypeOfService(ost::RTPDataQueue::tosEnhanced); } AudioRtpSession::~AudioRtpSession() { - queue_->disableStack(); + queue_.disableStack(); } -void AudioRtpSession::updateSessionMedia(AudioCodec *audioCodec) +void AudioRtpSession::updateSessionMedia(AudioCodec &audioCodec) { int lastSamplingRate = audioRtpRecord_.codecSampleRate_; @@ -74,15 +69,15 @@ void AudioRtpSession::updateSessionMedia(AudioCodec *audioCodec) Manager::instance().audioSamplingRateChanged(audioRtpRecord_.codecSampleRate_); if (lastSamplingRate != audioRtpRecord_.codecSampleRate_) { - DEBUG("AudioRtpSession: Update noise suppressor with sampling rate %d and frame size %d", getCodecSampleRate(), getCodecFrameSize()); + DEBUG("Update noise suppressor with sampling rate %d and frame size %d", + getCodecSampleRate(), getCodecFrameSize()); initNoiseSuppress(); } - } -void AudioRtpSession::setSessionMedia(AudioCodec *audioCodec) +void AudioRtpSession::setSessionMedia(AudioCodec &audioCodec) { - setRtpMedia(audioCodec); + setRtpMedia(&audioCodec); // store codec info locally int payloadType = getCodecPayloadType(); @@ -96,26 +91,28 @@ void AudioRtpSession::setSessionMedia(AudioCodec *audioCodec) else timestampIncrement_ = frameSize; - DEBUG("AudioRptSession: Codec payload: %d", payloadType); - DEBUG("AudioSymmetricRtpSession: Codec sampling rate: %d", smplRate); - DEBUG("AudioSymmetricRtpSession: Codec frame size: %d", frameSize); - DEBUG("AudioSymmetricRtpSession: RTP timestamp increment: %d", timestampIncrement_); + DEBUG("Codec payload: %d", payloadType); + DEBUG("Codec sampling rate: %d", smplRate); + DEBUG("Codec frame size: %d", frameSize); + DEBUG("RTP timestamp increment: %d", timestampIncrement_); if (payloadType == g722PayloadType) { - DEBUG("AudioSymmetricRtpSession: Setting G722 payload format"); - queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, g722RtpClockRate)); + DEBUG("Setting G722 payload format"); + queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, g722RtpClockRate)); } else { if (dynamic) { - DEBUG("AudioSymmetricRtpSession: Setting dynamic payload format"); - queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, smplRate)); + DEBUG("Setting dynamic payload format"); + queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, smplRate)); } else { - DEBUG("AudioSymmetricRtpSession: Setting static payload format"); - queue_->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) payloadType)); + DEBUG("Setting static payload format"); + queue_.setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) payloadType)); } } +} - if (type_ != Zrtp) - ca_->setRecordingSmplRate(getCodecSampleRate()); +void AudioRtpSession::incrementTimestampForDTMF() +{ + timestamp_ += timestampIncrement_; } void AudioRtpSession::sendDtmfEvent() @@ -129,34 +126,35 @@ void AudioRtpSession::sendDtmfEvent() audioRtpRecord_.dtmfQueue_.pop_front(); - DEBUG("AudioRtpSession: Send RTP Dtmf (%d)", payload.event); + DEBUG("Send RTP Dtmf (%d)", payload.event); - timestamp_ += (type_ == Zrtp) ? 160 : timestampIncrement_; + incrementTimestampForDTMF(); // discard equivalent size of audio processDataEncode(); // change Payload type for DTMF payload - queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) getDtmfPayloadType(), 8000)); + queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) getDtmfPayloadType(), 8000)); - queue_->setMark(true); - queue_->sendImmediate(timestamp_, (const unsigned char *)(&payload), sizeof(payload)); - queue_->setMark(false); + queue_.setMark(true); + queue_.sendImmediate(timestamp_, (const unsigned char *)(&payload), sizeof(payload)); + queue_.setMark(false); // get back the payload to audio - queue_->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) getCodecPayloadType())); + const ost::StaticPayloadFormat pf(static_cast<ost::StaticPayloadType>(getCodecPayloadType())); + queue_.setPayloadFormat(pf); } void AudioRtpSession::receiveSpeakerData() { - const ost::AppDataUnit* adu = queue_->getData(queue_->getFirstTimestamp()); + const ost::AppDataUnit* adu = queue_.getData(queue_.getFirstTimestamp()); if (!adu) return; unsigned char* spkrDataIn = (unsigned char*) adu->getData(); // data in char - unsigned int size = adu->getSize(); // size in char + size_t size = adu->getSize(); // size in char // DTMF over RTP, size must be over 4 in order to process it as voice data if (size > 4) @@ -166,66 +164,63 @@ void AudioRtpSession::receiveSpeakerData() } - void AudioRtpSession::sendMicData() { int compSize = processDataEncode(); // if no data return - if (!compSize) + if (compSize == 0) return; // Increment timestamp for outgoing packet timestamp_ += timestampIncrement_; - if (type_ == Zrtp) - queue_->putData(timestamp_, getMicDataEncoded(), compSize); - - // putData put the data on RTP queue, sendImmediate bypass this queue - queue_->sendImmediate(timestamp_, getMicDataEncoded(), compSize); + // putData puts the data on RTP queue, sendImmediate bypass this queue + queue_.sendImmediate(timestamp_, getMicDataEncoded(), compSize); } void AudioRtpSession::setSessionTimeouts() { - DEBUG("AudioRtpSession: Set session scheduling timeout (%d) and expireTimeout (%d)", sfl::schedulingTimeout, sfl::expireTimeout); + DEBUG("Set session scheduling timeout (%d) and expireTimeout (%d)", + sfl::schedulingTimeout, sfl::expireTimeout); - queue_->setSchedulingTimeout(sfl::schedulingTimeout); - queue_->setExpireTimeout(sfl::expireTimeout); + queue_.setSchedulingTimeout(sfl::schedulingTimeout); + queue_.setExpireTimeout(sfl::expireTimeout); } void AudioRtpSession::setDestinationIpAddress() { // Store remote ip in case we would need to forget current destination - remote_ip_ = ost::InetHostAddress(ca_->getLocalSDP()->getRemoteIP().c_str()); + remote_ip_ = ost::InetHostAddress(call_.getLocalSDP()->getRemoteIP().c_str()); if (!remote_ip_) { - WARN("AudioRtpSession: Target IP address (%s) is not correct!", - ca_->getLocalSDP()->getRemoteIP().data()); + WARN("Target IP address (%s) is not correct!", + call_.getLocalSDP()->getRemoteIP().data()); return; } // Store remote port in case we would need to forget current destination - remote_port_ = (unsigned short) ca_->getLocalSDP()->getRemoteAudioPort(); + remote_port_ = (unsigned short) call_.getLocalSDP()->getRemoteAudioPort(); - DEBUG("AudioRtpSession: New remote address for session: %s:%d", - ca_->getLocalSDP()->getRemoteIP().data(), remote_port_); + DEBUG("New remote address for session: %s:%d", + call_.getLocalSDP()->getRemoteIP().data(), remote_port_); - if (!queue_->addDestination(remote_ip_, remote_port_)) { - WARN("AudioRtpSession: Can't add new destination to session!"); + if (!queue_.addDestination(remote_ip_, remote_port_)) { + WARN("Can't add new destination to session!"); return; } } void AudioRtpSession::updateDestinationIpAddress() { - DEBUG("AudioRtpSession: Update destination ip address"); + DEBUG("Update destination ip address"); // Destination address are stored in a list in ccrtp // This method remove the current destination entry - if (!queue_->forgetDestination(remote_ip_, remote_port_, remote_port_ + 1)) - DEBUG("AudioRtpSession: Did not remove previous destination"); + if (!queue_.forgetDestination(remote_ip_, remote_port_, remote_port_ + 1)) + DEBUG("Did not remove previous destination"); // new destination is stored in call // we just need to recall this method @@ -233,12 +228,12 @@ void AudioRtpSession::updateDestinationIpAddress() } -int AudioRtpSession::startRtpThread(AudioCodec* audiocodec) +int AudioRtpSession::startRtpThread(AudioCodec &audiocodec) { if (isStarted_) return 0; - DEBUG("AudioSymmetricRtpSession: Starting main thread"); + DEBUG("Starting main thread"); isStarted_ = true; setSessionTimeouts(); @@ -246,15 +241,9 @@ int AudioRtpSession::startRtpThread(AudioCodec* audiocodec) initBuffers(); initNoiseSuppress(); - queue_->enableStack(); - int ret = thread_->start(); - - if (type_ == Zrtp) - return ret; - - AudioSymmetricRtpSession *self = dynamic_cast<AudioSymmetricRtpSession*>(this); - assert(self); - return self->startSymmetricRtpThread(); + queue_.enableStack(); + thread_.start(); + return 0; } diff --git a/daemon/src/audio/audiortp/audio_rtp_session.h b/daemon/src/audio/audiortp/audio_rtp_session.h index 4f8723b234f0897490cadd65faa237518d02bbfc..c6baca3f29fd81b9899922e6b1aef87a767a0478 100644 --- a/daemon/src/audio/audiortp/audio_rtp_session.h +++ b/daemon/src/audio/audiortp/audio_rtp_session.h @@ -31,44 +31,35 @@ * shall include the source code for the parts of OpenSSL used as well * as that of the covered work. */ -#ifndef SFL_AUDIO_RTP_SESSION_H_ -#define SFL_AUDIO_RTP_SESSION_H_ +#ifndef AUDIO_RTP_SESSION_H_ +#define AUDIO_RTP_SESSION_H_ #include "audio_rtp_record_handler.h" -#include <audio/codecs/audiocodec.h> #include <ccrtp/rtp.h> #include <ccrtp/formats.h> #include "noncopyable.h" class SIPCall; +namespace ost { + class Thread; +} namespace sfl { class AudioCodec; -// Possible kind of rtp session -typedef enum RtpMethod { - Symmetric, - Zrtp, - Sdes -} RtpMethod; - - class AudioRtpSession : public AudioRtpRecordHandler { public: /** * Constructor * @param sipcall The pointer on the SIP call */ - AudioRtpSession(SIPCall* sipcall, RtpMethod type, ost::RTPDataQueue *queue, ost::Thread *thread); + AudioRtpSession(SIPCall &sipcall, ost::RTPDataQueue &queue, ost::Thread &thread); virtual ~AudioRtpSession(); - RtpMethod getAudioRtpType() { - return type_; - } - void updateSessionMedia(AudioCodec *audioCodec); + void updateSessionMedia(AudioCodec &audioCodec); - int startRtpThread(AudioCodec*); + virtual int startRtpThread(AudioCodec&); /** * Used mostly when receiving a reinvite @@ -76,6 +67,11 @@ class AudioRtpSession : public AudioRtpRecordHandler { void updateDestinationIpAddress(); protected: + /** + * Set the audio codec for this RTP session + */ + virtual void setSessionMedia(AudioCodec &codec) = 0; + bool onRTPPacketRecv(ost::IncomingRTPPkt&); @@ -90,19 +86,26 @@ class AudioRtpSession : public AudioRtpRecordHandler { /** * Send encoded data to peer */ - void sendMicData(); - - SIPCall *ca_; + virtual void sendMicData(); - RtpMethod type_; + SIPCall &call_; - private: - NON_COPYABLE(AudioRtpSession); + /** + * Timestamp for this session + */ + int timestamp_; /** - * Set the audio codec for this RTP session + * Timestamp incrementation value based on codec period length (framesize) + * except for G722 which require a 8 kHz incrementation. */ - void setSessionMedia(AudioCodec*); + int timestampIncrement_; + + ost::RTPDataQueue &queue_; + + bool isStarted_; + private: + NON_COPYABLE(AudioRtpSession); /** * Set RTP Sockets send/receive timeouts @@ -119,6 +122,11 @@ class AudioRtpSession : public AudioRtpRecordHandler { */ void receiveSpeakerData(); + /** + * Increment timestamp for DTMF event + */ + virtual void incrementTimestampForDTMF(); + // Main destination address for this rtp session. // Stored in case or reINVITE, which may require to forget // this destination and update a new one. @@ -129,27 +137,12 @@ class AudioRtpSession : public AudioRtpRecordHandler { // this destination and update a new one unsigned short remote_port_; - /** - * Timestamp for this session - */ - int timestamp_; - - /** - * Timestamp incrementation value based on codec period length (framesize) - * except for G722 which require a 8 kHz incrementation. - */ - int timestampIncrement_; - /** * Timestamp reset frequency specified in number of packet sent */ short timestampCount_; - bool isStarted_; - - ost::RTPDataQueue *queue_; - - ost::Thread *thread_; + ost::Thread &thread_; }; } diff --git a/daemon/src/audio/audiortp/audio_srtp_session.cpp b/daemon/src/audio/audiortp/audio_srtp_session.cpp index 0f3bf23c0983d40b6461602b4997a2a5feef7490..25eb48da99ceb29e966dc736b864b10dc3d350d8 100644 --- a/daemon/src/audio/audiortp/audio_srtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_srtp_session.cpp @@ -28,8 +28,10 @@ * as that of the covered work. */ #include "audio_srtp_session.h" +#include "logger.h" +#include "array_size.h" -#include "sip/sipcall.h" +#include <algorithm> #include <openssl/sha.h> #include <openssl/hmac.h> @@ -44,29 +46,103 @@ namespace sfl { -AudioSrtpSession::AudioSrtpSession(SIPCall * sipcall) : - AudioSymmetricRtpSession(sipcall), - remoteCryptoCtx_(NULL), - localCryptoCtx_(NULL), +namespace { + std::string + encodeBase64(unsigned char *input, int length) + { + // init decoder + BIO *b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + // init internal buffer + BIO *bmem = BIO_new(BIO_s_mem()); + + // create decoder chain + b64 = BIO_push(b64, bmem); + + BIO_write(b64, input, length); + // BIO_flush (b64); + + // get pointer to data + BUF_MEM *bptr = 0; + BIO_get_mem_ptr(b64, &bptr); + + std::string output(bptr->data, bptr->length); + + BIO_free_all(bmem); + + return output; + } + + std::vector<char> decodeBase64(unsigned char *input, int length) + { + BIO *b64, *bmem; + + // init decoder and read-only BIO buffer + b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + // init internal buffer + bmem = BIO_new_mem_buf(input, length); + + // create encoder chain + bmem = BIO_push(b64, bmem); + + std::vector<char> buffer(length, 0); + BIO_read(bmem, &(*buffer.begin()), length); + + BIO_free_all(bmem); + + return buffer; + } + + // Fills the array dest with length random bytes + void bufferFillMasterKey(std::vector<uint8>& dest) + { + DEBUG("Init local master key"); + + // Allocate memory for key + std::vector<unsigned char> random_key(dest.size()); + + // Generate ryptographically strong pseudo-random bytes + if (RAND_bytes(&(*random_key.begin()), dest.size()) != 1) + DEBUG("Error occured while generating cryptographically strong pseudo-random key"); + + std::copy(random_key.begin(), random_key.end(), dest.begin()); + } + + // Fills the array dest with length random bytes + void bufferFillMasterSalt(std::vector<uint8>& dest) + { + DEBUG("Init local master key"); + + // Allocate memory for key + std::vector<unsigned char> random_key(dest.size()); + + // Generate ryptographically strong pseudo-random bytes + if (RAND_bytes(&(*random_key.begin()), dest.size()) != 1) + DEBUG("Error occured while generating cryptographically strong pseudo-random key"); + + std::copy(random_key.begin(), random_key.end(), dest.begin()); + } +} + +AudioSrtpSession::AudioSrtpSession(SIPCall &call) : + AudioSymmetricRtpSession(call), + remoteCryptoCtx_(0), + localCryptoCtx_(0), localCryptoSuite_(0), remoteCryptoSuite_(0), - localMasterKeyLength_(0), - localMasterSaltLength_(0), - remoteMasterKeyLength_(0), - remoteMasterSaltLength_(0), + localMasterKey_(MAX_MASTER_KEY_LENGTH), + localMasterSalt_(MAX_MASTER_SALT_LENGTH), + remoteMasterKey_(MAX_MASTER_KEY_LENGTH), + remoteMasterSalt_(MAX_MASTER_SALT_LENGTH), remoteOfferIsSet_(false) -{ - type_ = Sdes; -} - -AudioSrtpSession::~AudioSrtpSession() -{ - DEBUG("AudioSrtp: Destroy audio srtp session"); -} +{} void AudioSrtpSession::initLocalCryptoInfo() { - DEBUG("AudioSrtp: Set cryptographic info for this rtp session"); + DEBUG("AudioSrtpSession: Set cryptographic info for this rtp session"); // Initialize local Crypto context initializeLocalMasterKey(); @@ -79,10 +155,22 @@ void AudioSrtpSession::initLocalCryptoInfo() setOutQueueCryptoContext(localCryptoCtx_); } -std::vector<std::string> AudioSrtpSession::getLocalCryptoInfo() +void AudioSrtpSession::initLocalCryptoInfoOnOffhold() { + DEBUG("AudioSrtpSession: Set cryptographic info for this rtp session"); - DEBUG("AudioSrtp: Get Cryptographic info from this rtp session"); + // Initialize local Crypto context + initializeLocalCryptoContext(); + + // Set local crypto context in ccrtp + localCryptoCtx_->deriveSrtpKeys(0); + + setOutQueueCryptoContext(localCryptoCtx_); +} + +std::vector<std::string> AudioSrtpSession::getLocalCryptoInfo() +{ + DEBUG("Get Cryptographic info from this rtp session"); std::vector<std::string> crypto_vector; @@ -90,7 +178,7 @@ std::vector<std::string> AudioSrtpSession::getLocalCryptoInfo() // cryptographic context tagged 1, 2, 3... std::string tag = "1"; - std::string crypto_suite = sfl::CryptoSuites[localCryptoSuite_].name; + std::string crypto_suite(sfl::CryptoSuites[localCryptoSuite_].name); // srtp keys formated as the following as the following // inline:keyParameters|keylifetime|MasterKeyIdentifier @@ -111,13 +199,10 @@ std::vector<std::string> AudioSrtpSession::getLocalCryptoInfo() return crypto_vector; } -void AudioSrtpSession::setRemoteCryptoInfo(sfl::SdesNegotiator& nego) +void AudioSrtpSession::setRemoteCryptoInfo(const sfl::SdesNegotiator& nego) { if (not remoteOfferIsSet_) { - DEBUG("%s", nego.getKeyInfo().c_str()); - // Use second crypto suite if key length is 32 bit, default is 80; - if (nego.getAuthTagLength() == "32") { localCryptoSuite_ = 1; remoteCryptoSuite_ = 1; @@ -128,198 +213,151 @@ void AudioSrtpSession::setRemoteCryptoInfo(sfl::SdesNegotiator& nego) // init crypto content in Srtp session initializeRemoteCryptoContext(); - setInQueueCryptoContext(remoteCryptoCtx_); + if (remoteCryptoCtx_) { + setInQueueCryptoContext(remoteCryptoCtx_); + } - // initLocalCryptoInfo(); remoteOfferIsSet_ = true; } } +namespace { + static const size_t BITS_PER_BYTE = 8; +} + void AudioSrtpSession::initializeLocalMasterKey() { - DEBUG("AudioSrtp: Init local master key"); - - // @TODO key may have different length depending on cipher suite - localMasterKeyLength_ = sfl::CryptoSuites[localCryptoSuite_].masterKeyLength / 8; - - DEBUG("AudioSrtp: Local master key length %d", localMasterKeyLength_); - - // Allocate memory for key - unsigned char *random_key = new unsigned char[localMasterKeyLength_]; - - // Generate ryptographically strong pseudo-random bytes - int err; - - if ((err = RAND_bytes(random_key, localMasterKeyLength_)) != 1) - DEBUG("Error occured while generating cryptographically strong pseudo-random key"); - - memcpy(localMasterKey_, random_key, localMasterKeyLength_); + localMasterKey_.resize(sfl::CryptoSuites[localCryptoSuite_].masterKeyLength / BITS_PER_BYTE); + bufferFillMasterKey(localMasterKey_); } void AudioSrtpSession::initializeLocalMasterSalt() { - // @TODO key may have different length depending on cipher suite - localMasterSaltLength_ = sfl::CryptoSuites[localCryptoSuite_].masterSaltLength / 8; - - // Allocate memory for key - unsigned char *random_key = new unsigned char[localMasterSaltLength_]; - - DEBUG("AudioSrtp: Local master salt length %d", localMasterSaltLength_); - - // Generate ryptographically strong pseudo-random bytes - int err; - - if ((err = RAND_bytes(random_key, localMasterSaltLength_)) != 1) - DEBUG("Error occured while generating cryptographically strong pseudo-random key"); - - memcpy(localMasterSalt_, random_key, localMasterSaltLength_); + localMasterSalt_.resize(sfl::CryptoSuites[localCryptoSuite_].masterSaltLength / BITS_PER_BYTE); + bufferFillMasterSalt(localMasterSalt_); } std::string AudioSrtpSession::getBase64ConcatenatedKeys() { - DEBUG("AudioSrtp: Get base64 concatenated keys"); + DEBUG("Get base64 concatenated keys"); // compute concatenated master and salt length - int concatLength = localMasterKeyLength_ + localMasterSaltLength_; - - uint8 concatKeys[concatLength]; - - DEBUG("AudioSrtp: Concatenated length %d", concatLength); + std::vector<uint8> concatKeys; + concatKeys.reserve(localMasterKey_.size() + localMasterSalt_.size()); // concatenate keys - memcpy((void*) concatKeys, (void*) localMasterKey_, localMasterKeyLength_); - memcpy((void*)(concatKeys + localMasterKeyLength_), (void*) localMasterSalt_, localMasterSaltLength_); + concatKeys.insert(concatKeys.end(), localMasterKey_.begin(), localMasterKey_.end()); + concatKeys.insert(concatKeys.end(), localMasterSalt_.begin(), localMasterSalt_.end()); // encode concatenated keys in base64 - return encodeBase64((unsigned char*) concatKeys, concatLength); + return encodeBase64(&(*concatKeys.begin()), concatKeys.size()); } void AudioSrtpSession::unBase64ConcatenatedKeys(std::string base64keys) { - remoteMasterKeyLength_ = sfl::CryptoSuites[remoteCryptoSuite_].masterKeyLength / 8; - remoteMasterSaltLength_ = sfl::CryptoSuites[remoteCryptoSuite_].masterSaltLength / 8; + remoteMasterKey_.resize(sfl::CryptoSuites[remoteCryptoSuite_].masterKeyLength / BITS_PER_BYTE); + remoteMasterSalt_.resize(sfl::CryptoSuites[remoteCryptoSuite_].masterSaltLength / BITS_PER_BYTE); // pointer to binary data char *dataptr = (char*) base64keys.data(); // decode concatenated binary keys - char *output = decodeBase64((unsigned char*) dataptr, strlen(dataptr)); + std::vector<char> output(decodeBase64((unsigned char*) dataptr, strlen(dataptr))); // copy master and slt respectively - memcpy((void*) remoteMasterKey_, (void*) output, remoteMasterKeyLength_); - memcpy((void*) remoteMasterSalt_, (void*)(output + remoteMasterKeyLength_), remoteMasterSaltLength_); - - delete[] output; + const std::vector<char>::iterator key_end = output.begin() + remoteMasterKey_.size(); + std::copy(output.begin(), key_end, remoteMasterKey_.begin()); + std::copy(key_end, output.end(), remoteMasterSalt_.begin()); } void AudioSrtpSession::initializeRemoteCryptoContext() { - DEBUG("AudioSrtp: Initialize remote crypto context"); + DEBUG("Initialize remote crypto context"); - CryptoSuiteDefinition crypto = sfl::CryptoSuites[remoteCryptoSuite_]; - - if (remoteCryptoCtx_) { - delete remoteCryptoCtx_; - remoteCryptoCtx_ = NULL; - } + const CryptoSuiteDefinition &crypto = sfl::CryptoSuites[remoteCryptoSuite_]; remoteCryptoCtx_ = new ost::CryptoContext(0x0, - 0, // roc, - 0L, // keydr, - SrtpEncryptionAESCM, // encryption algo - SrtpAuthenticationSha1Hmac, // authtication algo - remoteMasterKey_, - remoteMasterKeyLength_, - remoteMasterSalt_, - remoteMasterSaltLength_, - crypto.encryptionKeyLength / 8, - crypto.srtpAuthKeyLength / 8, - crypto.masterSaltLength / 8, // session salt len - crypto.srtpAuthTagLength / 8); + 0, // roc, + 0L, // keydr, + SrtpEncryptionAESCM, + SrtpAuthenticationSha1Hmac, + &(*remoteMasterKey_.begin()), + remoteMasterKey_.size(), + &(*remoteMasterSalt_.begin()), + remoteMasterSalt_.size(), + crypto.encryptionKeyLength / BITS_PER_BYTE, + crypto.srtpAuthKeyLength / BITS_PER_BYTE, + crypto.masterSaltLength / BITS_PER_BYTE, + crypto.srtpAuthTagLength / BITS_PER_BYTE); } void AudioSrtpSession::initializeLocalCryptoContext() { - DEBUG("AudioSrtp: Initialize local crypto context"); - - CryptoSuiteDefinition crypto = sfl::CryptoSuites[localCryptoSuite_]; + DEBUG("Initialize local crypto context"); - if (localCryptoCtx_) { - delete localCryptoCtx_; - localCryptoCtx_ = NULL; - } + const CryptoSuiteDefinition &crypto = sfl::CryptoSuites[localCryptoSuite_]; localCryptoCtx_ = new ost::CryptoContext(OutgoingDataQueue::getLocalSSRC(), - 0, // roc, - 0L, // keydr, - SrtpEncryptionAESCM, // encryption algo - SrtpAuthenticationSha1Hmac, // authtication algo - localMasterKey_, - localMasterKeyLength_, - localMasterSalt_, - localMasterSaltLength_, - crypto.encryptionKeyLength / 8, - crypto.srtpAuthKeyLength / 8, - crypto.masterSaltLength / 8, // session salt len - crypto.srtpAuthTagLength / 8); + 0, // roc, + 0L, // keydr, + SrtpEncryptionAESCM, + SrtpAuthenticationSha1Hmac, + &(*localMasterKey_.begin()), + localMasterKey_.size(), + &(*localMasterSalt_.begin()), + localMasterSalt_.size(), + crypto.encryptionKeyLength / BITS_PER_BYTE, + crypto.srtpAuthKeyLength / BITS_PER_BYTE, + crypto.masterSaltLength / BITS_PER_BYTE, + crypto.srtpAuthTagLength / BITS_PER_BYTE); } -void AudioSrtpSession::restoreCryptoContext(ost::CryptoContext *localContext, ost::CryptoContext *remoteContext) +void +AudioSrtpSession::setLocalMasterKey(const std::vector<uint8>& key) { - setInQueueCryptoContext(remoteContext); - setOutQueueCryptoContext(localContext); + localMasterKey_ = key; } -std::string AudioSrtpSession::encodeBase64(unsigned char *input, int length) +std::vector<uint8> +AudioSrtpSession::getLocalMasterKey() const { - BIO *b64, *bmem; - BUF_MEM *bptr ; - - // init decoder - b64 = BIO_new(BIO_f_base64()); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - - // init internal buffer - bmem = BIO_new(BIO_s_mem()); - - // create decoder chain - b64 = BIO_push(b64, bmem); - - BIO_write(b64, input, length); - // BIO_flush (b64); - - // get pointer to data - BIO_get_mem_ptr(b64, &bptr); - - std::string output(bptr->data, bptr->length); - - BIO_free_all(bmem); - - return output; + return localMasterKey_; } -char* AudioSrtpSession::decodeBase64(unsigned char *input, int length) +void +AudioSrtpSession::setLocalMasterSalt(const std::vector<uint8>& salt) { - BIO *b64, *bmem; - - // init decoder and read-only BIO buffer - b64 = BIO_new(BIO_f_base64()); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - - // init internal buffer - bmem = BIO_new_mem_buf(input, length); + localMasterSalt_ = salt; +} - // create encoder chain - bmem = BIO_push(b64, bmem); +std::vector<uint8> +AudioSrtpSession::getLocalMasterSalt() const +{ + return localMasterSalt_; +} - char *buffer = new char[length]; - memset(buffer, 0, length); +void +AudioSrtpSession::setRemoteMasterKey(const std::vector<uint8>& key) +{ + remoteMasterKey_ = key; +} - BIO_read(bmem, buffer, length); +std::vector<uint8> AudioSrtpSession::getRemoteMasterKey() const +{ + return remoteMasterKey_; +} - BIO_free_all(bmem); +void +AudioSrtpSession::setRemoteMasterSalt(const std::vector<uint8>& salt) +{ + remoteMasterSalt_ = salt; +} - return buffer; +std::vector<uint8> +AudioSrtpSession::getRemoteMasterSalt() const +{ + return remoteMasterSalt_; } + } diff --git a/daemon/src/audio/audiortp/audio_srtp_session.h b/daemon/src/audio/audiortp/audio_srtp_session.h index f641e8eaa55b21065e7efcee35eb87f3543f93eb..18d0adc926b0251913a155084797431afb06b5a8 100644 --- a/daemon/src/audio/audiortp/audio_srtp_session.h +++ b/daemon/src/audio/audiortp/audio_srtp_session.h @@ -27,10 +27,9 @@ * shall include the source code for the parts of OpenSSL used as well * as that of the covered work. */ -#ifndef __AUDIO_SRTP_SESSION_H__ -#define __AUDIO_SRTP_SESSION_H__ +#ifndef AUDIO_SRTP_SESSION_H_ +#define AUDIO_SRTP_SESSION_H_ -#include "audio_rtp_session.h" #include "audio_symmetric_rtp_session.h" #include "sip/sdes_negotiator.h" #include "noncopyable.h" @@ -64,18 +63,19 @@ class SIPCall; +---------------------+-------------+--------------+---------------+ */ - namespace sfl { +#define MAX_MASTER_KEY_LENGTH 16 +#define MAX_MASTER_SALT_LENGTH 14 + class AudioSrtpSession : public AudioSymmetricRtpSession { public: /** - * Constructor for this rtp session + * Constructor for this rtp session. The local and remote keys must be properly + * initialized using initLocalCryptoInfo and setRemoteCryptoInfo respectively. */ - AudioSrtpSession(SIPCall * sipcall); - - ~AudioSrtpSession(); + AudioSrtpSession(SIPCall &call); /** * Used to get sdp crypto header to be included in sdp session. This @@ -85,33 +85,87 @@ class AudioSrtpSession : public AudioSymmetricRtpSession { std::vector<std::string> getLocalCryptoInfo(); /** - * Set remote crypto header from incoming sdp offer + * Set remote crypto header from incoming sdp offer. It is expected that the + * local cryptographic context is initialized with mehod */ - void setRemoteCryptoInfo(sfl::SdesNegotiator& nego); + void setRemoteCryptoInfo(const sfl::SdesNegotiator &nego); /** * Init local crypto context for outgoing data - * this method must be called before sending first Invite request - * with SDP offer. - */ + * this method must be called before sending or receiving an SDP offer. + * It is required for media negotiation that the local cryptographic + * context be properly initialized. + * + * @return The new local crypto context, to be cached by the caller + */ void initLocalCryptoInfo(); /** - * Restore the cryptographic context. most likely useful to restore - * a call after hold action + * Initialize crypto context */ - void restoreCryptoContext(ost::CryptoContext *, ost::CryptoContext *); + void initLocalCryptoInfoOnOffhold(); + /** + * Replace the local master key with the one specified. One must call + * initializeLocalCryptoContext to apply the key to the encryption engine. + */ + void setLocalMasterKey(const std::vector<uint8>& key); - /** Remote srtp crypto context to be set into incoming data queue. */ - ost::CryptoContext* remoteCryptoCtx_; + /** + * Store the current local master key in an external buffer + * for future reinitialization of the session. + */ + std::vector<uint8> getLocalMasterKey() const; - /** Local srtp crypto context to be set into outgoing data queue. */ - ost::CryptoContext* localCryptoCtx_; + /** + * Replace the local master salt with the one specificed. One must call + * initializeLocalCryptoContext to apply the key to the encryption engine. + */ + void setLocalMasterSalt(const std::vector<uint8>& salt); + + /** + * Store the lcoal master salt in an external buffer for future + * reinitialization of the ssession. + */ + std::vector<uint8> getLocalMasterSalt() const; + + /** + * Replace the remote master key with one specified. One must call + * initializeRemoteCryptoContext to apply the key to the decryption engine. + */ + void setRemoteMasterKey(const std::vector<uint8>& key); + + /** + * Store the remote master key in an extenal buffer for future + * reinitialization of the session. + */ + std::vector<uint8> getRemoteMasterKey() const; + + /** + * Replace the remote master salt with one specified. On must call + * initializeRemoteCryptoContext to apply the key to the decryption engine. + */ + void setRemoteMasterSalt(const std::vector<uint8>& salt); + + /** + * Store the remote master salt in an external buffer for future + * reinitialization of the session. + */ + std::vector<uint8> getRemoteMasterSalt() const; private: NON_COPYABLE(AudioSrtpSession); + /** + * Remote srtp crypto context to be set into incoming data queue. + */ + ost::CryptoContext* remoteCryptoCtx_; + + /** + * Local srtp crypto context to be set into outgoing data queue. + */ + ost::CryptoContext* localCryptoCtx_; + /** * Init local master key according to current crypto context * as defined in SdesNegotiator.h @@ -147,42 +201,35 @@ class AudioSrtpSession : public AudioSymmetricRtpSession { void unBase64ConcatenatedKeys(std::string base64keys); /** - * Encode input data as base64 + * Default local crypto suite is AES_CM_128_HMAC_SHA1_80 */ - std::string encodeBase64(unsigned char *input, int length); + int localCryptoSuite_; /** - * Decode base64 data + * Remote crypto suite is initialized at AES_CM_128_HMAC_SHA1_80 */ - char* decodeBase64(unsigned char *input, int length); - - /** Default local crypto suite is AES_CM_128_HMAC_SHA1_80*/ - int localCryptoSuite_; - - /** Remote crypto suite is initialized at AES_CM_128_HMAC_SHA1_80*/ int remoteCryptoSuite_; - uint8 localMasterKey_[16]; - - /** local master key length in byte */ - int localMasterKeyLength_; - - uint8 localMasterSalt_[14]; - - /** local master salt length in byte */ - int localMasterSaltLength_; - - uint8 remoteMasterKey_[16]; + /** + * Array to store the local master key + */ + std::vector<uint8> localMasterKey_; - /** remote master key length in byte */ - int remoteMasterKeyLength_; + /** + * Array to store local master salt + */ + std::vector<uint8> localMasterSalt_; - uint8 remoteMasterSalt_[14]; + std::vector<uint8> remoteMasterKey_; - /** remote master salt length in byte */ - int remoteMasterSaltLength_; + /** + * Array to store the remote master salt + */ + std::vector<uint8> remoteMasterSalt_; - /** Used to make sure remote crypto context not initialized wice. */ + /** + * Used to make sure remote crypto context not initialized twice. + */ bool remoteOfferIsSet_; }; } diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp index cc5d9ba37e068ad94c070a739cde6d6079b5116d..559c6578057742790ffefa2d951045834d7fd22b 100644 --- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp @@ -32,33 +32,32 @@ * as that of the covered work. */ -#include "audio_rtp_session.h" #include "audio_symmetric_rtp_session.h" -#include "audio_rtp_record_handler.h" -#include "sip/sdp.h" +#include "logger.h" #include "sip/sipcall.h" -#include "audio/audiolayer.h" namespace sfl { -AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall * sipcall) : +AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall &call) : ost::TimerPort() - , ost::SymmetricRTPSession(ost::InetHostAddress(sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort()) - , AudioRtpSession(sipcall, Symmetric, this, this) - , echoCanceller() - , rtpThread_(new AudioRtpThread(this)) + , ost::SymmetricRTPSession(ost::InetHostAddress(call.getLocalIp().c_str()), call.getLocalAudioPort()) + , AudioRtpSession(call, *this, *this) + , rtpThread_(*this) { - DEBUG("AudioSymmetricRtpSession: Setting new RTP session with destination %s:%d", ca_->getLocalIp().c_str(), ca_->getLocalAudioPort()); - audioRtpRecord_.callId_ = ca_->getCallId(); + DEBUG("Setting new RTP session with destination %s:%d", + call_.getLocalIp().c_str(), call_.getLocalAudioPort()); + audioRtpRecord_.callId_ = call_.getCallId(); } AudioSymmetricRtpSession::~AudioSymmetricRtpSession() { - rtpThread_->running = false; - delete rtpThread_; + if (rtpThread_.running_) { + rtpThread_.running_ = false; + rtpThread_.join(); + } } -AudioSymmetricRtpSession::AudioRtpThread::AudioRtpThread(AudioSymmetricRtpSession *session) : running(true), rtpSession(session) +AudioSymmetricRtpSession::AudioRtpThread::AudioRtpThread(AudioSymmetricRtpSession &session) : running_(true), rtpSession_(session) {} void AudioSymmetricRtpSession::AudioRtpThread::run() @@ -67,21 +66,36 @@ void AudioSymmetricRtpSession::AudioRtpThread::run() TimerPort::setTimer(threadSleep); - DEBUG("AudioRtpThread: Entering Audio rtp thread main loop"); + DEBUG("Entering Audio rtp thread main loop"); - while (running) { + while (running_) { // Send session - if (rtpSession->DtmfPending()) - rtpSession->sendDtmfEvent(); + if (rtpSession_.DtmfPending()) + rtpSession_.sendDtmfEvent(); else - rtpSession->sendMicData(); + rtpSession_.sendMicData(); Thread::sleep(TimerPort::getTimer()); TimerPort::incTimer(threadSleep); } - DEBUG("AudioRtpThread: Leaving audio rtp thread loop"); + DEBUG("Leaving audio rtp thread loop"); +} + +void AudioSymmetricRtpSession::setSessionMedia(AudioCodec &audioCodec) +{ + AudioRtpSession::setSessionMedia(audioCodec); + call_.setRecordingSmplRate(getCodecSampleRate()); } +int AudioSymmetricRtpSession::startRtpThread(AudioCodec &audiocodec) +{ + DEBUG("Starting main thread"); + if (isStarted_) + return 0; + + AudioRtpSession::startRtpThread(audiocodec); + return startSymmetricRtpThread(); +} } diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h index 256e55ae69f53ab36f349dbd7bb478e4f311ffd7..c89d39143b9f0412533b4bc6c2f5b1a81ac5bbb7 100644 --- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h +++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h @@ -47,7 +47,6 @@ using std::ptrdiff_t; #pragma GCC diagnostic ignored "-Weffc++" #include <ccrtp/rtp.h> #include <ccrtp/iqueue.h> -#include <cc++/numbers.h> // ost::Time class SIPCall; @@ -57,10 +56,9 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP public: /** * Constructor - * @param sipcall The pointer on the SIP call + * @param call The SIP call */ - AudioSymmetricRtpSession(SIPCall* sipcall); - + AudioSymmetricRtpSession(SIPCall &call); ~AudioSymmetricRtpSession(); virtual bool onRTPPacketRecv(ost::IncomingRTPPkt& pkt) { @@ -68,8 +66,8 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP } int startSymmetricRtpThread() { - assert(rtpThread_); - return rtpThread_->start(); + rtpThread_.start(); + return 0; } private: @@ -77,21 +75,20 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP class AudioRtpThread : public ost::Thread, public ost::TimerPort { public: - AudioRtpThread(AudioSymmetricRtpSession *session); - ~AudioRtpThread(){} + AudioRtpThread(AudioSymmetricRtpSession &session); virtual void run(); - bool running; + bool running_; private: NON_COPYABLE(AudioRtpThread); - AudioSymmetricRtpSession *rtpSession; + AudioSymmetricRtpSession &rtpSession_; }; - SpeexEchoCancel echoCanceller; + void setSessionMedia(AudioCodec &codec); + int startRtpThread(AudioCodec &audiocodec); - private: - AudioRtpThread *rtpThread_; + AudioRtpThread rtpThread_; }; } diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.cpp b/daemon/src/audio/audiortp/audio_zrtp_session.cpp index ebdb8f839e421b1494341b8a19bf846f9c6218c2..72570544b90fec53c5ec7b684147f098608ddd24 100644 --- a/daemon/src/audio/audiortp/audio_zrtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_zrtp_session.cpp @@ -28,56 +28,42 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif + #include "audio_zrtp_session.h" #include "zrtp_session_callback.h" - #include "sip/sipcall.h" -#include "sip/sdp.h" -#include "audio/audiolayer.h" +#include "logger.h" #include "manager.h" +#include "fileutils.h" #include <libzrtpcpp/zrtpccrtp.h> #include <libzrtpcpp/ZrtpQueue.h> #include <libzrtpcpp/ZrtpUserCallback.h> - -#include <cstdio> -#include <cstring> -#include <cerrno> - #include <ccrtp/rtp.h> namespace sfl { -AudioZrtpSession::AudioZrtpSession(SIPCall * sipcall, const std::string& zidFilename) : - AudioRtpSession(sipcall, Zrtp, this, this), - ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue>(ost::InetHostAddress(sipcall->getLocalIp().c_str()), - sipcall->getLocalAudioPort(), - 0, - ost::MembershipBookkeeping::defaultMembersHashSize, - ost::defaultApplication()), +AudioZrtpSession::AudioZrtpSession(SIPCall &call, const std::string &zidFilename) : + AudioRtpSession(call, *this, *this), + ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue>(ost::InetHostAddress(call_.getLocalIp().c_str()), + call_.getLocalAudioPort(), + 0, + ost::MembershipBookkeeping::defaultMembersHashSize, + ost::defaultApplication()), zidFilename_(zidFilename) { - DEBUG("AudioZrtpSession initialized"); initializeZid(); - - setCancel(cancelDefault); - - DEBUG("AudioZrtpSession: Setting new RTP session with destination %s:%d", ca_->getLocalIp().c_str(), ca_->getLocalAudioPort()); + DEBUG("Setting new RTP session with destination %s:%d", + call_.getLocalIp().c_str(), call_.getLocalAudioPort()); } AudioZrtpSession::~AudioZrtpSession() { ost::Thread::terminate(); - Manager::instance().getMainBuffer()->unBindAll(ca_->getCallId()); -} - -void AudioZrtpSession::final() -{ -// tmatth:Oct 25 2011:FIXME: -// This was crashing...seems like it's not necessary. Double check -// with valgrind/helgrind -// delete this; + Manager::instance().getMainBuffer()->unBindAll(call_.getCallId()); } void AudioZrtpSession::initializeZid() @@ -89,20 +75,19 @@ void AudioZrtpSession::initializeZid() std::string xdg_config = std::string(HOMEDIR) + DIR_SEPARATOR_STR + ".cache" + DIR_SEPARATOR_STR + PACKAGE + "/" + zidFilename_; - DEBUG(" xdg_config %s", xdg_config.c_str()); + DEBUG("xdg_config %s", xdg_config.c_str()); if (XDG_CACHE_HOME != NULL) { std::string xdg_env = std::string(XDG_CACHE_HOME) + zidFilename_; - DEBUG(" xdg_env %s", xdg_env.c_str()); + DEBUG("xdg_env %s", xdg_env.c_str()); (xdg_env.length() > 0) ? zidCompleteFilename = xdg_env : zidCompleteFilename = xdg_config; } else zidCompleteFilename = xdg_config; if (initialize(zidCompleteFilename.c_str()) >= 0) { - DEBUG("Register callbacks"); setEnableZrtp(true); - setUserCallback(new ZrtpSessionCallback(ca_)); + setUserCallback(new ZrtpSessionCallback(call_)); return; } @@ -117,11 +102,29 @@ void AudioZrtpSession::initializeZid() return; } +void AudioZrtpSession::sendMicData() +{ + int compSize = processDataEncode(); + + // if no data return + if (compSize == 0) + return; + + // Increment timestamp for outgoing packet + timestamp_ += timestampIncrement_; + + // this step is only needed for ZRTP + queue_.putData(timestamp_, getMicDataEncoded(), compSize); + + // putData puts the data on RTP queue, sendImmediate bypasses this queue + queue_.sendImmediate(timestamp_, getMicDataEncoded(), compSize); +} + void AudioZrtpSession::run() { // Set recording sampling rate - ca_->setRecordingSmplRate(getCodecSampleRate()); - DEBUG("AudioZrtpSession: Entering mainloop for call %s", ca_->getCallId().c_str()); + call_.setRecordingSmplRate(getCodecSampleRate()); + DEBUG("Entering mainloop for call %s", call_.getCallId().c_str()); uint32 timeout = 0; @@ -135,10 +138,8 @@ void AudioZrtpSession::run() else sendMicData(); - setCancel(cancelDeferred); controlReceptionService(); controlTransmissionService(); - setCancel(cancelImmediate); uint32 maxWait = timeval2microtimeout(getRTCPCheckInterval()); // make sure the scheduling timeout is // <= the check interval for RTCP @@ -146,23 +147,29 @@ void AudioZrtpSession::run() timeout = (timeout > maxWait) ? maxWait : timeout; if (timeout < 1000) { // !(timeout/1000) - setCancel(cancelDeferred); // dispatchDataPacket(); - setCancel(cancelImmediate); timerTick(); } else { - if (isPendingData(timeout/1000)) { - setCancel(cancelDeferred); + if (isPendingData(timeout / 1000)) { if (isActive()) takeInDataPacket(); - - setCancel(cancelImmediate); } timeout = 0; } } - DEBUG("AudioZrtpSession: Left main loop for call %s", ca_->getCallId().c_str()); + DEBUG("Left main loop for call %s", call_.getCallId().c_str()); +} + +void AudioZrtpSession::incrementTimestampForDTMF() +{ + timestamp_ += 160; +} + +void AudioZrtpSession::setSessionMedia(AudioCodec &audioCodec) +{ + AudioRtpSession::setSessionMedia(audioCodec); } + } diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.h b/daemon/src/audio/audiortp/audio_zrtp_session.h index 3a19a5e3fd148e2e9090965a0b058bb56296407f..65a86fa352e3fe24d559c4b10bc51364b694afea 100644 --- a/daemon/src/audio/audiortp/audio_zrtp_session.h +++ b/daemon/src/audio/audiortp/audio_zrtp_session.h @@ -40,36 +40,39 @@ using std::ptrdiff_t; #include <libzrtpcpp/ZrtpUserCallback.h> #include "audio_rtp_session.h" -#include <cc++/numbers.h> // OST::Time +// #include <commoncpp/numbers.h> // OST::Time class SIPCall; +class AudioCodec; namespace sfl { -class ZrtpZidException: public std::runtime_error { +class ZrtpZidException : public std::runtime_error { public: ZrtpZidException(const std::string& str = "") : std::runtime_error("ZRTP ZID initialization failed." + str) {} }; -// class AudioZrtpSession : public ost::TimerPort, public ost::SymmetricZRTPSession, public AudioRtpRecordHandler -class AudioZrtpSession : public AudioRtpSession, protected ost::Thread, public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue> { +class AudioZrtpSession : + public AudioRtpSession, protected ost::Thread, + public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue> { public: - AudioZrtpSession(SIPCall * sipcall, const std::string& zidFilename); + AudioZrtpSession(SIPCall &call, const std::string& zidFilename); ~AudioZrtpSession(); - virtual void final(); - // Thread associated method virtual void run(); - virtual bool onRTPPacketRecv(ost::IncomingRTPPkt& pkt) { + virtual bool onRTPPacketRecv(ost::IncomingRTPPkt &pkt) { return AudioRtpSession::onRTPPacketRecv(pkt); } private: + void sendMicData(); void initializeZid(); std::string zidFilename_; + void incrementTimestampForDTMF(); + void setSessionMedia(AudioCodec &codec); }; } diff --git a/daemon/src/audio/audiortp/zrtp_session_callback.cpp b/daemon/src/audio/audiortp/zrtp_session_callback.cpp index 270468a80ea2a8fc8e683d515610d31dce7d0a17..635180a85a0adf68b5f48e678b7f9d9c18a3dd37 100644 --- a/daemon/src/audio/audiortp/zrtp_session_callback.cpp +++ b/daemon/src/audio/audiortp/zrtp_session_callback.cpp @@ -28,16 +28,14 @@ * as that of the covered work. */ #include "zrtp_session_callback.h" -#include "global.h" +#include "logger.h" #include "sip/sipcall.h" #include "dbus/dbusmanager.h" #include "dbus/callmanager.h" #include "manager.h" #include <cstdlib> -#include <string> #include <map> -#include <utility> // for std::pair using namespace GnuZrtpCodes; @@ -45,18 +43,12 @@ using namespace ost; namespace sfl { -ZrtpSessionCallback::ZrtpSessionCallback(SIPCall *sipcall) : - sipcall_(sipcall) +ZrtpSessionCallback::ZrtpSessionCallback(SIPCall &call) : call_(call) { - using std::pair; - using std::string; - // we've already initialized the maps, we only need to check one if (not infoMap_.empty()) return; - DEBUG("Zrtp: Initialize callbacks"); - // Information Map infoMap_[InfoHelloReceived] = "Hello received, preparing a Commit"; infoMap_[InfoCommitDHGenerated] = "Commit: Generated a public DH key"; @@ -111,33 +103,31 @@ ZrtpSessionCallback::ZrtpSessionCallback(SIPCall *sipcall) : void ZrtpSessionCallback::secureOn(std::string cipher) { - DEBUG("Zrtp: Secure mode is on with cipher %s", cipher.c_str()); - Manager::instance().getDbusManager()->getCallManager()->secureZrtpOn(sipcall_->getCallId(), cipher); + DEBUG("Secure mode is on with cipher %s", cipher.c_str()); + Manager::instance().getDbusManager()->getCallManager()->secureZrtpOn(call_.getCallId(), cipher); } void ZrtpSessionCallback::secureOff() { - DEBUG("Zrtp: Secure mode is off"); - Manager::instance().getDbusManager()->getCallManager()->secureZrtpOff(sipcall_->getCallId()); + DEBUG("Secure mode is off"); + Manager::instance().getDbusManager()->getCallManager()->secureZrtpOff(call_.getCallId()); } void ZrtpSessionCallback::showSAS(std::string sas, bool verified) { - DEBUG("Zrtp: SAS is: %s", sas.c_str()); - Manager::instance().getDbusManager()->getCallManager()->showSAS(sipcall_->getCallId(), sas, verified); + DEBUG("SAS is: %s", sas.c_str()); + Manager::instance().getDbusManager()->getCallManager()->showSAS(call_.getCallId(), sas, verified); } - void ZrtpSessionCallback::zrtpNotSuppOther() { - DEBUG("Zrtp: Callee does not support ZRTP"); - Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(sipcall_->getCallId()); + DEBUG("Callee does not support ZRTP"); + Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(call_.getCallId()); } - void ZrtpSessionCallback::showMessage(GnuZrtpCodes::MessageSeverity sev, int32_t subCode) { @@ -156,20 +146,20 @@ ZrtpSessionCallback::zrtpNegotiationFailed(MessageSeverity severity, int subCode if (severity == ZrtpError) { if (subCode < 0) { // received an error packet from peer subCode *= -1; - DEBUG("Zrtp: Received error packet: "); + DEBUG("Received error packet: "); } else - DEBUG("Zrtp: Sent error packet: "); + DEBUG("Sent error packet: "); std::map<int32, std::string>::const_iterator iter = zrtpMap_.find(subCode); if (iter != zrtpMap_.end()) { DEBUG("%s", iter->second.c_str()); - Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(sipcall_->getCallId(), iter->second, "ZRTP"); + Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(call_.getCallId(), iter->second, "ZRTP"); } } else { std::map<int32, std::string>::const_iterator iter = severeMap_.find(subCode); if (iter != severeMap_.end()) { DEBUG("%s", iter->second.c_str()); - Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(sipcall_->getCallId(), iter->second, "severe"); + Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(call_.getCallId(), iter->second, "severe"); } } } @@ -177,8 +167,8 @@ ZrtpSessionCallback::zrtpNegotiationFailed(MessageSeverity severity, int subCode void ZrtpSessionCallback::confirmGoClear() { - DEBUG("Zrtp: Received go clear message. Until confirmation, ZRTP won't send any data"); - Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(sipcall_->getCallId()); + DEBUG("Received go clear message. Until confirmation, ZRTP won't send any data"); + Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(call_.getCallId()); } std::map<int32, std::string> ZrtpSessionCallback::infoMap_; diff --git a/daemon/src/audio/audiortp/zrtp_session_callback.h b/daemon/src/audio/audiortp/zrtp_session_callback.h index 08bb9cf4fb4c9bffd2f9fbc49d50520dda88a6c3..1577efe949326c85ba7e3cd94c00655d42ad8f6b 100644 --- a/daemon/src/audio/audiortp/zrtp_session_callback.h +++ b/daemon/src/audio/audiortp/zrtp_session_callback.h @@ -28,8 +28,8 @@ * as that of the covered work. */ -#ifndef __ZRTP_SESSION_CALLBACK_H__ -#define __ZRTP_SESSION_CALLBACK_H__ +#ifndef ZRTP_SESSION_CALLBACK_H_ +#define ZRTP_SESSION_CALLBACK_H_ #include <cstddef> using std::ptrdiff_t; @@ -37,9 +37,8 @@ using std::ptrdiff_t; #include <libzrtpcpp/zrtpccrtp.h> #include <libzrtpcpp/ZrtpQueue.h> #include <libzrtpcpp/ZrtpUserCallback.h> -#include <exception> +#include <string> #include <map> -#include "noncopyable.h" class SIPCall; @@ -47,7 +46,7 @@ namespace sfl { class ZrtpSessionCallback: public ZrtpUserCallback { public: - ZrtpSessionCallback(SIPCall *sipcall); + ZrtpSessionCallback(SIPCall &call); void secureOn(std::string cipher); void secureOff(); @@ -58,12 +57,11 @@ class ZrtpSessionCallback: public ZrtpUserCallback { void confirmGoClear(); private: - NON_COPYABLE(ZrtpSessionCallback); - SIPCall* sipcall_; + SIPCall &call_; static std::map<int32, std::string> infoMap_; static std::map<int32, std::string> warningMap_; static std::map<int32, std::string> severeMap_; static std::map<int32, std::string> zrtpMap_; }; } -#endif // __ZRTP_SESSION_CALLBACK_H__ +#endif // ZRTP_SESSION_CALLBACK_H_ diff --git a/daemon/src/audio/codecs/Makefile.am b/daemon/src/audio/codecs/Makefile.am index e18478023780cb1044bc6bcf630878d65e1ff476..f696c728bd3be79c737982a01a5d21662f6b6871 100644 --- a/daemon/src/audio/codecs/Makefile.am +++ b/daemon/src/audio/codecs/Makefile.am @@ -8,7 +8,6 @@ libcodecdescriptor_la_LIBADD = $(CCRTP_LIBS) if BUILD_GSM GSM_LIB = libcodec_gsm.so libcodec_gsm_so_SOURCES = gsmcodec.cpp -libcodec_gsm_so_CFLAGS = -fPIC -g -Wall libcodec_gsm_so_CXXFLAGS = -fPIC -g -Wall libcodec_gsm_so_LDFLAGS = --shared -lc -lgsm libcodec_gsm_so_LDADD = libcodecdescriptor.la @@ -18,9 +17,8 @@ endif if BUILD_SPEEX SPEEX_NB_LIB = libcodec_speex_nb.so libcodec_speex_nb_so_SOURCES = speexcodec_nb.cpp -libcodec_speex_nb_so_CFLAGS = -fPIC -g -Wall libcodec_speex_nb_so_CXXFLAGS = -fPIC -g -Wall $(SPEEXDSP) -libcodec_speex_nb_so_LDFLAGS = --shared -lc -lspeex $(SPEEX_NIMP) +libcodec_speex_nb_so_LDFLAGS = --shared -lc -lspeex libcodec_speex_nb_so_LDADD = libcodecdescriptor.la INSTALL_SPEEX_NB_RULE = install-libcodec_speex_nb_so endif @@ -28,9 +26,8 @@ endif if BUILD_SPEEX SPEEX_WB_LIB = libcodec_speex_wb.so libcodec_speex_wb_so_SOURCES = speexcodec_wb.cpp -libcodec_speex_wb_so_CFLAGS = -fPIC -g -Wall libcodec_speex_wb_so_CXXFLAGS = -fPIC -g -Wall $(SPEEXDSP) -libcodec_speex_wb_so_LDFLAGS = --shared -lc -lspeex $(SPEEX_NIMP) +libcodec_speex_wb_so_LDFLAGS = --shared -lc -lspeex libcodec_speex_wb_so_LDADD = libcodecdescriptor.la INSTALL_SPEEX_WB_RULE = install-libcodec_speex_wb_so endif @@ -38,57 +35,33 @@ endif if BUILD_SPEEX SPEEX_UB_LIB = libcodec_speex_ub.so libcodec_speex_ub_so_SOURCES = speexcodec_ub.cpp -libcodec_speex_ub_so_CFLAGS = -fPIC -g -Wall libcodec_speex_ub_so_CXXFLAGS = -fPIC -g -Wall $(SPEEXDSP) -libcodec_speex_ub_so_LDFLAGS = --shared -lc -lspeex $(SPEEX_NIMP) +libcodec_speex_ub_so_LDFLAGS = --shared -lc -lspeex libcodec_speex_ub_so_LDADD = libcodecdescriptor.la INSTALL_SPEEX_UB_RULE = install-libcodec_speex_ub_so endif -if BUILD_CELT_91 -CELT_LIB = libcodec_celt.so -libcodec_celt_so_SOURCES = celtcodec.cpp -libcodec_celt_so_CFLAGS = -fPIC -g -Wall -DBUILD_CELT_91 -libcodec_celt_so_CXXFLAGS = -fPIC -g -Wall -DBUILD_CELT_91 -libcodec_celt_so_LDFLAGS = --shared -lc -lcelt0 $(CELT_NIMP) -libcodec_celt_so_LDADD = libcodecdescriptor.la -INSTALL_CELT_RULE = install-libcodec_celt_so -endif - -if BUILD_CELT_71 -CELT_LIB = libcodec_celt.so -libcodec_celt_so_SOURCES = celtcodec.cpp -libcodec_celt_so_CFLAGS = -fPIC -g -Wall -DBUILD_CELT_71 -libcodec_celt_so_CXXFLAGS = -fPIC -g -Wall -DBUILD_CELT_71 -libcodec_celt_so_LDFLAGS = --shared -lc -lcelt0 $(CELT_NIMP) -libcodec_celt_so_LDADD = libcodecdescriptor.la -INSTALL_CELT_RULE = install-libcodec_celt_so -endif - -noinst_PROGRAMS = libcodec_ulaw.so libcodec_alaw.so libcodec_g722.so $(GSM_LIB) $(SPEEX_NB_LIB) $(SPEEX_WB_LIB) $(SPEEX_UB_LIB) $(CELT_LIB) +noinst_PROGRAMS = libcodec_ulaw.so libcodec_alaw.so libcodec_g722.so $(GSM_LIB) $(SPEEX_NB_LIB) $(SPEEX_WB_LIB) $(SPEEX_UB_LIB) noinst_HEADERS = audiocodec.h audiocodecfactory.h speexcodec.h g722.h libcodec_ulaw_so_SOURCES = ulaw.cpp -libcodec_ulaw_so_CFLAGS = -fPIC -g -Wall libcodec_ulaw_so_CXXFLAGS = -fPIC -g -Wall libcodec_ulaw_so_LDADD = libcodecdescriptor.la libcodec_ulaw_so_LDFLAGS = --shared -lc libcodec_alaw_so_SOURCES = alaw.cpp -libcodec_alaw_so_CFLAGS = -fPIC -g -Wall libcodec_alaw_so_CXXFLAGS = -fPIC -g -Wall libcodec_alaw_so_LDADD = libcodecdescriptor.la libcodec_alaw_so_LDFLAGS = --shared -lc libcodec_g722_so_SOURCES = g722.cpp -libcodec_g722_so_CFLAGS = -fPIC -g -Wall libcodec_g722_so_CXXFLAGS = -fPIC -g -Wall libcodec_g722_so_LDADD = libcodecdescriptor.la libcodec_g722_so_LDFLAGS = --shared -lc -install-exec-local: install-libcodec_ulaw_so install-libcodec_alaw_so install-libcodec_g722_so $(INSTALL_GSM_RULE) $(INSTALL_SPEEX_NB_RULE) $(INSTALL_SPEEX_WB_RULE) $(INSTALL_SPEEX_UB_RULE) $(INSTALL_CELT_RULE) $(INSTALL_ILBC_RULE) -uninstall-local: uninstall-libcodec_ulaw_so uninstall-libcodec_alaw_so uninstall-libcodec_g722_so uninstall-libcodec_gsm_so uninstall-libcodec_speex_nb_so uninstall-libcodec_speex_wb_so uninstall-libcodec_speex_ub_so uninstall-libcodec_celt_so +install-exec-local: install-libcodec_ulaw_so install-libcodec_alaw_so install-libcodec_g722_so $(INSTALL_GSM_RULE) $(INSTALL_SPEEX_NB_RULE) $(INSTALL_SPEEX_WB_RULE) $(INSTALL_SPEEX_UB_RULE) $(INSTALL_ILBC_RULE) +uninstall-local: uninstall-libcodec_ulaw_so uninstall-libcodec_alaw_so uninstall-libcodec_g722_so uninstall-libcodec_gsm_so uninstall-libcodec_speex_nb_so uninstall-libcodec_speex_wb_so uninstall-libcodec_speex_ub_so install-libcodec_ulaw_so: libcodec_ulaw.so @@ -112,9 +85,6 @@ install-libcodec_speex_wb_so: libcodec_speex_wb.so install-libcodec_speex_ub_so: libcodec_speex_ub.so mkdir -p $(sflcodecdir) $(INSTALL_PROGRAM) libcodec_speex_ub.so $(sflcodecdir) -install-libcodec_celt_so: libcodec_celt.so - mkdir -p $(sflcodecdir) - $(INSTALL_PROGRAM) libcodec_celt.so $(sflcodecdir) uninstall-libcodec_ulaw_so: rm -f $(sflcodecdir)/libcodec_ulaw.so @@ -130,7 +100,4 @@ uninstall-libcodec_speex_wb_so: rm -f $(sflcodecdir)/libcodec_speex_wb.so uninstall-libcodec_speex_ub_so: rm -f $(sflcodecdir)/libcodec_speex_ub.so -uninstall-libcodec_celt_so: - rm -f $(sflcodecdir)/libcodec_celt.so - rm -rf $(sflcodecdir) diff --git a/daemon/src/audio/codecs/alaw.cpp b/daemon/src/audio/codecs/alaw.cpp index 77df91008b0b4aad6830191c43372d49d9a45cfb..5a51a7ac7c85c976e1334bedb343eda1fba6c561 100644 --- a/daemon/src/audio/codecs/alaw.cpp +++ b/daemon/src/audio/codecs/alaw.cpp @@ -29,52 +29,40 @@ * as that of the covered work. */ -#include "global.h" -#include "../common.h" +#include "sfl_types.h" #include "audiocodec.h" -#include <cassert> class Alaw : public sfl::AudioCodec { public: // 8 PCMA A 8000 1 [RFC3551] - Alaw(int payload=8) - : sfl::AudioCodec(payload, "PCMA") { - clockRate_ = 8000; - frameSize_ = 160; // samples, 20 ms at 8kHz - channel_ = 1; + Alaw() : sfl::AudioCodec(8, "PCMA", 8000, 160, 1) { bitrate_ = 64; hasDynamicPayload_ = false; } - virtual ~Alaw() {} - - virtual int decode(short *dst, unsigned char *src, size_t buf_size) { - assert(buf_size == frameSize_ / 2 /* compression factor = 2:1 */ * sizeof(SFLDataFormat)); - unsigned char* end = src + buf_size; - - while (src < end) - *dst++ = ALawDecode(*src++); + private: + virtual int decode(SFLDataFormat *dst, unsigned char *src, size_t buf_size) + { + for (unsigned char* end = src + buf_size; src < end; ++src, ++dst) + *dst = ALawDecode(*src); return frameSize_; } - virtual int encode(unsigned char *dst, short *src, size_t buf_size) { - assert(buf_size >= frameSize_ / 2 /* compression factor = 2:1 */ * sizeof(SFLDataFormat)); - uint8* end = dst + frameSize_; - - while (dst < end) - *dst++ = ALawEncode(*src++); + virtual int encode(unsigned char *dst, SFLDataFormat *src, size_t /*buf_size*/) + { + for (unsigned char *end = dst + frameSize_; dst < end; ++src, ++dst) + *dst = ALawEncode(*src); return frameSize_ / 2 /* compression factor = 2:1 */ * sizeof(SFLDataFormat); } - - - int ALawDecode(uint8 alaw) { + int ALawDecode(uint8 alaw) + { alaw ^= 0x55; // A-law has alternate bits inverted for transmission - uint sign = alaw&0x80; - int linear = alaw&0x1f; + uint sign = alaw & 0x80; + int linear = alaw & 0x1f; linear <<= 4; linear += 8; // Add a 'half' bit (0x08) to place PCM value in middle of range @@ -92,8 +80,8 @@ class Alaw : public sfl::AudioCodec { return linear; } - - uint8 ALawEncode(int16 pcm16) { + uint8 ALawEncode(SFLDataFormat pcm16) + { int p = pcm16; uint a; // u-law value we are forming @@ -108,18 +96,18 @@ class Alaw : public sfl::AudioCodec { //calculate segment and interval numbers p >>= 4; - if (p>=0x20) { - if (p>=0x100) { + if (p >= 0x20) { + if (p >= 0x100) { p >>= 4; a += 0x40; } - if (p>=0x40) { + if (p >= 0x40) { p >>= 2; a += 0x20; } - if (p>=0x20) { + if (p >= 0x20) { p >>= 1; a += 0x10; } @@ -128,16 +116,19 @@ class Alaw : public sfl::AudioCodec { // a&0x70 now holds segment value and 'p' the interval number a += p; // a now equal to encoded A-law value - return a^0x55; // A-law has alternate bits inverted for transmission + // A-law has alternate bits inverted for transmission + return a ^ 0x55; } }; // the class factories +// cppcheck-suppress unusedFunction extern "C" sfl::Codec* create() { - return new Alaw(8); + return new Alaw; } +// cppcheck-suppress unusedFunction extern "C" void destroy(sfl::Codec* a) { delete a; diff --git a/daemon/src/audio/codecs/audiocodec.cpp b/daemon/src/audio/codecs/audiocodec.cpp index e9701c6b306ee196d00ef458c20ac70889f824e0..05287fbe8944dba38a6a7d2d0077561eadcae37b 100644 --- a/daemon/src/audio/codecs/audiocodec.cpp +++ b/daemon/src/audio/codecs/audiocodec.cpp @@ -36,47 +36,36 @@ using std::ptrdiff_t; namespace sfl { -AudioCodec::AudioCodec(uint8 payload, const std::string &codecName) : - codecName_(codecName), clockRate_(8000), channel_(1), frameSize_(0), - bitrate_(0.0), bandwidth_(0.0), hasDynamicPayload_(false), - payload_(payload), payloadFormat_(0) -{ - init(payload, clockRate_); -} +AudioCodec::AudioCodec(uint8 payload, const std::string &codecName, + int clockRate, int frameSize, int channel) : + codecName_(codecName), + clockRate_(clockRate), + channel_(channel), + frameSize_(frameSize), + bitrate_(0.0), + bandwidth_(0.0), + payload_(payload), + payloadFormat_(payload, clockRate_), + hasDynamicPayload_((payload_ >= 96 and payload_ <= 127) or payload_ == 9) +{} AudioCodec::AudioCodec(const AudioCodec& c) : - codecName_(c.codecName_), clockRate_(c.clockRate_), channel_(c.channel_), - frameSize_(c.frameSize_), bitrate_(c.bitrate_), bandwidth_(c.bandwidth_), - hasDynamicPayload_(c.hasDynamicPayload_), payload_(c.payload_), - payloadFormat_(c.payloadFormat_) -{ - init(c.payload_, c.clockRate_); -} - -void AudioCodec::init(uint8 payloadType, uint32 clockRate) -{ - payloadFormat_ = new ost::DynamicPayloadFormat(payloadType, clockRate); - - // If g722 (payload 9), we need to init libccrtp symetric sessions with using - // dynamic payload format. This way we get control on rtp clockrate. - hasDynamicPayload_ = ((payload_ >= 96 and payload_ <= 127) or payload_ == 9); -} - -std::string AudioCodec::getMimeType() const -{ - return "audio"; -} + codecName_(c.codecName_), + clockRate_(c.clockRate_), + channel_(c.channel_), + frameSize_(c.frameSize_), + bitrate_(c.bitrate_), + bandwidth_(c.bandwidth_), + payload_(c.payload_), + payloadFormat_(c.payloadFormat_), + hasDynamicPayload_(c.hasDynamicPayload_) +{} std::string AudioCodec::getMimeSubtype() const { return codecName_; } -const ost::PayloadFormat& AudioCodec::getPayloadFormat() -{ - return *payloadFormat_; -} - uint8 AudioCodec::getPayloadType() const { return payload_; @@ -97,19 +86,9 @@ unsigned AudioCodec::getFrameSize() const return frameSize_; } -uint8 AudioCodec::getChannel() const -{ - return channel_; -} - double AudioCodec::getBitRate() const { return bitrate_; } -AudioCodec::~AudioCodec() -{ - delete payloadFormat_; -} - } // end namespace sfl diff --git a/daemon/src/audio/codecs/audiocodec.h b/daemon/src/audio/codecs/audiocodec.h index f1b42ffe86d7f4c1afef1927947f9de13ffb14e9..11b2caf8e8cf811e8824313fad97a96fbf4bbc1b 100644 --- a/daemon/src/audio/codecs/audiocodec.h +++ b/daemon/src/audio/codecs/audiocodec.h @@ -33,7 +33,8 @@ #define __AUDIO_CODEC_H__ #include <string> -#include <dlfcn.h> +#include "cc_config.h" +#include <ccrtp/formats.h> // for ost::DynamicPayloadFormat #include "codec.h" @@ -42,51 +43,25 @@ // Also assume mono #define DEC_BUFFER_SIZE ((44100 * 20) / 1000) -namespace ost { -class PayloadFormat; -class DynamicPayloadFormat; -} - namespace sfl { class AudioCodec : public Codec { public: - AudioCodec(uint8 payload, const std::string &codecName); + AudioCodec(uint8 payload, const std::string &codecName, int clockRate, + int frameSize, int channel); /** * Copy constructor. */ AudioCodec(const AudioCodec& codec); - virtual ~AudioCodec(); - - /** - * @Override - */ - std::string getMimeType() const; + virtual ~AudioCodec() {}; /** * @Override */ std::string getMimeSubtype() const; - /** - * @Override - */ - const ost::PayloadFormat& getPayloadFormat(); - - /** - * @Override - */ - void setParameter(const std::string& /*name*/, const std::string& /*value*/) {}; - - /** - * @Override - */ - std::string getParameter(const std::string& /*name*/) const { - return ""; - }; - /** * Decode an input buffer and fill the output buffer with the decoded data * @param buffer_size : the size of the input buffer @@ -123,11 +98,6 @@ class AudioCodec : public Codec { */ uint32 getClockRate() const; - /** - * @return the number of audio channels. - */ - uint8 getChannel() const; - /** * @Override */ @@ -157,15 +127,14 @@ class AudioCodec : public Codec { /** Bandwidth */ double bandwidth_; - bool hasDynamicPayload_; - private: AudioCodec& operator=(const AudioCodec&); uint8 payload_; - ost::DynamicPayloadFormat* payloadFormat_; + ost::DynamicPayloadFormat payloadFormat_; - void init(uint8 payloadType, uint32 clockRate); +protected: + bool hasDynamicPayload_; }; } // end namespace sfl diff --git a/daemon/src/audio/codecs/audiocodecfactory.cpp b/daemon/src/audio/codecs/audiocodecfactory.cpp index 6436a6f6363cb2ec66dca3d83f67f6910a09b33c..0454caa4317d197346279110c46e28feafca4e6e 100644 --- a/daemon/src/audio/codecs/audiocodecfactory.cpp +++ b/daemon/src/audio/codecs/audiocodecfactory.cpp @@ -31,11 +31,16 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif + #include "audiocodecfactory.h" #include <cstdlib> #include <algorithm> // for std::find +#include <dlfcn.h> #include "fileutils.h" +#include "logger.h" AudioCodecFactory::AudioCodecFactory() : codecsMap_(), defaultCodecOrder_(), libCache_(), codecInMemory_() @@ -44,7 +49,7 @@ AudioCodecFactory::AudioCodecFactory() : CodecVector codecDynamicList(scanCodecDirectory()); if (codecDynamicList.empty()) - ERROR("Error - No codecs available"); + ERROR("No codecs available"); else { for (CodecVector::const_iterator iter = codecDynamicList.begin(); iter != codecDynamicList.end() ; ++iter) { @@ -78,11 +83,9 @@ std::vector<int32_t > AudioCodecFactory::getAudioCodecList() const { std::vector<int32_t> list; -int size = codecsMap_.size(); -printf("%d\n",size); for (CodecsMap::const_iterator iter = codecsMap_.begin(); iter != codecsMap_.end(); ++iter) if (iter->second) - list.push_back((int32_t)iter->first); + list.push_back((int32_t) iter->first); return list; } @@ -95,7 +98,7 @@ AudioCodecFactory::getCodec(int payload) const if (iter != codecsMap_.end()) return iter->second; else { - ERROR("CodecDescriptor: cannot find codec %i", payload); + ERROR("Cannot find codec %i", payload); return NULL; } } @@ -162,7 +165,7 @@ std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory() for (size_t i = 0 ; i < dirToScan.size() ; i++) { std::string dirStr = dirToScan[i]; - DEBUG("CodecDescriptor: Scanning %s to find audio codecs....", dirStr.c_str()); + DEBUG("Scanning %s to find audio codecs....", dirStr.c_str()); DIR *dir = opendir(dirStr.c_str()); @@ -198,7 +201,7 @@ sfl::Codec* AudioCodecFactory::loadCodec(const std::string &path) void * codecHandle = dlopen(path.c_str() , RTLD_LAZY); if (!codecHandle) { - ERROR("%s\n", dlerror()); + ERROR("%s", dlerror()); return NULL; } @@ -208,7 +211,7 @@ sfl::Codec* AudioCodecFactory::loadCodec(const std::string &path) char *error = dlerror(); if (error) { - ERROR("%s\n", error); + ERROR("%s", error); return NULL; } @@ -227,7 +230,7 @@ void AudioCodecFactory::unloadCodec(CodecHandlePointer p) char *error = dlerror(); if (error) { - ERROR("%s\n", error); + ERROR("%s", error); return; } @@ -247,7 +250,7 @@ sfl::Codec* AudioCodecFactory::instantiateCodec(int payload) const char *error = dlerror(); if (error) - ERROR("%s\n", error); + ERROR("%s", error); else return createCodec(); } diff --git a/daemon/src/audio/codecs/celtcodec.cpp b/daemon/src/audio/codecs/celtcodec.cpp deleted file mode 100644 index ccc59910e16944ee6782903a18bb8e22e6597ede..0000000000000000000000000000000000000000 --- a/daemon/src/audio/codecs/celtcodec.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#include "audiocodec.h" -#include <cstdio> -#include <celt/celt.h> -#include <stdexcept> -#include "noncopyable.h" - -class Celt : public sfl::AudioCodec { - - public: - Celt(int payload = 115) : sfl::AudioCodec(payload, "celt"), mode_(0), enc_(0), dec_(0) { - clockRate_ = 32000; - frameSize_ = 320; // fixed frameSize, TODO: support variable size from 64 to 512 - channel_ = 1; - bitrate_ = 0; - hasDynamicPayload_ = true; - int error = 0; - - mode_ = celt_mode_create(clockRate_, frameSize_, &error); - - if (error != CELT_OK) { - switch (error) { - case CELT_BAD_ARG: - throw std::runtime_error("Celt: An (or more) invalid argument (e.g. out of range)\n"); - break; - case CELT_INVALID_MODE: - throw std::runtime_error("Celt: The mode struct passed is invalid\n"); - break; - case CELT_INTERNAL_ERROR: - throw std::runtime_error("Celt: An internal error was detected\n"); - break; - case CELT_CORRUPTED_DATA: - throw std::runtime_error("Celt: The data passed (e.g. compressed data to decoder) is corrupted\n"); - break; - case CELT_UNIMPLEMENTED: - throw std::runtime_error("Celt: Invalid/unsupported request numbe\n"); - break; - case CELT_INVALID_STATE: - throw std::runtime_error("Celt: An encoder or decoder structure is invalid or already freed\n"); - break; - case CELT_ALLOC_FAIL: - throw std::runtime_error("Celt: Memory allocation has failed\n"); - break; - default: - throw std::runtime_error("Celt: Unknown error"); - } - - } - - if (mode_ == NULL) - throw std::runtime_error("Celt: Failed to create Celt mode"); - - enc_ = celt_encoder_create(mode_, channel_, &error); - dec_ = celt_decoder_create(mode_, channel_, &error); - - celt_encoder_ctl(enc_, CELT_SET_COMPLEXITY(2)); - celt_decoder_ctl(dec_, CELT_SET_COMPLEXITY(2)); - - celt_encoder_ctl(enc_, CELT_SET_PREDICTION(2)); - celt_decoder_ctl(dec_, CELT_SET_PREDICTION(2)); - } - - NON_COPYABLE(Celt); - - ~Celt() { - celt_encoder_destroy(enc_); - celt_decoder_destroy(dec_); - celt_mode_destroy(mode_); - } - - virtual int decode(short *dst, unsigned char *src, size_t buf_size) { -#ifdef BUILD_CELT_91 // == 91 - celt_decode(dec_, src, buf_size, (celt_int16*) dst, frameSize_); -#endif -#ifdef BUILD_CELT_71 - celt_decode(dec_, src, buf_size, (celt_int16*) dst); -#endif - return frameSize_; - } - - virtual int encode(unsigned char *dst, short *src, size_t buf_size) { - int len = 0; -#ifdef BUILD_CELT_91// == 91 - len = celt_encode(enc_, (celt_int16*) src, frameSize_, dst, buf_size); -#endif -#ifdef BUILD_CELT_71 - len = celt_encode(enc_, (celt_int16*) src, (celt_int16 *) src, dst, buf_size); -#endif - return len; - } - - private: - CELTMode *mode_; - - CELTEncoder *enc_; - CELTDecoder *dec_; -}; - -// the class factories -extern "C" sfl::Codec* create() -{ - return new Celt(115); -} - -extern "C" void destroy(sfl::Codec* a) -{ - delete a; -} diff --git a/daemon/src/audio/codecs/g722.cpp b/daemon/src/audio/codecs/g722.cpp index 7a7931ce7a5e3df6b21bef52201e28d74061c07a..0f2a264df0e1a46f03006ac81ef508397e0ff8c5 100644 --- a/daemon/src/audio/codecs/g722.cpp +++ b/daemon/src/audio/codecs/g722.cpp @@ -30,341 +30,291 @@ * as that of the covered work. */ - - -#include "global.h" -#include "../common.h" #include "audiocodec.h" +#include "sfl_types.h" #include "g722.h" -#include "noncopyable.h" -#include <stdlib.h> -#include <string.h> -#include <cassert> +#include <cstdlib> +#include <cstring> class G722 : public sfl::AudioCodec { public: - G722(int payload=9) : sfl::AudioCodec(payload, "G722"), - decode_s(new g722_decode_state_t), - encode_s(new g722_encode_state_t) { - clockRate_ = 16000; - frameSize_ = 320; // samples, 20 ms at 16kHz - channel_ = 1; + G722() : sfl::AudioCodec(9, "G722", 16000, 320, 1), decode_state_(), + encode_state_() { bitrate_ = 64; hasDynamicPayload_ = false; - g722_decode_init(); - g722_encode_init(); - } - - ~G722() { - g722_decode_release(); - g722_encode_release(); + g722_state_init(decode_state_); + g722_state_init(encode_state_); } - virtual int decode(short *dst, unsigned char *src, size_t buf_size) { - assert(buf_size == frameSize_ / sizeof(SFLDataFormat) * encode_s->bits_per_sample / 8); - return g722_decode((int16_t*) dst, (const uint8_t*) src, buf_size); + private: + virtual int decode(SFLDataFormat *dst, unsigned char *src, size_t buf_size) + { + return g722_decode(dst, src, buf_size); } - virtual int encode(unsigned char *dst, short *src, size_t buf_size) { - int out = g722_encode((uint8_t*) dst, (const int16_t*) src, frameSize_); - assert((size_t)out <= buf_size); + virtual int encode(unsigned char *dst, SFLDataFormat *src, size_t /*buf_size*/) + { + int out = g722_encode(dst, src, frameSize_); return out; } - - void g722_encode_init() { - encode_s->itu_test_mode = false; - - // 8 => 64 kbps; 7 => 56 kbps; 6 => 48 kbps - encode_s->bits_per_sample = 8; - - // Enable 8khz mode, encode using lower subband only - encode_s->eight_k = false; - - // Never set packed true when using 64 kbps - encode_s->packed = false; - - memset(encode_s->band, 0, sizeof(decode_s->band)); - encode_s->band[0].det = 32; - encode_s->band[1].det = 8; - - memset(encode_s->x, 0, sizeof(encode_s->x)); - - decode_s->in_buffer = 0; - decode_s->in_bits = 0; - decode_s->out_buffer = 0; - decode_s->out_bits = 0; - } - - void g722_decode_init() { - - decode_s->itu_test_mode = false; + static void g722_state_init(g722_state_t &state) + { + state.itu_test_mode = false; // 8 => 64 kbps; 7 => 56 kbps; 6 => 48 kbps - decode_s->bits_per_sample = 8; + state.bits_per_sample = 8; // Enable 8khz mode, encode using lower subband only - decode_s->eight_k = false; + state.eight_k = false; // Never set packed true when using 64 kbps - decode_s->packed = false; + state.packed = false; - memset(decode_s->band, 0, sizeof(decode_s->band)); - decode_s->band[0].det = 32; - decode_s->band[1].det = 8; + memset(state.band, 0, sizeof(state.band)); + state.band[0].det = 32; + state.band[1].det = 8; - decode_s->in_bits = 0; + memset(state.x, 0, sizeof(state.x)); - memset(decode_s->x, 0, sizeof(decode_s->x)); - - decode_s->in_buffer = 0; - decode_s->in_bits = 0; - decode_s->out_buffer = 0; - decode_s->out_bits = 0; + state.in_buffer = 0; + state.in_bits = 0; + state.out_buffer = 0; + state.out_bits = 0; } - int16_t saturate(int32_t amp) { - int16_t amp16 = 0; + SFLDataFormat saturate(int32_t amp) + { + SFLDataFormat amp16 = 0; /* Hopefully this is optimised for the common case - not clipping */ - amp16 = (int16_t) amp; + amp16 = (SFLDataFormat) amp; if (amp == amp16) return amp16; if (amp > INT16_MAX) - return INT16_MAX; + return INT16_MAX; - return INT16_MIN; + return INT16_MIN; } - - void block4_encode(int band, int d) { + void block4_encode(int band, int d) + { int wd1 = 0; int wd2 = 0; int wd3 = 0; int i = 0; /* Block 4, RECONS */ - encode_s->band[band].d[0] = d; - encode_s->band[band].r[0] = saturate(encode_s->band[band].s + d); + encode_state_.band[band].d[0] = d; + encode_state_.band[band].r[0] = saturate(encode_state_.band[band].s + d); /* Block 4, PARREC */ - encode_s->band[band].p[0] = saturate(encode_s->band[band].sz + d); + encode_state_.band[band].p[0] = saturate(encode_state_.band[band].sz + d); /* Block 4, UPPOL2 */ for (i = 0; i < 3; i++) - encode_s->band[band].sg[i] = encode_s->band[band].p[i] >> 15; + encode_state_.band[band].sg[i] = encode_state_.band[band].p[i] >> 15; - wd1 = saturate(encode_s->band[band].a[1] << 2); + wd1 = saturate(encode_state_.band[band].a[1] << 2); - wd2 = (encode_s->band[band].sg[0] == encode_s->band[band].sg[1]) ? -wd1 : wd1; + wd2 = (encode_state_.band[band].sg[0] == encode_state_.band[band].sg[1]) ? -wd1 : wd1; if (wd2 > 32767) wd2 = 32767; - wd3 = (wd2 >> 7) + ((encode_s->band[band].sg[0] == encode_s->band[band].sg[2]) ? 128 : -128); + wd3 = (wd2 >> 7) + ((encode_state_.band[band].sg[0] == encode_state_.band[band].sg[2]) ? 128 : -128); - wd3 += (encode_s->band[band].a[2]*32512) >> 15; + wd3 += (encode_state_.band[band].a[2]*32512) >> 15; if (wd3 > 12288) wd3 = 12288; else if (wd3 < -12288) wd3 = -12288; - encode_s->band[band].ap[2] = wd3; + encode_state_.band[band].ap[2] = wd3; /* Block 4, UPPOL1 */ - encode_s->band[band].sg[0] = encode_s->band[band].p[0] >> 15; + encode_state_.band[band].sg[0] = encode_state_.band[band].p[0] >> 15; - encode_s->band[band].sg[1] = encode_s->band[band].p[1] >> 15; + encode_state_.band[band].sg[1] = encode_state_.band[band].p[1] >> 15; - wd1 = (encode_s->band[band].sg[0] == encode_s->band[band].sg[1]) ? 192 : -192; + wd1 = (encode_state_.band[band].sg[0] == encode_state_.band[band].sg[1]) ? 192 : -192; - wd2 = (encode_s->band[band].a[1]*32640) >> 15; + wd2 = (encode_state_.band[band].a[1]*32640) >> 15; - encode_s->band[band].ap[1] = saturate(wd1 + wd2); + encode_state_.band[band].ap[1] = saturate(wd1 + wd2); - wd3 = saturate(15360 - encode_s->band[band].ap[2]); + wd3 = saturate(15360 - encode_state_.band[band].ap[2]); - if (encode_s->band[band].ap[1] > wd3) - encode_s->band[band].ap[1] = wd3; - else if (encode_s->band[band].ap[1] < -wd3) - encode_s->band[band].ap[1] = -wd3; + if (encode_state_.band[band].ap[1] > wd3) + encode_state_.band[band].ap[1] = wd3; + else if (encode_state_.band[band].ap[1] < -wd3) + encode_state_.band[band].ap[1] = -wd3; /* Block 4, UPZERO */ wd1 = (d == 0) ? 0 : 128; - encode_s->band[band].sg[0] = d >> 15; + encode_state_.band[band].sg[0] = d >> 15; for (i = 1; i < 7; i++) { - encode_s->band[band].sg[i] = encode_s->band[band].d[i] >> 15; - wd2 = (encode_s->band[band].sg[i] == encode_s->band[band].sg[0]) ? wd1 : -wd1; - wd3 = (encode_s->band[band].b[i]*32640) >> 15; - encode_s->band[band].bp[i] = saturate(wd2 + wd3); + encode_state_.band[band].sg[i] = encode_state_.band[band].d[i] >> 15; + wd2 = (encode_state_.band[band].sg[i] == encode_state_.band[band].sg[0]) ? wd1 : -wd1; + wd3 = (encode_state_.band[band].b[i]*32640) >> 15; + encode_state_.band[band].bp[i] = saturate(wd2 + wd3); } /* Block 4, DELAYA */ for (i = 6; i > 0; i--) { - encode_s->band[band].d[i] = encode_s->band[band].d[i - 1]; - encode_s->band[band].b[i] = encode_s->band[band].bp[i]; + encode_state_.band[band].d[i] = encode_state_.band[band].d[i - 1]; + encode_state_.band[band].b[i] = encode_state_.band[band].bp[i]; } for (i = 2; i > 0; i--) { - encode_s->band[band].r[i] = encode_s->band[band].r[i - 1]; - encode_s->band[band].p[i] = encode_s->band[band].p[i - 1]; - encode_s->band[band].a[i] = encode_s->band[band].ap[i]; + encode_state_.band[band].r[i] = encode_state_.band[band].r[i - 1]; + encode_state_.band[band].p[i] = encode_state_.band[band].p[i - 1]; + encode_state_.band[band].a[i] = encode_state_.band[band].ap[i]; } /* Block 4, FILTEP */ - wd1 = saturate(encode_s->band[band].r[1] + encode_s->band[band].r[1]); + wd1 = saturate(encode_state_.band[band].r[1] + encode_state_.band[band].r[1]); - wd1 = (encode_s->band[band].a[1]*wd1) >> 15; + wd1 = (encode_state_.band[band].a[1]*wd1) >> 15; - wd2 = saturate(encode_s->band[band].r[2] + encode_s->band[band].r[2]); + wd2 = saturate(encode_state_.band[band].r[2] + encode_state_.band[band].r[2]); - wd2 = (encode_s->band[band].a[2]*wd2) >> 15; + wd2 = (encode_state_.band[band].a[2]*wd2) >> 15; - encode_s->band[band].sp = saturate(wd1 + wd2); + encode_state_.band[band].sp = saturate(wd1 + wd2); /* Block 4, FILTEZ */ - encode_s->band[band].sz = 0; + encode_state_.band[band].sz = 0; for (i = 6; i > 0; i--) { - wd1 = saturate(encode_s->band[band].d[i] + encode_s->band[band].d[i]); - encode_s->band[band].sz += (encode_s->band[band].b[i]*wd1) >> 15; + wd1 = saturate(encode_state_.band[band].d[i] + encode_state_.band[band].d[i]); + encode_state_.band[band].sz += (encode_state_.band[band].b[i]*wd1) >> 15; } - encode_s->band[band].sz = saturate(encode_s->band[band].sz); + encode_state_.band[band].sz = saturate(encode_state_.band[band].sz); /* Block 4, PREDIC */ - encode_s->band[band].s = saturate(encode_s->band[band].sp + encode_s->band[band].sz); + encode_state_.band[band].s = saturate(encode_state_.band[band].sp + encode_state_.band[band].sz); } - void block4_decode(int band, int d) { + void block4_decode(int band, int d) + { int wd1 = 0; int wd2 = 0; int wd3 = 0; int i = 0; /* Block 4, RECONS */ - decode_s->band[band].d[0] = d; - decode_s->band[band].r[0] = saturate(decode_s->band[band].s + d); + decode_state_.band[band].d[0] = d; + decode_state_.band[band].r[0] = saturate(decode_state_.band[band].s + d); /* Block 4, PARREC */ - decode_s->band[band].p[0] = saturate(decode_s->band[band].sz + d); + decode_state_.band[band].p[0] = saturate(decode_state_.band[band].sz + d); /* Block 4, UPPOL2 */ for (i = 0; i < 3; i++) - decode_s->band[band].sg[i] = decode_s->band[band].p[i] >> 15; + decode_state_.band[band].sg[i] = decode_state_.band[band].p[i] >> 15; - wd1 = saturate(decode_s->band[band].a[1] << 2); + wd1 = saturate(decode_state_.band[band].a[1] << 2); - wd2 = (decode_s->band[band].sg[0] == decode_s->band[band].sg[1]) ? -wd1 : wd1; + wd2 = (decode_state_.band[band].sg[0] == decode_state_.band[band].sg[1]) ? -wd1 : wd1; if (wd2 > 32767) wd2 = 32767; - wd3 = (decode_s->band[band].sg[0] == decode_s->band[band].sg[2]) ? 128 : -128; + wd3 = (decode_state_.band[band].sg[0] == decode_state_.band[band].sg[2]) ? 128 : -128; wd3 += (wd2 >> 7); - wd3 += (decode_s->band[band].a[2]*32512) >> 15; + wd3 += (decode_state_.band[band].a[2]*32512) >> 15; if (wd3 > 12288) wd3 = 12288; else if (wd3 < -12288) wd3 = -12288; - decode_s->band[band].ap[2] = wd3; + decode_state_.band[band].ap[2] = wd3; /* Block 4, UPPOL1 */ - decode_s->band[band].sg[0] = decode_s->band[band].p[0] >> 15; + decode_state_.band[band].sg[0] = decode_state_.band[band].p[0] >> 15; - decode_s->band[band].sg[1] = decode_s->band[band].p[1] >> 15; + decode_state_.band[band].sg[1] = decode_state_.band[band].p[1] >> 15; - wd1 = (decode_s->band[band].sg[0] == decode_s->band[band].sg[1]) ? 192 : -192; + wd1 = (decode_state_.band[band].sg[0] == decode_state_.band[band].sg[1]) ? 192 : -192; - wd2 = (decode_s->band[band].a[1]*32640) >> 15; + wd2 = (decode_state_.band[band].a[1]*32640) >> 15; - decode_s->band[band].ap[1] = saturate(wd1 + wd2); + decode_state_.band[band].ap[1] = saturate(wd1 + wd2); - wd3 = saturate(15360 - decode_s->band[band].ap[2]); + wd3 = saturate(15360 - decode_state_.band[band].ap[2]); - if (decode_s->band[band].ap[1] > wd3) - decode_s->band[band].ap[1] = wd3; - else if (decode_s->band[band].ap[1] < -wd3) - decode_s->band[band].ap[1] = -wd3; + if (decode_state_.band[band].ap[1] > wd3) + decode_state_.band[band].ap[1] = wd3; + else if (decode_state_.band[band].ap[1] < -wd3) + decode_state_.band[band].ap[1] = -wd3; /* Block 4, UPZERO */ wd1 = (d == 0) ? 0 : 128; - decode_s->band[band].sg[0] = d >> 15; + decode_state_.band[band].sg[0] = d >> 15; for (i = 1; i < 7; i++) { - decode_s->band[band].sg[i] = decode_s->band[band].d[i] >> 15; - wd2 = (decode_s->band[band].sg[i] == decode_s->band[band].sg[0]) ? wd1 : -wd1; - wd3 = (decode_s->band[band].b[i]*32640) >> 15; - decode_s->band[band].bp[i] = saturate(wd2 + wd3); + decode_state_.band[band].sg[i] = decode_state_.band[band].d[i] >> 15; + wd2 = (decode_state_.band[band].sg[i] == decode_state_.band[band].sg[0]) ? wd1 : -wd1; + wd3 = (decode_state_.band[band].b[i]*32640) >> 15; + decode_state_.band[band].bp[i] = saturate(wd2 + wd3); } /* Block 4, DELAYA */ for (i = 6; i > 0; i--) { - decode_s->band[band].d[i] = decode_s->band[band].d[i - 1]; - decode_s->band[band].b[i] = decode_s->band[band].bp[i]; + decode_state_.band[band].d[i] = decode_state_.band[band].d[i - 1]; + decode_state_.band[band].b[i] = decode_state_.band[band].bp[i]; } for (i = 2; i > 0; i--) { - decode_s->band[band].r[i] = decode_s->band[band].r[i - 1]; - decode_s->band[band].p[i] = decode_s->band[band].p[i - 1]; - decode_s->band[band].a[i] = decode_s->band[band].ap[i]; + decode_state_.band[band].r[i] = decode_state_.band[band].r[i - 1]; + decode_state_.band[band].p[i] = decode_state_.band[band].p[i - 1]; + decode_state_.band[band].a[i] = decode_state_.band[band].ap[i]; } /* Block 4, FILTEP */ - wd1 = saturate(decode_s->band[band].r[1] + decode_s->band[band].r[1]); + wd1 = saturate(decode_state_.band[band].r[1] + decode_state_.band[band].r[1]); - wd1 = (decode_s->band[band].a[1]*wd1) >> 15; + wd1 = (decode_state_.band[band].a[1]*wd1) >> 15; - wd2 = saturate(decode_s->band[band].r[2] + decode_s->band[band].r[2]); + wd2 = saturate(decode_state_.band[band].r[2] + decode_state_.band[band].r[2]); - wd2 = (decode_s->band[band].a[2]*wd2) >> 15; + wd2 = (decode_state_.band[band].a[2]*wd2) >> 15; - decode_s->band[band].sp = saturate(wd1 + wd2); + decode_state_.band[band].sp = saturate(wd1 + wd2); /* Block 4, FILTEZ */ - decode_s->band[band].sz = 0; + decode_state_.band[band].sz = 0; for (i = 6; i > 0; i--) { - wd1 = saturate(decode_s->band[band].d[i] + decode_s->band[band].d[i]); - decode_s->band[band].sz += (decode_s->band[band].b[i]*wd1) >> 15; + wd1 = saturate(decode_state_.band[band].d[i] + decode_state_.band[band].d[i]); + decode_state_.band[band].sz += (decode_state_.band[band].b[i]*wd1) >> 15; } - decode_s->band[band].sz = saturate(decode_s->band[band].sz); + decode_state_.band[band].sz = saturate(decode_state_.band[band].sz); /* Block 4, PREDIC */ - decode_s->band[band].s = saturate(decode_s->band[band].sp + decode_s->band[band].sz); - } - - int g722_encode_release() { - delete decode_s; - decode_s = NULL; - return 0; - } - - - int g722_decode_release() { - delete encode_s; - encode_s = NULL; - return 0; + decode_state_.band[band].s = saturate(decode_state_.band[band].sp + decode_state_.band[band].sz); } - int g722_decode(int16_t amp[], const uint8_t g722_data[], int len) { + int g722_decode(SFLDataFormat amp[], const uint8_t g722_data[], int len) + { static const int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 }; static const int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 }; static const int ilb[32] = { @@ -436,22 +386,22 @@ class G722 : public sfl::AudioCodec { for (j = 0; j < len;) { - if (decode_s->packed) { + if (decode_state_.packed) { /* Unpack the code bits */ - if (decode_s->in_bits < decode_s->bits_per_sample) { - decode_s->in_buffer |= (g722_data[j++] << decode_s->in_bits); - decode_s->in_bits += 8; + if (decode_state_.in_bits < decode_state_.bits_per_sample) { + decode_state_.in_buffer |= (g722_data[j++] << decode_state_.in_bits); + decode_state_.in_bits += 8; } - code = decode_s->in_buffer & ((1 << decode_s->bits_per_sample) - 1); + code = decode_state_.in_buffer & ((1 << decode_state_.bits_per_sample) - 1); - decode_s->in_buffer >>= decode_s->bits_per_sample; - decode_s->in_bits -= decode_s->bits_per_sample; + decode_state_.in_buffer >>= decode_state_.bits_per_sample; + decode_state_.in_bits -= decode_state_.bits_per_sample; } else { code = g722_data[j++]; } - switch (decode_s->bits_per_sample) { + switch (decode_state_.bits_per_sample) { default: @@ -477,10 +427,10 @@ class G722 : public sfl::AudioCodec { } /* Block 5L, LOW BAND INVQBL */ - wd2 = (decode_s->band[0].det*wd2) >> 15; + wd2 = (decode_state_.band[0].det*wd2) >> 15; /* Block 5L, RECONS */ - rlow = decode_s->band[0].s + wd2; + rlow = decode_state_.band[0].s + wd2; /* Block 6L, LIMIT */ if (rlow > 16383) @@ -491,12 +441,12 @@ class G722 : public sfl::AudioCodec { /* Block 2L, INVQAL */ wd2 = qm4[wd1]; - dlowt = (decode_s->band[0].det*wd2) >> 15; + dlowt = (decode_state_.band[0].det*wd2) >> 15; /* Block 3L, LOGSCL */ wd2 = rl42[wd1]; - wd1 = (decode_s->band[0].nb*127) >> 7; + wd1 = (decode_state_.band[0].nb*127) >> 7; wd1 += wl[wd2]; @@ -505,25 +455,25 @@ class G722 : public sfl::AudioCodec { else if (wd1 > 18432) wd1 = 18432; - decode_s->band[0].nb = wd1; + decode_state_.band[0].nb = wd1; /* Block 3L, SCALEL */ - wd1 = (decode_s->band[0].nb >> 6) & 31; + wd1 = (decode_state_.band[0].nb >> 6) & 31; - wd2 = 8 - (decode_s->band[0].nb >> 11); + wd2 = 8 - (decode_state_.band[0].nb >> 11); wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); - decode_s->band[0].det = wd3 << 2; + decode_state_.band[0].det = wd3 << 2; block4_decode(0, dlowt); - if (!decode_s->eight_k) { + if (!decode_state_.eight_k) { /* Block 2H, INVQAH */ wd2 = qm2[ihigh]; - dhigh = (decode_s->band[1].det*wd2) >> 15; + dhigh = (decode_state_.band[1].det*wd2) >> 15; /* Block 5H, RECONS */ - rhigh = dhigh + decode_s->band[1].s; + rhigh = dhigh + decode_state_.band[1].s; /* Block 6H, LIMIT */ if (rhigh > 16383) @@ -534,7 +484,7 @@ class G722 : public sfl::AudioCodec { /* Block 2H, INVQAH */ wd2 = rh2[ihigh]; - wd1 = (decode_s->band[1].nb*127) >> 7; + wd1 = (decode_state_.band[1].nb*127) >> 7; wd1 += wh[wd2]; @@ -543,47 +493,47 @@ class G722 : public sfl::AudioCodec { else if (wd1 > 22528) wd1 = 22528; - decode_s->band[1].nb = wd1; + decode_state_.band[1].nb = wd1; /* Block 3H, SCALEH */ - wd1 = (decode_s->band[1].nb >> 6) & 31; + wd1 = (decode_state_.band[1].nb >> 6) & 31; - wd2 = 10 - (decode_s->band[1].nb >> 11); + wd2 = 10 - (decode_state_.band[1].nb >> 11); wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); - decode_s->band[1].det = wd3 << 2; + decode_state_.band[1].det = wd3 << 2; block4_decode(1, dhigh); } - if (decode_s->itu_test_mode) { - amp[outlen++] = (int16_t)(rlow << 1); - amp[outlen++] = (int16_t)(rhigh << 1); + if (decode_state_.itu_test_mode) { + amp[outlen++] = (SFLDataFormat)(rlow << 1); + amp[outlen++] = (SFLDataFormat)(rhigh << 1); } else { - if (decode_s->eight_k) { - amp[outlen++] = (int16_t) rlow; + if (decode_state_.eight_k) { + amp[outlen++] = (SFLDataFormat) rlow; } else { /* Apply the receive QMF */ for (i = 0; i < 22; i++) - decode_s->x[i] = decode_s->x[i + 2]; + decode_state_.x[i] = decode_state_.x[i + 2]; - decode_s->x[22] = rlow + rhigh; + decode_state_.x[22] = rlow + rhigh; - decode_s->x[23] = rlow - rhigh; + decode_state_.x[23] = rlow - rhigh; xout1 = 0; xout2 = 0; for (i = 0; i < 12; i++) { - xout2 += decode_s->x[2*i]*qmf_coeffs[i]; - xout1 += decode_s->x[2*i + 1]*qmf_coeffs[11 - i]; + xout2 += decode_state_.x[2*i]*qmf_coeffs[i]; + xout1 += decode_state_.x[2*i + 1]*qmf_coeffs[11 - i]; } - amp[outlen++] = (int16_t)(xout1 >> 12); + amp[outlen++] = (SFLDataFormat)(xout1 >> 12); - amp[outlen++] = (int16_t)(xout2 >> 12); + amp[outlen++] = (SFLDataFormat)(xout2 >> 12); } } } @@ -591,7 +541,8 @@ class G722 : public sfl::AudioCodec { return outlen; } - int g722_encode(uint8_t g722_data[], const int16_t amp[], int len) { + int g722_encode(uint8_t g722_data[], const SFLDataFormat amp[], int len) + { static const int q6[32] = { 0, 35, 72, 110, 150, 190, 233, 276, 323, 370, 422, 473, 530, 587, 650, 714, @@ -669,21 +620,21 @@ class G722 : public sfl::AudioCodec { xhigh = 0; for (j = 0; j < len;) { - if (encode_s->itu_test_mode) { + if (encode_state_.itu_test_mode) { xlow = xhigh = amp[j++] >> 1; } else { - if (encode_s->eight_k) { + if (encode_state_.eight_k) { xlow = amp[j++]; } else { /* Apply the transmit QMF */ /* Shuffle the buffer down */ for (i = 0; i < 22; i++) - encode_s->x[i] = encode_s->x[i + 2]; + encode_state_.x[i] = encode_state_.x[i + 2]; - encode_s->x[22] = amp[j++]; + encode_state_.x[22] = amp[j++]; - encode_s->x[23] = amp[j++]; + encode_state_.x[23] = amp[j++]; /* Discard every other QMF output */ sumeven = 0; @@ -691,8 +642,8 @@ class G722 : public sfl::AudioCodec { sumodd = 0; for (i = 0; i < 12; i++) { - sumodd += encode_s->x[2*i]*qmf_coeffs[i]; - sumeven += encode_s->x[2*i + 1]*qmf_coeffs[11 - i]; + sumodd += encode_state_.x[2*i]*qmf_coeffs[i]; + sumeven += encode_state_.x[2*i + 1]*qmf_coeffs[11 - i]; } xlow = (sumeven + sumodd) >> 13; @@ -702,13 +653,13 @@ class G722 : public sfl::AudioCodec { } /* Block 1L, SUBTRA */ - el = saturate(xlow - encode_s->band[0].s); + el = saturate(xlow - encode_state_.band[0].s); /* Block 1L, QUANTL */ wd = (el >= 0) ? el : - (el + 1); for (i = 1; i < 30; i++) { - wd1 = (q6[i]*encode_s->band[0].det) >> 12; + wd1 = (q6[i]*encode_state_.band[0].det) >> 12; if (wd < wd1) break; @@ -719,79 +670,79 @@ class G722 : public sfl::AudioCodec { /* Block 2L, INVQAL */ ril = ilow >> 2; wd2 = qm4[ril]; - dlow = (encode_s->band[0].det*wd2) >> 15; + dlow = (encode_state_.band[0].det*wd2) >> 15; /* Block 3L, LOGSCL */ il4 = rl42[ril]; - wd = (encode_s->band[0].nb*127) >> 7; - encode_s->band[0].nb = wd + wl[il4]; + wd = (encode_state_.band[0].nb*127) >> 7; + encode_state_.band[0].nb = wd + wl[il4]; - if (encode_s->band[0].nb < 0) - encode_s->band[0].nb = 0; - else if (encode_s->band[0].nb > 18432) - encode_s->band[0].nb = 18432; + if (encode_state_.band[0].nb < 0) + encode_state_.band[0].nb = 0; + else if (encode_state_.band[0].nb > 18432) + encode_state_.band[0].nb = 18432; /* Block 3L, SCALEL */ - wd1 = (encode_s->band[0].nb >> 6) & 31; + wd1 = (encode_state_.band[0].nb >> 6) & 31; - wd2 = 8 - (encode_s->band[0].nb >> 11); + wd2 = 8 - (encode_state_.band[0].nb >> 11); wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); - encode_s->band[0].det = wd3 << 2; + encode_state_.band[0].det = wd3 << 2; block4_encode(0, dlow); - if (encode_s->eight_k) { + if (encode_state_.eight_k) { /* Just leave the high bits as zero */ - code = (0xC0 | ilow) >> (8 - encode_s->bits_per_sample); + code = (0xC0 | ilow) >> (8 - encode_state_.bits_per_sample); } else { /* Block 1H, SUBTRA */ - eh = saturate(xhigh - encode_s->band[1].s); + eh = saturate(xhigh - encode_state_.band[1].s); /* Block 1H, QUANTH */ wd = (eh >= 0) ? eh : - (eh + 1); - wd1 = (564*encode_s->band[1].det) >> 12; + wd1 = (564*encode_state_.band[1].det) >> 12; mih = (wd >= wd1) ? 2 : 1; ihigh = (eh < 0) ? ihn[mih] : ihp[mih]; /* Block 2H, INVQAH */ wd2 = qm2[ihigh]; - dhigh = (encode_s->band[1].det*wd2) >> 15; + dhigh = (encode_state_.band[1].det*wd2) >> 15; /* Block 3H, LOGSCH */ ih2 = rh2[ihigh]; - wd = (encode_s->band[1].nb*127) >> 7; - encode_s->band[1].nb = wd + wh[ih2]; + wd = (encode_state_.band[1].nb*127) >> 7; + encode_state_.band[1].nb = wd + wh[ih2]; - if (encode_s->band[1].nb < 0) - encode_s->band[1].nb = 0; - else if (encode_s->band[1].nb > 22528) - encode_s->band[1].nb = 22528; + if (encode_state_.band[1].nb < 0) + encode_state_.band[1].nb = 0; + else if (encode_state_.band[1].nb > 22528) + encode_state_.band[1].nb = 22528; /* Block 3H, SCALEH */ - wd1 = (encode_s->band[1].nb >> 6) & 31; + wd1 = (encode_state_.band[1].nb >> 6) & 31; - wd2 = 10 - (encode_s->band[1].nb >> 11); + wd2 = 10 - (encode_state_.band[1].nb >> 11); wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); - encode_s->band[1].det = wd3 << 2; + encode_state_.band[1].det = wd3 << 2; block4_encode(1, dhigh); - code = ((ihigh << 6) | ilow) >> (8 - encode_s->bits_per_sample); + code = ((ihigh << 6) | ilow) >> (8 - encode_state_.bits_per_sample); } - if (encode_s->packed) { + if (encode_state_.packed) { /* Pack the code bits */ - encode_s->out_buffer |= (code << encode_s->out_bits); - encode_s->out_bits += encode_s->bits_per_sample; + encode_state_.out_buffer |= (code << encode_state_.out_bits); + encode_state_.out_bits += encode_state_.bits_per_sample; - if (encode_s->out_bits >= 8) { - g722_data[g722_bytes++] = (uint8_t)(encode_s->out_buffer & 0xFF); - encode_s->out_bits -= 8; - encode_s->out_buffer >>= 8; + if (encode_state_.out_bits >= 8) { + g722_data[g722_bytes++] = (uint8_t)(encode_state_.out_buffer & 0xFF); + encode_state_.out_bits -= 8; + encode_state_.out_buffer >>= 8; } } else { g722_data[g722_bytes++] = (uint8_t) code; @@ -801,20 +752,18 @@ class G722 : public sfl::AudioCodec { return g722_bytes; } - private: - NON_COPYABLE(G722); - - g722_decode_state_t *decode_s; - g722_encode_state_t *encode_s; - + g722_state_t decode_state_; + g722_state_t encode_state_; }; // the class factories +// cppcheck-suppress unusedFunction extern "C" sfl::Codec* create() { - return new G722(9); + return new G722; } +// cppcheck-suppress unusedFunction extern "C" void destroy(sfl::Codec* a) { delete a; diff --git a/daemon/src/audio/codecs/g722.h b/daemon/src/audio/codecs/g722.h index cb589e54c801af74b04f7ed4c236ede61839ee0c..b117a09ed06025b54d4865bcf287a7eb38c9c4cd 100644 --- a/daemon/src/audio/codecs/g722.h +++ b/daemon/src/audio/codecs/g722.h @@ -30,10 +30,8 @@ * as that of the covered work. */ - - -#if !defined(_G722_H_) -#define _G722_H_ +#ifndef G722_H_ +#define G722_H_ /** @@ -54,13 +52,13 @@ enum { }; #ifndef INT16_MAX -#define INT16_MAX 32767 +#define INT16_MAX 32767 #endif #ifndef INT16_MIN -#define INT16_MIN (-32768) +#define INT16_MIN (-32768) #endif -typedef struct { +struct g722_state_t { /*! TRUE if the operating in the special ITU test mode, with the band split filters disabled. */ int itu_test_mode; @@ -94,58 +92,6 @@ typedef struct { int in_bits; unsigned int out_buffer; int out_bits; -} g722_encode_state_t; - -typedef struct { - /*! TRUE if the operating in the special ITU test mode, with the band split filters - disabled. */ - int itu_test_mode; - /*! TRUE if the G.722 data is packed */ - int packed; - /*! TRUE if decode to 8k samples/second */ - int eight_k; - /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ - int bits_per_sample; - - /*! Signal history for the QMF */ - int x[24]; - - struct { - int s; - int sp; - int sz; - int r[3]; - int a[3]; - int ap[3]; - int p[3]; - int d[7]; - int b[7]; - int bp[7]; - int sg[7]; - int nb; - int det; - } band[2]; - - unsigned int in_buffer; - int in_bits; - unsigned int out_buffer; - int out_bits; -} g722_decode_state_t; - -#ifdef __cplusplus -extern "C" { -#endif - - void g722_encode_init(); - int g722_encode_release(); - int g722_encode(uint8_t g722_data[], const int16_t amp[], int len); - - void g722_decode_init(); - int g722_decode_release(); - int g722_decode(int16_t amp[], const uint8_t g722_data[], int len); - -#ifdef __cplusplus -} -#endif +}; -#endif +#endif // G722_H_ diff --git a/daemon/src/audio/codecs/gsmcodec.cpp b/daemon/src/audio/codecs/gsmcodec.cpp index 8160253587a3dc2df02f4ce596530d0fa1d6ac80..16f5fdcdd452b7bddcb07213fb6d11092db290be 100644 --- a/daemon/src/audio/codecs/gsmcodec.cpp +++ b/daemon/src/audio/codecs/gsmcodec.cpp @@ -31,8 +31,8 @@ #include "audiocodec.h" +#include "sfl_types.h" #include "noncopyable.h" -#include <cassert> #include <stdexcept> extern "C" { @@ -47,10 +47,8 @@ class Gsm : public sfl::AudioCodec { public: // _payload should be 3 - Gsm(int payload=3) : sfl::AudioCodec(payload, "GSM"), decode_gsmhandle_(NULL), encode_gsmhandle_(NULL) { - clockRate_ = 8000; - frameSize_ = 160; // samples, 20 ms at 8kHz - channel_ = 1; + Gsm() : sfl::AudioCodec(3, "GSM", 8000, 160, 1), + decode_gsmhandle_(NULL), encode_gsmhandle_(NULL) { bitrate_ = 13.3; hasDynamicPayload_ = false; @@ -61,22 +59,22 @@ class Gsm : public sfl::AudioCodec { throw std::runtime_error("ERROR: encode_gsm_create\n"); } - virtual ~Gsm() { + virtual ~Gsm() + { gsm_destroy(decode_gsmhandle_); gsm_destroy(encode_gsmhandle_); } - virtual int decode(short * dst, unsigned char * src, size_t buf_size) { - assert(buf_size == 33); - + virtual int decode(SFLDataFormat * dst, unsigned char * src, size_t /*buf_size*/) + { if (gsm_decode(decode_gsmhandle_, (gsm_byte*) src, (gsm_signal*) dst) < 0) throw std::runtime_error("ERROR: gsm_decode\n"); return frameSize_; } - virtual int encode(unsigned char * dst, short * src, size_t buf_size) { - assert(buf_size >= 33); + virtual int encode(unsigned char * dst, SFLDataFormat * src, size_t /*buf_size*/) + { gsm_encode(encode_gsmhandle_, (gsm_signal*) src, (gsm_byte*) dst); return 33; } @@ -87,11 +85,13 @@ class Gsm : public sfl::AudioCodec { gsm encode_gsmhandle_; }; +// cppcheck-suppress unusedFunction extern "C" sfl::Codec* create() { - return new Gsm(3); + return new Gsm; } +// cppcheck-suppress unusedFunction extern "C" void destroy(sfl::Codec* a) { delete a; diff --git a/daemon/src/audio/codecs/speexcodec.h b/daemon/src/audio/codecs/speexcodec.h index 7b53fcdce261ed1b24bb644341080f3faee599b9..7b5cb261bec21f47fcebac5423ee655e23f6cbd4 100644 --- a/daemon/src/audio/codecs/speexcodec.h +++ b/daemon/src/audio/codecs/speexcodec.h @@ -32,62 +32,35 @@ #include "global.h" #include "audiocodec.h" #include "noncopyable.h" -#include <cstdio> +#include "array_size.h" #include <speex/speex.h> #include <cassert> -static const unsigned int clockRate [3] = { - 8000, - 16000, - 32000 -}; -static const unsigned int frameSize[3] = { - 160, - 320, - 640, -}; -static const unsigned int bitRate[3] = { // FIXME : not using VBR? - 24, - 42, - 0, -}; -static const bool dynamicPayload[3] = { - true, - false, - true, -}; - -const SpeexMode* speexMode[3] = { - &speex_nb_mode, - &speex_wb_mode, - &speex_uwb_mode, // wb -}; - class Speex : public sfl::AudioCodec { public: - Speex(int payload) : - sfl::AudioCodec(payload, "speex"), speex_dec_bits_(), - speex_enc_bits_(), speex_dec_state_(0), speex_enc_state_(0), + Speex(int payload, unsigned clockRate, unsigned frameSize, + unsigned bitRate, bool dynamicPayload, const SpeexMode *mode) : + sfl::AudioCodec(payload, "speex", clockRate, frameSize, 1), + speex_dec_bits_(), + speex_enc_bits_(), + speex_dec_state_(0), + speex_enc_state_(0), speex_frame_size_(0) { assert(payload >= 110 && payload <= 112); assert(110 == PAYLOAD_CODEC_SPEEX_8000 && - 111 == PAYLOAD_CODEC_SPEEX_16000 && - 112 == PAYLOAD_CODEC_SPEEX_32000); - int type = payload - 110; + 111 == PAYLOAD_CODEC_SPEEX_16000 && + 112 == PAYLOAD_CODEC_SPEEX_32000); - clockRate_ = clockRate[type]; - frameSize_ = frameSize[type]; - channel_ = 1; - bitrate_ = bitRate[type]; - hasDynamicPayload_ = dynamicPayload[type]; + bitrate_ = bitRate; + hasDynamicPayload_ = dynamicPayload; // Init the decoder struct speex_bits_init(&speex_dec_bits_); - speex_dec_state_ = speex_decoder_init(speexMode[type]); + speex_dec_state_ = speex_decoder_init(mode); // Init the encoder struct speex_bits_init(&speex_enc_bits_); - speex_enc_state_ = speex_encoder_init(speexMode[type]); + speex_enc_state_ = speex_encoder_init(mode); speex_encoder_ctl(speex_enc_state_, SPEEX_SET_SAMPLING_RATE, &clockRate_); speex_decoder_ctl(speex_dec_state_, SPEEX_GET_FRAME_SIZE, &speex_frame_size_); diff --git a/daemon/src/audio/codecs/speexcodec_nb.cpp b/daemon/src/audio/codecs/speexcodec_nb.cpp index d9e5d0f9c649e96ce90080c7a010346017bdea71..a3066f4be16c96781d7baa7b2a60facfae14d573 100644 --- a/daemon/src/audio/codecs/speexcodec_nb.cpp +++ b/daemon/src/audio/codecs/speexcodec_nb.cpp @@ -32,11 +32,13 @@ #include "audiocodec.h" #include "speexcodec.h" +// cppcheck-suppress unusedFunction extern "C" sfl::Codec* create() { - return new Speex(110); + return new Speex(110, 8000, 160, 24, true, &speex_nb_mode); } +// cppcheck-suppress unusedFunction extern "C" void destroy(sfl::Codec* a) { delete a; diff --git a/daemon/src/audio/codecs/speexcodec_ub.cpp b/daemon/src/audio/codecs/speexcodec_ub.cpp index ffd7027676f2312700ff4dc0926acdca5a7e265d..4db65d509a294bd03cc90089630fbd6466ab4509 100644 --- a/daemon/src/audio/codecs/speexcodec_ub.cpp +++ b/daemon/src/audio/codecs/speexcodec_ub.cpp @@ -32,11 +32,13 @@ #include "audiocodec.h" #include "speexcodec.h" +// cppcheck-suppress unusedFunction extern "C" sfl::Codec* create() { - return new Speex(112); + return new Speex(112, 32000, 640, 0, true, &speex_uwb_mode); } +// cppcheck-suppress unusedFunction extern "C" void destroy(sfl::Codec* a) { delete a; diff --git a/daemon/src/audio/codecs/speexcodec_wb.cpp b/daemon/src/audio/codecs/speexcodec_wb.cpp index 1fd1fb8a5f6e74639b9f715d152634b7f3570f16..b220d3753c3134b074d0c29c75e33f62b285065e 100644 --- a/daemon/src/audio/codecs/speexcodec_wb.cpp +++ b/daemon/src/audio/codecs/speexcodec_wb.cpp @@ -32,11 +32,13 @@ #include "audiocodec.h" #include "speexcodec.h" +// cppcheck-suppress unusedFunction extern "C" sfl::Codec* create() { - return new Speex(111); + return new Speex(111, 16000, 320, 42, false, &speex_wb_mode); } +// cppcheck-suppress unusedFunction extern "C" void destroy(sfl::Codec* a) { delete a; diff --git a/daemon/src/audio/codecs/ulaw.cpp b/daemon/src/audio/codecs/ulaw.cpp index 5b6e7400c900e28d8ba4d095ded161a96e5ff0c1..29d18c6ba9cb92a30b1f173a753bdc5caa007556 100644 --- a/daemon/src/audio/codecs/ulaw.cpp +++ b/daemon/src/audio/codecs/ulaw.cpp @@ -29,91 +29,80 @@ * as that of the covered work. */ - -#include "global.h" -#include "../common.h" #include "audiocodec.h" -#include <cassert> +#include "sfl_types.h" class Ulaw : public sfl::AudioCodec { public: // 0 PCMU A 8000 1 [RFC3551] - Ulaw(int payload=0) - : sfl::AudioCodec(payload, "PCMU") { - clockRate_ = 8000; - frameSize_ = 160; // samples, 20 ms at 8kHz - channel_ = 1; + Ulaw() : sfl::AudioCodec(0, "PCMU", 8000, 160, 1) { bitrate_ = 64; hasDynamicPayload_ = false; } - virtual int decode(short *dst, unsigned char *src, size_t buf_size) { - assert(buf_size == frameSize_ / 2 /* compression factor = 2:1 */ * sizeof(SFLDataFormat)); - unsigned char* end = src+buf_size; - - while (src<end) - *dst++ = ULawDecode(*src++); + virtual int decode(SFLDataFormat *dst, unsigned char *src, size_t buf_size) { + for (unsigned char* end = src + buf_size; src < end; ++src, ++dst) + *dst = ULawDecode(*src); return frameSize_; } - virtual int encode(unsigned char *dst, short *src, size_t buf_size) { - assert(buf_size >= frameSize_ / 2 /* compression factor = 2:1 */ * sizeof(SFLDataFormat)); - uint8* end = dst + frameSize_; - - while (dst<end) - *dst++ = ULawEncode(*src++); + virtual int encode(unsigned char *dst, SFLDataFormat *src, size_t /*buf_size*/) { + for (unsigned char * end = dst + frameSize_; dst < end; ++src, ++dst) + *dst = ULawEncode(*src); return frameSize_ / 2 /* compression factor = 2:1 */ * sizeof(SFLDataFormat);; } - int ULawDecode(uint8 ulaw) { + SFLDataFormat ULawDecode(uint8 ulaw) + { ulaw ^= 0xff; // u-law has all bits inverted for transmission - int linear = ulaw&0x0f; + int linear = ulaw & 0x0f; linear <<= 3; linear |= 0x84; // Set MSB (0x80) and a 'half' bit (0x04) to place PCM value in middle of range - uint shift = ulaw>>4; + uint shift = ulaw >> 4; shift &= 7; linear <<= shift; linear -= 0x84; // Subract uLaw bias - if (ulaw&0x80) + if (ulaw & 0x80) return -linear; else return linear; } - uint8 ULawEncode(int16 pcm16) { + uint8 ULawEncode(SFLDataFormat pcm16) + { int p = pcm16; uint u; // u-law value we are forming - if (p<0) { + if (p < 0) { p = ~p; - u = 0x80^0x10^0xff; // Sign bit = 1 (^0x10 because this will get inverted later) ^0xff ^0xff to invert final u-Law code + u = 0x80 ^ 0x10 ^ 0xff; // Sign bit = 1 (^0x10 because this will get inverted later) ^0xff ^0xff to invert final u-Law code } else { - u = 0x00^0x10^0xff; // Sign bit = 0 (-0x10 because this amount extra will get added later) ^0xff to invert final u-Law code + u = 0x00 ^ 0x10 ^ 0xff; // Sign bit = 0 (-0x10 because this amount extra will get added later) ^0xff to invert final u-Law code } p += 0x84; // Add uLaw bias - if (p>0x7f00) + if (p > 0x7f00) p = 0x7f00; // Clip to 15 bits // Calculate segment and interval numbers p >>= 3; // Shift down to 13bit - if (p>=0x100) { + if (p >= 0x100) { p >>= 4; u ^= 0x40; } - if (p>=0x40) { + if (p >= 0x40) { p >>= 2; u ^= 0x20; } - if (p>=0x20) { + if (p >= 0x20) { p >>= 1; u ^= 0x10; } @@ -125,11 +114,13 @@ class Ulaw : public sfl::AudioCodec { }; // the class factories +// cppcheck-suppress unusedFunction extern "C" sfl::Codec* create() { - return new Ulaw(0); + return new Ulaw; } +// cppcheck-suppress unusedFunction extern "C" void destroy(sfl::Codec* a) { delete a; diff --git a/daemon/src/audio/common.h b/daemon/src/audio/common.h deleted file mode 100644 index e8a2b460fb8e6b436c5b25348dfcc2a155bbbfe9..0000000000000000000000000000000000000000 --- a/daemon/src/audio/common.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. - * Author: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -/* - Type definitions and helper macros which aren't part of Standard C++ - This will need to be edited on systems where 'char', 'short' and 'int' - have sizes different from 8, 16 and 32 bits. -*/ - -#ifndef __COMMON_H__ -#define __COMMON_H__ - - -// #define DEBUG /**< Defined when compiling code for debugging */ - -/* -Basic integer types. -Note 'int' is assumed to be in 2s complement format and at least 32 bits in size -*/ -typedef unsigned char uint8; /**< An 8 bit unsigned integer */ -typedef unsigned short uint16; /**< An 16 bit unsigned integer */ -typedef unsigned int uint32; /**< An 32 bit unsigned integer */ -typedef signed char int8; /**< An 8 bit signed integer (2s complement) */ -typedef signed short int16; /**< An 16 bit signed integer (2s complement) */ -typedef signed int int32; /**< An 32 bit signed integer (2s complement) */ -typedef unsigned int uint; /**< An unsigned integer or at least 32 bits */ - -#ifndef NULL -#define NULL 0 /**< Used to represent a null pointer type */ -#endif - -#ifdef _MSC_VER // Compiling for Microsoft Visual C++ - -#define DEBUGGER { _asm int 3 } /**< Invoke debugger */ -#define IMPORT __declspec(dllexport) /**< Mark a function which is to be imported from a DLL */ -#define EXPORT __declspec(dllexport) /**< Mark a function to be exported from a DLL */ -#define ASSERT(c) { if(!(c)) DEBUGGER; } /**< Assert that expression 'c' is true */ - -#else // Not compiling for Microsoft Visual C++ ... - -#define DEBUGGER /**< Invoke debugger */ -#define IMPORT /**< Mark a function which is to be imported from a DLL */ -#define EXPORT /**< Mark a function to be exported from a DLL */ - -#endif - -#ifdef DEBUG -#define ASSERT_DEBUG(c) ASSERT(c) /**< Assert that expression 'c' is true (when compiled for debugging)*/ -#else -#define ASSERT_DEBUG(c) -#endif - -#endif diff --git a/daemon/src/audio/dcblocker.cpp b/daemon/src/audio/dcblocker.cpp index 3aa1169a36fa0ffbf0fe7f48df336a8ee6408643..923dffcd21d70b9a556920be3184637e25bf1292 100644 --- a/daemon/src/audio/dcblocker.cpp +++ b/daemon/src/audio/dcblocker.cpp @@ -30,6 +30,9 @@ #include "dcblocker.h" +DcBlocker::DcBlocker() : y_(0), x_(0), xm1_(0), ym1_(0) +{} + void DcBlocker::reset() { y_ = 0; diff --git a/daemon/src/audio/dcblocker.h b/daemon/src/audio/dcblocker.h index 6dbb073ea50330eef90b3308d20a99b1e2c4f524..caedcbae430b5d3a062dc677d9e21429f09fefde 100644 --- a/daemon/src/audio/dcblocker.h +++ b/daemon/src/audio/dcblocker.h @@ -31,10 +31,11 @@ #ifndef DCBLOCKER_H #define DCBLOCKER_H -#include "global.h" +#include "sfl_types.h" class DcBlocker { public: + DcBlocker(); void reset(); void process(SFLDataFormat *out, SFLDataFormat *in, int samples); diff --git a/daemon/src/audio/delaydetection.h b/daemon/src/audio/delaydetection.h index 286baab13c628402b9ebfb615b5bd2fbb80ff99c..f83dba536e7e87463100e0b95dca9c2ef3b734c0 100644 --- a/daemon/src/audio/delaydetection.h +++ b/daemon/src/audio/delaydetection.h @@ -32,7 +32,7 @@ #ifndef DELAYDETECTION_H #define DELAYDETECTION_H -#include "global.h" +#include "sfl_types.h" #include <vector> // Template size in samples for correlation diff --git a/daemon/src/audio/echosuppress.cpp b/daemon/src/audio/echosuppress.cpp index 4f384c0bf8a747ab752d52cf6ee6ccff86f17be8..d30b03f8ae66e724a82bb6c7d3ecbdb1f2e40254 100644 --- a/daemon/src/audio/echosuppress.cpp +++ b/daemon/src/audio/echosuppress.cpp @@ -7,8 +7,9 @@ #include <cassert> #include <stdexcept> - +#include "logger.h" #include "echosuppress.h" +#include "pjmedia/echo.h" #include "pj/pool.h" #include "pj/os.h" @@ -31,7 +32,7 @@ void EchoSuppress::putData(SFLDataFormat *inputData, int samples) assert(sizeof(SFLDataFormat) == sizeof(pj_int16_t)); if (pjmedia_echo_playback(echoState_, reinterpret_cast<pj_int16_t *>(inputData)) != PJ_SUCCESS) - WARN("EchoCancel: Problem while putting input data"); + WARN("Problem while putting input data"); } void EchoSuppress::getData(SFLDataFormat *outputData) @@ -39,5 +40,5 @@ void EchoSuppress::getData(SFLDataFormat *outputData) assert(sizeof(SFLDataFormat) == sizeof(pj_int16_t)); if (pjmedia_echo_capture(echoState_, reinterpret_cast<pj_int16_t *>(outputData), 0) != PJ_SUCCESS) - WARN("EchoCancel: Problem while getting output data"); + WARN("Problem while getting output data"); } diff --git a/daemon/src/audio/echosuppress.h b/daemon/src/audio/echosuppress.h index 15b7eed93231622d00ed5d6c56ebcc014fd61e68..9b7d08fbecb83674d30c9e0a4fc81cf7190c1c89 100644 --- a/daemon/src/audio/echosuppress.h +++ b/daemon/src/audio/echosuppress.h @@ -8,10 +8,12 @@ #ifndef ECHOSUPPRESS_H_ #define ECHOSUPPRESS_H_ -#include "pjmedia/echo.h" -#include "global.h" +#include "sfl_types.h" #include "noncopyable.h" +class pjmedia_echo_state; +class pj_pool_t; + class EchoSuppress { public: EchoSuppress(pj_pool_t *pool); diff --git a/daemon/src/audio/gaincontrol.cpp b/daemon/src/audio/gaincontrol.cpp index 336d99870cd5ebb93b69b451ac7c85c380da0982..297b1fd0e0e1300f224c5e4b1be9148b07db3367 100644 --- a/daemon/src/audio/gaincontrol.cpp +++ b/daemon/src/audio/gaincontrol.cpp @@ -2,7 +2,8 @@ #include <climits> #include <fstream> -#include "global.h" +#include "sfl_types.h" +#include "logger.h" #include "gaincontrol.h" #define SFL_GAIN_ATTACK_TIME 10 @@ -22,7 +23,7 @@ GainControl::GainControl(double sr, double target) : averager_(sr, SFL_GAIN_ATTA , maxIncreaseStep_(exp(0.11513 * 12. * 160 / 8000)) // Computed on 12 frames (240 ms) , maxDecreaseStep_(exp(-0.11513 * 40. * 160 / 8000))// Computed on 40 frames (800 ms) { - DEBUG("GainControl: Target gain %f dB (%f linear)", targetLeveldB_, targetLevelLinear_); + DEBUG("Target gain %f dB (%f linear)", targetLeveldB_, targetLevelLinear_); } void GainControl::process(SFLDataFormat *buf, int samples) @@ -81,7 +82,7 @@ double GainControl::DetectionAverage::getAverage(double in) GainControl::Limiter::Limiter(double r, double thresh) : ratio_(r), threshold_(thresh) {} -double GainControl::Limiter::limit(double in) +double GainControl::Limiter::limit(double in) const { double out = (in > threshold_ ? (ratio_ * (in - threshold_)) + threshold_ : in < -threshold_ ? (ratio_ * (in + threshold_)) - threshold_ : in); diff --git a/daemon/src/audio/gaincontrol.h b/daemon/src/audio/gaincontrol.h index e8f0ecd685103c14d4232805d7f17b2cf79ebec7..eeed3745c0abab8ce40dcaf6091d38e127323657 100644 --- a/daemon/src/audio/gaincontrol.h +++ b/daemon/src/audio/gaincontrol.h @@ -80,7 +80,7 @@ class GainControl { /** * Perform compression on input signal */ - double limit(double); + double limit(double) const; private: double ratio_; diff --git a/daemon/src/audio/mainbuffer.cpp b/daemon/src/audio/mainbuffer.cpp index 997db982023a46f5386d097fc95a4675e2c42618..6925bf0f43f13888902fae3ae1075ad980ee5c92 100644 --- a/daemon/src/audio/mainbuffer.cpp +++ b/daemon/src/audio/mainbuffer.cpp @@ -30,8 +30,12 @@ */ #include "mainbuffer.h" +#include "ringbuffer.h" +#include "sfl_types.h" // for SIZEBUF #include <utility> // for std::pair -#include "manager.h" +#include "logger.h" + +const char * const MainBuffer::DEFAULT_ID = "audiolayer_id"; MainBuffer::MainBuffer() : ringBufferMap_(), callIDMap_(), mutex_(), internalSamplingRate_(8000) {} @@ -67,12 +71,12 @@ bool MainBuffer::removeCallIDSet(const std::string & set_id) CallIDSet* callid_set = getCallIDSet(set_id); if (!callid_set) { - DEBUG("removeCallIDSet error callid set %s does not exist!", set_id.c_str()); + DEBUG("CallID set %s does not exist!", set_id.c_str()); return false; } if (callIDMap_.erase(set_id) == 0) { - DEBUG("removeCallIDSet error while removing callid set %s!", set_id.c_str()); + DEBUG("CallID set %s not found!", set_id.c_str()); return false; } @@ -92,9 +96,9 @@ void MainBuffer::removeCallIDfromSet(const std::string & set_id, const std::stri CallIDSet* callid_set = getCallIDSet(set_id); if (callid_set == NULL) - ERROR("removeCallIDfromSet error callid set %s does not exist!", set_id.c_str()); + ERROR("CallIDSet %s does not exist!", set_id.c_str()); else if (callid_set->erase(call_id) == 0) - ERROR("removeCallIDfromSet error while removing callid %s from set %s!", call_id.c_str(), set_id.c_str()); + ERROR("Could not find callID %s in set %s!", call_id.c_str(), set_id.c_str()); } RingBuffer* MainBuffer::getRingBuffer(const std::string & call_id) @@ -119,11 +123,11 @@ bool MainBuffer::removeRingBuffer(const std::string & call_id) delete ring_buffer; return true; } else { - ERROR("BufferManager: Error: Fail to delete ringbuffer %s!", call_id.c_str()); + ERROR("Fail to delete ringbuffer %s!", call_id.c_str()); return false; } } else { - DEBUG("BufferManager: Error: Ringbuffer %s does not exist!", call_id.c_str()); + DEBUG("Ringbuffer %s does not exist!", call_id.c_str()); return true; } } @@ -132,19 +136,16 @@ void MainBuffer::bindCallID(const std::string & call_id1, const std::string & ca { ost::MutexLock guard(mutex_); - RingBuffer* ring_buffer; - CallIDSet* callid_set; - - if ((ring_buffer = getRingBuffer(call_id1)) == NULL) + if (getRingBuffer(call_id1) == NULL) createRingBuffer(call_id1); - if ((callid_set = getCallIDSet(call_id1)) == NULL) + if (getCallIDSet(call_id1) == NULL) createCallIDSet(call_id1); - if ((ring_buffer = getRingBuffer(call_id2)) == NULL) + if (getRingBuffer(call_id2) == NULL) createRingBuffer(call_id2); - if ((callid_set = getCallIDSet(call_id2)) == NULL) + if (getCallIDSet(call_id2) == NULL) createCallIDSet(call_id2); getRingBuffer(call_id1)->createReadPointer(call_id2); @@ -214,7 +215,7 @@ void MainBuffer::unBindHalfDuplexOut(const std::string & process_id, const std:: removeRingBuffer(call_id); } } else { - DEBUG("Error: did not found ringbuffer %s", process_id.c_str()); + DEBUG("did not found ringbuffer %s", process_id.c_str()); removeCallIDSet(process_id); } @@ -228,25 +229,19 @@ void MainBuffer::unBindAll(const std::string & call_id) { CallIDSet* callid_set = getCallIDSet(call_id); - if (callid_set == NULL) + if (callid_set == NULL or callid_set->empty()) return; - if (callid_set->empty()) - return; - - CallIDSet temp_set = *callid_set; - - CallIDSet::iterator iter_set = temp_set.begin(); + CallIDSet temp_set(*callid_set); - while (iter_set != temp_set.end()) { - std::string call_id_in_set = *iter_set; + for (CallIDSet::iterator iter_set = temp_set.begin(); + iter_set != temp_set.end(); ++iter_set) { + std::string call_id_in_set(*iter_set); unBindCallID(call_id, call_id_in_set); - - iter_set++; } } -void MainBuffer::putData(void *buffer, int toCopy, const std::string & call_id) +void MainBuffer::putData(void *buffer, int toCopy, const std::string &call_id) { ost::MutexLock guard(mutex_); @@ -256,7 +251,7 @@ void MainBuffer::putData(void *buffer, int toCopy, const std::string & call_id) ring_buffer->Put(buffer, toCopy); } -int MainBuffer::getData(void *buffer, int toCopy, const std::string & call_id) +int MainBuffer::getData(void *buffer, int toCopy, const std::string &call_id) { ost::MutexLock guard(mutex_); @@ -278,20 +273,17 @@ int MainBuffer::getData(void *buffer, int toCopy, const std::string & call_id) int size = 0; - CallIDSet::iterator iter_id = callid_set->begin(); - - while (iter_id != callid_set->end()) { + for (CallIDSet::iterator iter_id = callid_set->begin(); + iter_id != callid_set->end(); ++iter_id) { int nbSmplToCopy = toCopy / sizeof(SFLDataFormat); SFLDataFormat mixBuffer[nbSmplToCopy]; memset(mixBuffer, 0, toCopy); size = getDataByID(mixBuffer, toCopy, *iter_id, call_id); if (size > 0) { - for (int k = 0; k < nbSmplToCopy; k++) + for (int k = 0; k < nbSmplToCopy; ++k) ((SFLDataFormat*)(buffer))[k] += mixBuffer[k]; } - - iter_id++; } return size; @@ -319,7 +311,7 @@ int MainBuffer::availForGet(const std::string & call_id) if (callid_set->size() == 1) { CallIDSet::iterator iter_id = callid_set->begin(); - if ((call_id != Call::DEFAULT_ID) && (*iter_id == call_id)) + if ((call_id != DEFAULT_ID) && (*iter_id == call_id)) DEBUG("This problem should not occur since we have %i element", (int) callid_set->size()); return availForGetByID(*iter_id, call_id); @@ -332,7 +324,7 @@ int MainBuffer::availForGet(const std::string & call_id) syncBuffers(call_id); - for (iter_id = callid_set->begin(); iter_id != callid_set->end(); iter_id++) { + for (iter_id = callid_set->begin(); iter_id != callid_set->end(); ++iter_id) { nb_bytes = availForGetByID(*iter_id, call_id); if ((nb_bytes != 0) && (nb_bytes < avail_bytes)) @@ -343,22 +335,23 @@ int MainBuffer::availForGet(const std::string & call_id) } } -int MainBuffer::availForGetByID(const std::string & call_id, const std::string & reader_id) +int MainBuffer::availForGetByID(const std::string &call_id, + const std::string &reader_id) { - if ((call_id != Call::DEFAULT_ID) and (reader_id == call_id)) - ERROR("MainBuffer: Error: RingBuffer has a readpointer on tiself"); + if ((call_id != DEFAULT_ID) and (reader_id == call_id)) + ERROR("RingBuffer has a readpointer on itself"); RingBuffer* ringbuffer = getRingBuffer(call_id); if (ringbuffer == NULL) { - ERROR("MainBuffer: Error: RingBuffer does not exist"); + ERROR("RingBuffer does not exist"); return 0; } else return ringbuffer->AvailForGet(reader_id); } -int MainBuffer::discard(int toDiscard, const std::string & call_id) +int MainBuffer::discard(int toDiscard, const std::string &call_id) { ost::MutexLock guard(mutex_); @@ -367,7 +360,7 @@ int MainBuffer::discard(int toDiscard, const std::string & call_id) if (!callid_set or callid_set->empty()) return 0; - for (CallIDSet::iterator iter = callid_set->begin(); iter != callid_set->end(); iter++) + for (CallIDSet::iterator iter = callid_set->begin(); iter != callid_set->end(); ++iter) discardByID(toDiscard, *iter, call_id); return toDiscard; @@ -390,7 +383,7 @@ void MainBuffer::flush(const std::string & call_id) if (callid_set == NULL) return; - for (CallIDSet::iterator iter = callid_set->begin(); iter != callid_set->end(); iter++) + for (CallIDSet::iterator iter = callid_set->begin(); iter != callid_set->end(); ++iter) flushByID(*iter, call_id); } @@ -422,16 +415,17 @@ void MainBuffer::syncBuffers(const std::string & call_id) float mean_nbBytes = 0.0; - CallIDSet::iterator iter; - // compute mean nb byte in buffers - for (iter = callid_set->begin(); iter != callid_set->end(); iter++) + + for (CallIDSet::iterator iter = callid_set->begin(); + iter != callid_set->end(); ++iter) mean_nbBytes += availForGetByID(*iter, call_id); - mean_nbBytes /= (float) callid_set->size(); + mean_nbBytes /= static_cast<float>(callid_set->size()); // resync buffers in this conference according to the computed mean - for (iter = callid_set->begin(); iter != callid_set->end(); iter++) + for (CallIDSet::iterator iter = callid_set->begin(); + iter != callid_set->end(); ++iter) if (availForGetByID(*iter, call_id) > (mean_nbBytes + 640)) discardByID(640, *iter, call_id); } diff --git a/daemon/src/audio/mainbuffer.h b/daemon/src/audio/mainbuffer.h index b2fddc4c0a03fb73dcdd316ae156345ef7faf3be..13b374b510653eaed15ac9709135a2a4490c9666 100644 --- a/daemon/src/audio/mainbuffer.h +++ b/daemon/src/audio/mainbuffer.h @@ -29,17 +29,16 @@ * as that of the covered work. */ -#ifndef __MAIN_BUFFER__ -#define __MAIN_BUFFER__ +#ifndef MAIN_BUFFER_H_ +#define MAIN_BUFFER_H_ #include <map> #include <set> -#include <cc++/thread.h> // for ost::Mutex #include <string> -#include "global.h" -#include "call.h" -#include "ringbuffer.h" +#include "cc_thread.h" // for ost::Mutex + +class RingBuffer; typedef std::map<std::string, RingBuffer*> RingBufferMap; @@ -50,6 +49,7 @@ typedef std::map<std::string, CallIDSet*> CallIDMap; class MainBuffer { public: + static const char * const DEFAULT_ID; MainBuffer(); @@ -57,7 +57,7 @@ class MainBuffer { void setInternalSamplingRate(int sr); - int getInternalSamplingRate() { + int getInternalSamplingRate() const { return internalSamplingRate_; } @@ -65,74 +65,74 @@ class MainBuffer { * Bind together two audio streams so taht a client will be able * to put and get data specifying its callid only. */ - void bindCallID(const std::string & call_id1, const std::string & call_id2 = Call::DEFAULT_ID); + void bindCallID(const std::string &call_id1, const std::string &call_id2); /** * Add a new call_id to unidirectional outgoing stream * \param call_id New call id to be added for this stream * \param process_id Process that require this stream */ - void bindHalfDuplexOut(const std::string & process_id, const std::string & call_id = Call::DEFAULT_ID); + void bindHalfDuplexOut(const std::string &process_id, const std::string &call_id); /** * Unbind two calls */ - void unBindCallID(const std::string & call_id1, const std::string & call_id2 = Call::DEFAULT_ID); + void unBindCallID(const std::string &call_id1, const std::string &call_id2); /** * Unbind a unidirectional stream */ - void unBindHalfDuplexOut(const std::string & process_id, const std::string & call_id = Call::DEFAULT_ID); + void unBindHalfDuplexOut(const std::string &process_id, const std::string &call_id); - void unBindAll(const std::string & call_id); + void unBindAll(const std::string &call_id); - void putData(void *buffer, int toCopy, const std::string & call_id = Call::DEFAULT_ID); + void putData(void *buffer, int toCopy, const std::string &call_id); - int getData(void *buffer, int toCopy, const std::string & call_id = Call::DEFAULT_ID); + int getData(void *buffer, int toCopy, const std::string &call_id); - int availForGet(const std::string & call_id = Call::DEFAULT_ID); + int availForGet(const std::string &call_id); - int discard(int toDiscard, const std::string & call_id = Call::DEFAULT_ID); + int discard(int toDiscard, const std::string &call_id); - void flush(const std::string & call_id = Call::DEFAULT_ID); + void flush(const std::string &call_id); void flushAllBuffers(); - void syncBuffers(const std::string & call_id); + void syncBuffers(const std::string &call_id); void stateInfo(); private: - CallIDSet* getCallIDSet(const std::string & call_id); + CallIDSet* getCallIDSet(const std::string &call_id); - void createCallIDSet(const std::string & set_id); + void createCallIDSet(const std::string &set_id); - bool removeCallIDSet(const std::string & set_id); + bool removeCallIDSet(const std::string &set_id); /** * Add a new call id to this set */ - void addCallIDtoSet(const std::string & set_id, const std::string & call_id); + void addCallIDtoSet(const std::string &set_id, const std::string &call_id); - void removeCallIDfromSet(const std::string & set_id, const std::string & call_id); + void removeCallIDfromSet(const std::string &set_id, const std::string &call_id); /** * Create a new ringbuffer with default readpointer */ - RingBuffer* createRingBuffer(const std::string & call_id); + RingBuffer* createRingBuffer(const std::string &call_id); - bool removeRingBuffer(const std::string & call_id); + bool removeRingBuffer(const std::string &call_id); - RingBuffer* getRingBuffer(const std::string & call_id); + RingBuffer* getRingBuffer(const std::string &call_id); - int getDataByID(void *buffer, int toCopy, const std::string & call_id, const std::string & reader_id); + int getDataByID(void *buffer, int toCopy, const std::string &call_id, const std::string &reader_id); - int availForGetByID(const std::string & call_id, const std::string & reader_id); + int availForGetByID(const std::string &call_id, const std::string &reader_id); - void discardByID(int toDiscard, const std::string & call_id, const std::string & reader_id); + void discardByID(int toDiscard, const std::string &call_id, const std::string &reader_id); - void flushByID(const std::string & call_id, const std::string & reader_id); + void flushByID(const std::string &call_id, const std::string &reader_id); RingBufferMap ringBufferMap_; @@ -142,9 +142,7 @@ class MainBuffer { int internalSamplingRate_; - public: - friend class MainBufferTest; }; -#endif +#endif // MainBuffer diff --git a/daemon/src/audio/noisesuppress.h b/daemon/src/audio/noisesuppress.h index 0e58f20ac7ffaee5ec641305c71648d4c495e5ac..30197386db6266afa660657c9758fc49cac3eb81 100644 --- a/daemon/src/audio/noisesuppress.h +++ b/daemon/src/audio/noisesuppress.h @@ -32,7 +32,7 @@ #define NOISESUPPRESS_H #include <speex/speex_preprocess.h> -#include "global.h" // for SFLDataFormat +#include "sfl_types.h" #include "noncopyable.h" class NoiseSuppress { diff --git a/daemon/src/audio/pulseaudio/audiostream.cpp b/daemon/src/audio/pulseaudio/audiostream.cpp index 2eb1308e5098c1e1c54fe6635b38737edcaa1b21..a1943f36d47649f4b001ddf783e9168be6b736f3 100644 --- a/daemon/src/audio/pulseaudio/audiostream.cpp +++ b/daemon/src/audio/pulseaudio/audiostream.cpp @@ -28,8 +28,10 @@ * as that of the covered work. */ -#include <audiostream.h> +#include "audiostream.h" #include "pulselayer.h" +#include "logger.h" +#include <stdexcept> AudioStream::AudioStream(pa_context *c, pa_threaded_mainloop *m, const char *desc, int type, int smplrate, std::string& deviceName) : audiostream_(0), mainloop_(m) @@ -51,8 +53,8 @@ AudioStream::AudioStream(pa_context *c, pa_threaded_mainloop *m, const char *des audiostream_ = pa_stream_new(c, desc, &sample_spec, &channel_map); if (!audiostream_) { - ERROR("Pulse: %s: pa_stream_new() failed : %s" , desc, pa_strerror(pa_context_errno(c))); - throw std::runtime_error("Pulse : could not create stream\n"); + ERROR("%s: pa_stream_new() failed : %s" , desc, pa_strerror(pa_context_errno(c))); + throw std::runtime_error("Could not create stream\n"); } pa_buffer_attr attributes; @@ -94,36 +96,36 @@ AudioStream::~AudioStream() } void -AudioStream::stream_state_callback(pa_stream* s, void* user_data UNUSED) +AudioStream::stream_state_callback(pa_stream* s, void* /*user_data*/) { char str[PA_SAMPLE_SPEC_SNPRINT_MAX]; switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: - DEBUG("Pulse: Stream is creating..."); + DEBUG("Stream is creating..."); break; case PA_STREAM_TERMINATED: - DEBUG("Pulse: Stream is terminating..."); + DEBUG("Stream is terminating..."); break; case PA_STREAM_READY: - DEBUG("Pulse: Stream successfully created, connected to %s", pa_stream_get_device_name(s)); - DEBUG("Pulse: maxlength %u", pa_stream_get_buffer_attr(s)->maxlength); - DEBUG("Pulse: tlength %u", pa_stream_get_buffer_attr(s)->tlength); - DEBUG("Pulse: prebuf %u", pa_stream_get_buffer_attr(s)->prebuf); - DEBUG("Pulse: minreq %u", pa_stream_get_buffer_attr(s)->minreq); - DEBUG("Pulse: fragsize %u", pa_stream_get_buffer_attr(s)->fragsize); - DEBUG("Pulse: samplespec %s", pa_sample_spec_snprint(str, sizeof(str), pa_stream_get_sample_spec(s))); + DEBUG("Stream successfully created, connected to %s", pa_stream_get_device_name(s)); + DEBUG("maxlength %u", pa_stream_get_buffer_attr(s)->maxlength); + DEBUG("tlength %u", pa_stream_get_buffer_attr(s)->tlength); + DEBUG("prebuf %u", pa_stream_get_buffer_attr(s)->prebuf); + DEBUG("minreq %u", pa_stream_get_buffer_attr(s)->minreq); + DEBUG("fragsize %u", pa_stream_get_buffer_attr(s)->fragsize); + DEBUG("samplespec %s", pa_sample_spec_snprint(str, sizeof(str), pa_stream_get_sample_spec(s))); break; case PA_STREAM_UNCONNECTED: - DEBUG("Pulse: Stream unconnected"); + DEBUG("Stream unconnected"); break; case PA_STREAM_FAILED: default: - ERROR("Pulse: Sink/Source doesn't exists: %s" , pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + ERROR("Sink/Source doesn't exists: %s" , pa_strerror(pa_context_errno(pa_stream_get_context(s)))); break; } } diff --git a/daemon/src/audio/pulseaudio/pulselayer.cpp b/daemon/src/audio/pulseaudio/pulselayer.cpp index 42e350728f5c134ca6dce0c56dd7ca7bfc1b5e29..fcf3884ebd5fb03e6d8c9d960f2da4e7df5dbe9c 100644 --- a/daemon/src/audio/pulseaudio/pulselayer.cpp +++ b/daemon/src/audio/pulseaudio/pulselayer.cpp @@ -30,41 +30,46 @@ */ #include <algorithm> // for std::find +#include <stdexcept> #include "audiostream.h" #include "pulselayer.h" #include "audio/samplerateconverter.h" #include "audio/dcblocker.h" -#include "managerimpl.h" +#include "logger.h" +#include "manager.h" + +#include <stdlib.h> +#include <fstream> namespace { -void playback_callback(pa_stream* s, size_t bytes, void* userdata) + +void playback_callback(pa_stream * /*s*/, size_t /*bytes*/, void* userdata) { - assert(s && bytes); - assert(bytes > 0); static_cast<PulseLayer*>(userdata)->writeToSpeaker(); } -void capture_callback(pa_stream* s, size_t bytes, void* userdata) +void capture_callback(pa_stream * /*s*/, size_t /*bytes*/, void* userdata) { - assert(s && bytes); - assert(bytes > 0); static_cast<PulseLayer*>(userdata)->readFromMic(); } -void ringtone_callback(pa_stream* s, size_t bytes, void* userdata) +void ringtone_callback(pa_stream * /*s*/, size_t /*bytes*/, void* userdata) { - assert(s && bytes); - assert(bytes > 0); static_cast<PulseLayer*>(userdata)->ringtoneToSpeaker(); } void stream_moved_callback(pa_stream *s, void *userdata UNUSED) { - DEBUG("stream_moved_callback: stream %d to %d", pa_stream_get_index(s), pa_stream_get_device_index(s)); + DEBUG("stream %d to %d", pa_stream_get_index(s), pa_stream_get_device_index(s)); } } // end anonymous namespace +#ifdef RECTODISK +std::ofstream outfileResampled ("testMicOuputResampled.raw", std::ifstream::binary); +std::ofstream outfile("testMicOuput.raw", std::ifstream::binary); +#endif + PulseLayer::PulseLayer() : playback_(0) , record_(0) @@ -109,6 +114,11 @@ PulseLayer::PulseLayer() PulseLayer::~PulseLayer() { +#ifdef RECTODISK + outfile.close(); + outfileResampled.close(); +#endif + disconnectAudioStream(); if (mainloop_) @@ -122,29 +132,27 @@ PulseLayer::~PulseLayer() if (mainloop_) pa_threaded_mainloop_free(mainloop_); - delete[] mic_buffer_; + delete [] mic_buffer_; } -void PulseLayer::context_state_callback(pa_context* c, void* user_data) +void PulseLayer::context_state_callback(pa_context* c, void *user_data) { - PulseLayer* pulse = (PulseLayer*) user_data; - assert(c && pulse->mainloop_); + PulseLayer *pulse = static_cast<PulseLayer*>(user_data); + assert(c and pulse and pulse->mainloop_); + const pa_subscription_mask_t mask = (pa_subscription_mask_t) + (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE); switch (pa_context_get_state(c)) { - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - DEBUG("Audio: Waiting...."); + DEBUG("Waiting...."); break; case PA_CONTEXT_READY: - DEBUG("Audio: Connection to PulseAudio server established"); + DEBUG("Connection to PulseAudio server established"); pa_threaded_mainloop_signal(pulse->mainloop_, 0); - pa_context_subscribe(c, (pa_subscription_mask_t)(PA_SUBSCRIPTION_MASK_SINK| - PA_SUBSCRIPTION_MASK_SOURCE), NULL, pulse); + pa_context_subscribe(c, mask, NULL, pulse); pa_context_set_subscribe_callback(c, context_changed_callback, pulse); pulse->updateSinkList(); pulse->updateSourceList(); @@ -154,9 +162,8 @@ void PulseLayer::context_state_callback(pa_context* c, void* user_data) break; case PA_CONTEXT_FAILED: - default: - ERROR("Pulse: %s" , pa_strerror(pa_context_errno(c))); + ERROR("%s" , pa_strerror(pa_context_errno(c))); pa_threaded_mainloop_signal(pulse->mainloop_, 0); pulse->disconnectAudioStream(); break; @@ -167,7 +174,7 @@ void PulseLayer::context_state_callback(pa_context* c, void* user_data) void PulseLayer::updateSinkList() { sinkList_.clear(); - pa_context_get_sink_info_list(context_, sink_input_info_callback, this); + pa_context_get_sink_info_list(context_, sink_input_info_callback, this); } void PulseLayer::updateSourceList() @@ -189,12 +196,10 @@ bool PulseLayer::inSourceList(const std::string &deviceName) const std::vector<std::string> PulseLayer::getAudioDeviceList(AudioStreamDirection dir) const { - if(AUDIO_STREAM_CAPTURE == dir) { + if (AUDIO_STREAM_CAPTURE == dir) return sinkList_; - } - if(AUDIO_STREAM_PLAYBACK) { + else if (AUDIO_STREAM_PLAYBACK) return sourceList_; - } } void PulseLayer::createStreams(pa_context* c) @@ -204,22 +209,22 @@ void PulseLayer::createStreams(pa_context* c) std::string ringtoneDevice(audioPref.getDeviceRingtone()); std::string defaultDevice = ""; - DEBUG("PulseAudio: Devices:\n playback: %s\n record: %s\n ringtone: %s", + DEBUG("Devices:\n playback: %s\n record: %s\n ringtone: %s", playbackDevice.c_str(), captureDevice.c_str(), ringtoneDevice.c_str()); - playback_ = new AudioStream(c, mainloop_, "SFLphone playback", PLAYBACK_STREAM, audioSampleRate_, + playback_ = new AudioStream(c, mainloop_, "SFLphone playback", PLAYBACK_STREAM, sampleRate_, inSourceList(playbackDevice) ? playbackDevice : defaultDevice); pa_stream_set_write_callback(playback_->pulseStream(), playback_callback, this); pa_stream_set_moved_callback(playback_->pulseStream(), stream_moved_callback, this); - record_ = new AudioStream(c, mainloop_, "SFLphone capture", CAPTURE_STREAM, audioSampleRate_, + record_ = new AudioStream(c, mainloop_, "SFLphone capture", CAPTURE_STREAM, sampleRate_, inSinkList(captureDevice) ? captureDevice : defaultDevice); pa_stream_set_read_callback(record_->pulseStream() , capture_callback, this); pa_stream_set_moved_callback(record_->pulseStream(), stream_moved_callback, this); - ringtone_ = new AudioStream(c, mainloop_, "SFLphone ringtone", RINGTONE_STREAM, audioSampleRate_, + ringtone_ = new AudioStream(c, mainloop_, "SFLphone ringtone", RINGTONE_STREAM, sampleRate_, inSourceList(ringtoneDevice) ? ringtoneDevice : defaultDevice); pa_stream_set_write_callback(ringtone_->pulseStream(), ringtone_callback, this); @@ -308,30 +313,31 @@ void PulseLayer::writeToSpeaker() pa_stream *s = playback_->pulseStream(); // available bytes to be written in pulseaudio internal buffer - int writable = pa_stream_writable_size(s); - - if (writable < 0) - ERROR("Pulse: playback error : %s", pa_strerror(writable)); + int ret = pa_stream_writable_size(s); - if (writable <= 0) + if (ret < 0) { + ERROR("Playback error : %s", pa_strerror(ret)); + return; + } else if (ret == 0) return; - size_t bytes = writable; - void *data; + size_t writableBytes = ret; - notifyincomingCall(); + notifyIncomingCall(); - size_t urgentBytes = urgentRingBuffer_.AvailForGet(); + size_t urgentBytes = urgentRingBuffer_.AvailForGet(MainBuffer::DEFAULT_ID); - if (urgentBytes > bytes) - urgentBytes = bytes; + if (urgentBytes > writableBytes) + urgentBytes = writableBytes; + void *data = 0; if (urgentBytes) { pa_stream_begin_write(s, &data, &urgentBytes); - urgentRingBuffer_.Get(data, urgentBytes); + urgentRingBuffer_.Get(data, urgentBytes, MainBuffer::DEFAULT_ID); + applyGain(static_cast<SFLDataFormat *>(data), urgentBytes / sizeof(SFLDataFormat), getPlaybackGain()); pa_stream_write(s, data, urgentBytes, NULL, 0, PA_SEEK_RELATIVE); // Consume the regular one as well (same amount of bytes) - Manager::instance().getMainBuffer()->discard(urgentBytes); + Manager::instance().getMainBuffer()->discard(urgentBytes, MainBuffer::DEFAULT_ID); return; } @@ -339,9 +345,10 @@ void PulseLayer::writeToSpeaker() if (toneToPlay) { if (playback_->isReady()) { - pa_stream_begin_write(s, &data, &bytes); - toneToPlay->getNext((SFLDataFormat*)data, bytes / sizeof(SFLDataFormat), 100); - pa_stream_write(s, data, bytes, NULL, 0, PA_SEEK_RELATIVE); + pa_stream_begin_write(s, &data, &writableBytes); + toneToPlay->getNext((SFLDataFormat*)data, writableBytes / sizeof(SFLDataFormat), 100); + applyGain(static_cast<SFLDataFormat *>(data), writableBytes / sizeof(SFLDataFormat), getPlaybackGain()); + pa_stream_write(s, data, writableBytes, NULL, 0, PA_SEEK_RELATIVE); } return; @@ -349,47 +356,50 @@ void PulseLayer::writeToSpeaker() flushUrgent(); // flush remaining samples in _urgentRingBuffer - size_t availSamples = Manager::instance().getMainBuffer()->availForGet() / sizeof(SFLDataFormat); + size_t availSamples = Manager::instance().getMainBuffer()->availForGet(MainBuffer::DEFAULT_ID) / sizeof(SFLDataFormat); if (availSamples == 0) { - pa_stream_begin_write(s, &data, &bytes); - memset(data, 0, bytes); - pa_stream_write(s, data, bytes, NULL, 0, PA_SEEK_RELATIVE); + pa_stream_begin_write(s, &data, &writableBytes); + memset(data, 0, writableBytes); + pa_stream_write(s, data, writableBytes, NULL, 0, PA_SEEK_RELATIVE); return; } - unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - bool resample = audioSampleRate_ != mainBufferSampleRate; - - // how much samples we can write in the output - size_t outSamples = bytes / sizeof(SFLDataFormat); + // how many samples we can write to the output + size_t writableSamples = writableBytes / sizeof(SFLDataFormat); - // how much samples we want to read from the buffer - size_t inSamples = outSamples; + // how many samples we want to read from the buffer + size_t readableSamples = writableSamples; double resampleFactor = 1.; + unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); + bool resample = sampleRate_ != mainBufferSampleRate; if (resample) { - resampleFactor = (double) audioSampleRate_ / mainBufferSampleRate; - inSamples = (double) inSamples / resampleFactor; + resampleFactor = (double) sampleRate_ / mainBufferSampleRate; + readableSamples = (double) readableSamples / resampleFactor; } - if (inSamples > availSamples) - inSamples = availSamples; + if (readableSamples > availSamples) + readableSamples = availSamples; - size_t outBytes = (double)inSamples * resampleFactor * sizeof(SFLDataFormat); - - size_t inBytes = inSamples * sizeof(SFLDataFormat); - pa_stream_begin_write(s, &data, &inBytes); - Manager::instance().getMainBuffer()->getData(data, inBytes); + size_t readableBytes = readableSamples * sizeof(SFLDataFormat); + pa_stream_begin_write(s, &data, &readableBytes); + Manager::instance().getMainBuffer()->getData(data, readableBytes, MainBuffer::DEFAULT_ID); if (resample) { - SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc(outBytes); - converter_->resample((SFLDataFormat*)data, rsmpl_out, mainBufferSampleRate, audioSampleRate_, inSamples); - pa_stream_write(s, rsmpl_out, outBytes, NULL, 0, PA_SEEK_RELATIVE); + const size_t nResampled = (double) readableSamples * resampleFactor; + size_t resampledBytes = nResampled * sizeof(SFLDataFormat); + SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc(resampledBytes); + converter_.resample((SFLDataFormat*)data, rsmpl_out, nResampled, + mainBufferSampleRate, sampleRate_, readableSamples); + applyGain(rsmpl_out, nResampled, getPlaybackGain()); + pa_stream_write(s, rsmpl_out, resampledBytes, NULL, 0, PA_SEEK_RELATIVE); pa_xfree(rsmpl_out); - } else - pa_stream_write(s, data, inBytes, NULL, 0, PA_SEEK_RELATIVE); + } else { + applyGain(static_cast<SFLDataFormat *>(data), readableSamples, getPlaybackGain()); + pa_stream_write(s, data, readableBytes, NULL, 0, PA_SEEK_RELATIVE); + } } void PulseLayer::readFromMic() @@ -400,16 +410,14 @@ void PulseLayer::readFromMic() const char *data = NULL; size_t bytes; - if (pa_stream_peek(record_->pulseStream() , (const void**) &data , &bytes) < 0 or !data) { - ERROR("Audio: Error capture stream peek failed: %s" , pa_strerror(pa_context_errno(context_))); + if (pa_stream_peek(record_->pulseStream() , (const void**) &data , &bytes) < 0 or !data) return; - } unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - bool resample = audioSampleRate_ != mainBufferSampleRate; + bool resample = sampleRate_ != mainBufferSampleRate; if (resample) { - double resampleFactor = (double) audioSampleRate_ / mainBufferSampleRate; + double resampleFactor = (double) sampleRate_ / mainBufferSampleRate; bytes = (double) bytes * resampleFactor; } @@ -417,18 +425,26 @@ void PulseLayer::readFromMic() if (bytes > mic_buf_size_) { mic_buf_size_ = bytes; - delete[] mic_buffer_; + delete [] mic_buffer_; mic_buffer_ = new SFLDataFormat[samples]; } - if (resample) - converter_->resample((SFLDataFormat*)data, mic_buffer_, mainBufferSampleRate, audioSampleRate_, samples); +#ifdef RECTODISK + outfile.write((const char *)data, bytes); +#endif + if (resample) { + converter_.resample((SFLDataFormat*)data, mic_buffer_, samples, mainBufferSampleRate, sampleRate_, samples); + } - dcblocker_.process(mic_buffer_, resample ? mic_buffer_ : (SFLDataFormat*)data, samples); - Manager::instance().getMainBuffer()->putData(mic_buffer_, bytes); + dcblocker_.process(mic_buffer_, (SFLDataFormat*)data, samples); + applyGain(mic_buffer_, bytes / sizeof(SFLDataFormat), getCaptureGain()); + Manager::instance().getMainBuffer()->putData(mic_buffer_, bytes, MainBuffer::DEFAULT_ID); +#ifdef RECTODISK + outfileResampled.write((const char *)mic_buffer_, bytes); +#endif if (pa_stream_drop(record_->pulseStream()) < 0) - ERROR("Audio: Error: capture stream drop failed: %s" , pa_strerror(pa_context_errno(context_))); + ERROR("Capture stream drop failed: %s" , pa_strerror(pa_context_errno(context_))); } @@ -442,7 +458,7 @@ void PulseLayer::ringtoneToSpeaker() int writable = pa_stream_writable_size(s); if (writable < 0) - ERROR("Pulse: ringtone error : %s", pa_strerror(writable)); + ERROR("Ringtone error : %s", pa_strerror(writable)); if (writable <= 0) return; @@ -453,67 +469,69 @@ void PulseLayer::ringtoneToSpeaker() pa_stream_begin_write(s, &data, &bytes); AudioLoop *fileToPlay = Manager::instance().getTelephoneFile(); - if (fileToPlay) + if (fileToPlay) { fileToPlay->getNext((SFLDataFormat *) data, bytes / sizeof(SFLDataFormat), 100); + applyGain(static_cast<SFLDataFormat *>(data), bytes / sizeof(SFLDataFormat), getPlaybackGain()); + } else memset(data, 0, bytes); pa_stream_write(s, data, bytes, NULL, 0, PA_SEEK_RELATIVE); } -void PulseLayer::context_changed_callback(pa_context* c, pa_subscription_event_type_t t, uint32_t idx UNUSED, void* userdata) +void PulseLayer::context_changed_callback(pa_context* c, pa_subscription_event_type_t t, uint32_t idx UNUSED, void *userdata) { - + PulseLayer *context = static_cast<PulseLayer*>(userdata); switch (t) { case PA_SUBSCRIPTION_EVENT_SINK: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_SINK"); - ((PulseLayer *) userdata)->sinkList_.clear(); + DEBUG("PA_SUBSCRIPTION_EVENT_SINK"); + context->sinkList_.clear(); pa_context_get_sink_info_list(c, sink_input_info_callback, userdata); break; case PA_SUBSCRIPTION_EVENT_SOURCE: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_SOURCE"); - ((PulseLayer *) userdata)->sourceList_.clear(); - pa_context_get_source_info_list(c, source_input_info_callback, userdata); + DEBUG("PA_SUBSCRIPTION_EVENT_SOURCE"); + context->sourceList_.clear(); + pa_context_get_source_info_list(c, source_input_info_callback, userdata); break; case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_SINK_INPUT"); + DEBUG("PA_SUBSCRIPTION_EVENT_SINK_INPUT"); break; case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT"); + DEBUG("PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT"); break; case PA_SUBSCRIPTION_EVENT_MODULE: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_MODULE"); + DEBUG("PA_SUBSCRIPTION_EVENT_MODULE"); break; case PA_SUBSCRIPTION_EVENT_CLIENT: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_CLIENT"); + DEBUG("PA_SUBSCRIPTION_EVENT_CLIENT"); break; case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE"); + DEBUG("PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE"); break; case PA_SUBSCRIPTION_EVENT_SERVER: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_SERVER"); + DEBUG("PA_SUBSCRIPTION_EVENT_SERVER"); break; case PA_SUBSCRIPTION_EVENT_CARD: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_CARD"); + DEBUG("PA_SUBSCRIPTION_EVENT_CARD"); break; case PA_SUBSCRIPTION_EVENT_FACILITY_MASK: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_FACILITY_MASK"); + DEBUG("PA_SUBSCRIPTION_EVENT_FACILITY_MASK"); break; case PA_SUBSCRIPTION_EVENT_CHANGE: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_CHANGE"); + DEBUG("PA_SUBSCRIPTION_EVENT_CHANGE"); break; case PA_SUBSCRIPTION_EVENT_REMOVE: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_REMOVE"); - ((PulseLayer *) userdata)->sinkList_.clear(); - ((PulseLayer *) userdata)->sourceList_.clear(); - pa_context_get_sink_info_list(c, sink_input_info_callback, userdata); - pa_context_get_source_info_list(c, source_input_info_callback, userdata); + DEBUG("PA_SUBSCRIPTION_EVENT_REMOVE"); + context->sinkList_.clear(); + context->sourceList_.clear(); + pa_context_get_sink_info_list(c, sink_input_info_callback, userdata); + pa_context_get_source_info_list(c, source_input_info_callback, userdata); break; case PA_SUBSCRIPTION_EVENT_TYPE_MASK: - DEBUG("Audio: PA_SUBSCRIPTION_EVENT_TYPE_MASK"); + DEBUG("PA_SUBSCRIPTION_EVENT_TYPE_MASK"); break; default: - DEBUG("Audio: Unknown event type %d", t); + DEBUG("Unknown event type %d", t); } } @@ -550,7 +568,7 @@ void PulseLayer::source_input_info_callback(pa_context *c UNUSED, const pa_sourc i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", i->flags & PA_SOURCE_HARDWARE ? "HARDWARE" : ""); - ((PulseLayer *)userdata)->sourceList_.push_back(i->name); + static_cast<PulseLayer *>(userdata)->sourceList_.push_back(i->name); } void PulseLayer::sink_input_info_callback(pa_context *c UNUSED, const pa_sink_info *i, int eol, void *userdata) @@ -561,30 +579,30 @@ void PulseLayer::sink_input_info_callback(pa_context *c UNUSED, const pa_sink_in return; DEBUG("Sink %u\n" - " Name: %s\n" - " Driver: %s\n" - " Description: %s\n" - " Sample Specification: %s\n" - " Channel Map: %s\n" - " Owner Module: %u\n" - " Volume: %s\n" - " Monitor Source: %u\n" - " Latency: %0.0f usec\n" - " Flags: %s%s%s\n", - i->index, - i->name, - i->driver, - i->description, - pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), - pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), - i->owner_module, - i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), - i->monitor_source, - (double) i->latency, - i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", - i->flags & PA_SINK_LATENCY ? "LATENCY " : "", - i->flags & PA_SINK_HARDWARE ? "HARDWARE" : ""); - - ((PulseLayer *)userdata)->sinkList_.push_back(i->name); + " Name: %s\n" + " Driver: %s\n" + " Description: %s\n" + " Sample Specification: %s\n" + " Channel Map: %s\n" + " Owner Module: %u\n" + " Volume: %s\n" + " Monitor Source: %u\n" + " Latency: %0.0f usec\n" + " Flags: %s%s%s\n", + i->index, + i->name, + i->driver, + i->description, + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), + i->owner_module, + i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + i->monitor_source, + static_cast<double>(i->latency), + i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", + i->flags & PA_SINK_LATENCY ? "LATENCY " : "", + i->flags & PA_SINK_HARDWARE ? "HARDWARE" : ""); + + static_cast<PulseLayer *>(userdata)->sinkList_.push_back(i->name); } diff --git a/daemon/src/audio/pulseaudio/pulselayer.h b/daemon/src/audio/pulseaudio/pulselayer.h index a8640f42cf35856552f3b174738314c5dac4eca1..f94cbdced5f76277ece0975be28ad3aae3b97729 100644 --- a/daemon/src/audio/pulseaudio/pulselayer.h +++ b/daemon/src/audio/pulseaudio/pulselayer.h @@ -68,6 +68,7 @@ class PulseLayer : public AudioLayer { virtual void stopStream(); + private: static void context_state_callback(pa_context* c, void* user_data); static void context_changed_callback(pa_context* c, diff --git a/daemon/src/audio/recordable.cpp b/daemon/src/audio/recordable.cpp index 71f5d00d6b0991220b060b1c069a54ef7c5584bb..6915c1e6c06eedf0a29f83be320d317045948ddf 100644 --- a/daemon/src/audio/recordable.cpp +++ b/daemon/src/audio/recordable.cpp @@ -29,9 +29,11 @@ #include "recordable.h" #include "manager.h" +#include "logger.h" Recordable::Recordable() : recAudio_(), recorder_(&recAudio_, Manager::instance().getMainBuffer()) { + DEBUG("Set recording options: %s", Manager::instance().audioPreference.getRecordpath().c_str()); recAudio_.setRecordingOption(AudioRecord::FILE_WAV, 8000, Manager::instance().audioPreference.getRecordpath()); } @@ -55,8 +57,3 @@ void Recordable::setRecordingSmplRate(int smplRate) { recAudio_.setSndSamplingRate(smplRate); } - -int Recordable::getRecordingSmplRate() const -{ - return recAudio_.getSndSamplingRate(); -} diff --git a/daemon/src/audio/recordable.h b/daemon/src/audio/recordable.h index 7df25c5365aa23a8c184e26fe8757d123c718814..07aeb229191d03de7d3bf73cbaab77f773a0c01f 100644 --- a/daemon/src/audio/recordable.h +++ b/daemon/src/audio/recordable.h @@ -75,17 +75,6 @@ class Recordable { */ void setRecordingSmplRate(int smplRate); - /** - * Return the recording sampling rate - */ - int getRecordingSmplRate() const; - - /** - * Virtual method to be implemented in order to the main - * buffer to retrieve the recorded id. - */ - virtual std::string getRecFileId() const = 0; - protected: AudioRecord recAudio_; AudioRecorder recorder_; diff --git a/daemon/src/audio/ringbuffer.cpp b/daemon/src/audio/ringbuffer.cpp index 9119838ffea0acfdebc05288b9204bfb8963c269..51491fcf6e1844c7b341765d91e376de0d55bb40 100644 --- a/daemon/src/audio/ringbuffer.cpp +++ b/daemon/src/audio/ringbuffer.cpp @@ -36,11 +36,11 @@ #include <cstring> #include <utility> // for std::pair +#include "logger.h" #include "ringbuffer.h" -#include "global.h" // corespond to 106 ms (about 5 rtp packets) -#define MIN_BUFFER_SIZE 1280 +#define MIN_BUFFER_SIZE 1280 int RingBuffer::count_rb = 0; @@ -132,7 +132,7 @@ RingBuffer::storeReadPointer(int pointer_value, const std::string &call_id) if (iter != readpointer_.end()) iter->second = pointer_value; else - DEBUG("storeReadPointer: Cannot find \"%s\" readPointer in \"%s\" ringbuffer", call_id.c_str(), buffer_id_.c_str()); + DEBUG("Cannot find \"%s\" readPointer in \"%s\" ringbuffer", call_id.c_str(), buffer_id_.c_str()); } diff --git a/daemon/src/audio/ringbuffer.h b/daemon/src/audio/ringbuffer.h index f22b1f7f10965248f59ffdadb4bc51576840bc0c..6fde62b4d1d807fd57435d49a92dfd2f8c258550 100644 --- a/daemon/src/audio/ringbuffer.h +++ b/daemon/src/audio/ringbuffer.h @@ -23,7 +23,7 @@ #define __RING_BUFFER__ #include <fstream> -#include "../call.h" +#include <map> #include "noncopyable.h" typedef std::map<std::string, int> ReadPointer; @@ -34,28 +34,28 @@ class RingBuffer { * Constructor * @param size Size of the buffer to create */ - RingBuffer(int size, const std::string &call_id = Call::DEFAULT_ID); + RingBuffer(int size, const std::string &call_id); /** * Destructor */ ~RingBuffer(); - std::string getBufferId() { + std::string getBufferId() const { return buffer_id_; } /** * Reset the counters to 0 for this read pointer */ - void flush(const std::string &call_id = Call::DEFAULT_ID); + void flush(const std::string &call_id); void flushAll(); /** * Get read pointer coresponding to this call */ - int getReadPointer(const std::string &call_id = Call::DEFAULT_ID); + int getReadPointer(const std::string &call_id); /** * Get the whole readpointer list for this ringbuffer @@ -72,17 +72,17 @@ class RingBuffer { /** * Move readpointer forward by pointer_value */ - void storeReadPointer(int pointer_value, const std::string &call_id = Call::DEFAULT_ID); + void storeReadPointer(int pointer_value, const std::string &call_id); /** * Add a new readpointer for this ringbuffer */ - void createReadPointer(const std::string &call_id = Call::DEFAULT_ID); + void createReadPointer(const std::string &call_id); /** * Remove a readpointer for this ringbuffer */ - void removeReadPointer(const std::string &call_id = Call::DEFAULT_ID); + void removeReadPointer(const std::string &call_id); /** * Test if readpointer coresponding to this call is still active @@ -102,7 +102,7 @@ class RingBuffer { * To get how much space is available in the buffer to read in * @return int The available size */ - int AvailForGet(const std::string &call_id = Call::DEFAULT_ID); + int AvailForGet(const std::string &call_id); /** * Get data in the ring buffer @@ -110,14 +110,14 @@ class RingBuffer { * @param toCopy Number of bytes to copy * @return int Number of bytes copied */ - int Get(void* buffer, int toCopy, const std::string &call_id = Call::DEFAULT_ID); + int Get(void* buffer, int toCopy, const std::string &call_id); /** * Discard data from the buffer * @param toDiscard Number of bytes to discard * @return int Number of bytes discarded */ - int Discard(int toDiscard, const std::string &call_id = Call::DEFAULT_ID); + int Discard(int toDiscard, const std::string &call_id); /** * Total length of the ring buffer @@ -125,7 +125,7 @@ class RingBuffer { */ int putLen(); - int getLen(const std::string &call_id = Call::DEFAULT_ID); + int getLen(const std::string &call_id); /** * Debug function print mEnd, mStart, mBufferSize @@ -142,13 +142,13 @@ class RingBuffer { /** Data */ unsigned char *buffer_; - ReadPointer readpointer_; + ReadPointer readpointer_; std::string buffer_id_; - public: - friend class MainBufferTest; + public: + std::fstream *buffer_input_rec; std::fstream *buffer_output_rec; diff --git a/daemon/src/audio/samplerateconverter.cpp b/daemon/src/audio/samplerateconverter.cpp index be38d25f957145ee9b24049ea045f97eee73174f..e64a86e9f6b0f074396b272aa468003e40809134 100644 --- a/daemon/src/audio/samplerateconverter.cpp +++ b/daemon/src/audio/samplerateconverter.cpp @@ -31,6 +31,7 @@ #include "samplerateconverter.h" #include "manager.h" #include <cassert> +#include "logger.h" SamplerateConverter::SamplerateConverter(int freq) : floatBufferIn_(0), floatBufferOut_(0), samples_(0), maxFreq_(freq), src_state_(0) @@ -63,15 +64,16 @@ SamplerateConverter::Short2FloatArray(const short *in, float *out, int len) } void SamplerateConverter::resample(SFLDataFormat *dataIn, - SFLDataFormat *dataOut, int inputFreq, - int outputFreq, int nbSamples) + SFLDataFormat *dataOut, + size_t dataOutSize, int inputFreq, + int outputFreq, size_t nbSamples) { double sampleFactor = (double) outputFreq / inputFreq; if (sampleFactor == 1.0) return; - const int outSamples = nbSamples * sampleFactor; + size_t outSamples = nbSamples * sampleFactor; const unsigned int maxSamples = std::max(outSamples, nbSamples); if (maxSamples > samples_) { @@ -91,8 +93,12 @@ void SamplerateConverter::resample(SFLDataFormat *dataIn, src_data.src_ratio = sampleFactor; src_data.end_of_input = 0; // More data will come - Short2FloatArray(dataIn , floatBufferIn_, nbSamples); + Short2FloatArray(dataIn, floatBufferIn_, nbSamples); src_process(src_state_, &src_data); - src_float_to_short_array(floatBufferOut_, dataOut , outSamples); + if (outSamples > dataOutSize) { + ERROR("Outsamples exceeds output buffer size, clamping to %u", dataOutSize); + outSamples = dataOutSize; + } + src_float_to_short_array(floatBufferOut_, dataOut, outSamples); } diff --git a/daemon/src/audio/samplerateconverter.h b/daemon/src/audio/samplerateconverter.h index f367161eba2e0d3e6afb7a2ef52123ff522a1fd1..3dbbab464f8602dcf248e86fcd48a8e4786f8b67 100644 --- a/daemon/src/audio/samplerateconverter.h +++ b/daemon/src/audio/samplerateconverter.h @@ -33,8 +33,9 @@ #include <samplerate.h> #include <cmath> +#include <cstring> -#include "global.h" +#include "sfl_types.h" #include "noncopyable.h" class SamplerateConverter { @@ -58,7 +59,7 @@ class SamplerateConverter { * @param SamplerateConverter2 The desired sample rate * @param nbSamples The number of samples to process */ - void resample(SFLDataFormat* dataIn , SFLDataFormat* dataOut , int oldrate, int newrate, int nbSamples); + void resample(SFLDataFormat* dataIn, SFLDataFormat* dataOut, size_t dataOutSize, int oldrate, int newrate, size_t nbSamples); /** * Convert short table to floats for audio processing diff --git a/daemon/src/audio/sound/audiofile.cpp b/daemon/src/audio/sound/audiofile.cpp index bafc2012b5d4e1196f04551bbb9f09e70cb66495..6678c7475196e91dd58d0473fdc213059ea874f0 100644 --- a/daemon/src/audio/sound/audiofile.cpp +++ b/daemon/src/audio/sound/audiofile.cpp @@ -31,27 +31,23 @@ * as that of the covered work. */ #include <fstream> -#include <math.h> +#include <cmath> #include <samplerate.h> #include <cstring> -#include <limits.h> +#include <vector> +#include <climits> #include "audiofile.h" -#include "audio/codecs/audiocodecfactory.h" #include "audio/codecs/audiocodec.h" #include "audio/samplerateconverter.h" +#include "logger.h" -#include "manager.h" - -RawFile::RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int sampleRate) - : audioCodec_(codec) +RawFile::RawFile(const std::string& name, sfl::AudioCodec *codec, unsigned int sampleRate) + : AudioFile(name), audioCodec_(codec) { - filepath_ = name; - if (filepath_.empty()) throw AudioFileException("Unable to open audio file: filename is empty"); - std::fstream file; file.open(filepath_.c_str(), std::fstream::in); @@ -62,8 +58,8 @@ RawFile::RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int s size_t length = file.tellg(); file.seekg(0, std::ios::beg); - char *fileBuffer = new char[length]; - file.read(fileBuffer,length); + std::vector<char> fileBuffer(length); + file.read(&fileBuffer[0], length); file.close(); const unsigned int frameSize = audioCodec_->getFrameSize(); @@ -74,7 +70,7 @@ RawFile::RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int s SFLDataFormat *monoBuffer = new SFLDataFormat[decodedSize]; SFLDataFormat *bufpos = monoBuffer; - unsigned char *filepos = reinterpret_cast<unsigned char *>(fileBuffer); + unsigned char *filepos = reinterpret_cast<unsigned char *>(&fileBuffer[0]); size_ = decodedSize; while (length >= encFrameSize) { @@ -83,8 +79,6 @@ RawFile::RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int s length -= encFrameSize; } - delete [] fileBuffer; - if (sampleRate == audioRate) buffer_ = monoBuffer; else { @@ -115,28 +109,27 @@ RawFile::RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int s } -WaveFile::WaveFile(const std::string& fileName, int newRate) +WaveFile::WaveFile(const std::string &fileName, int newRate) : AudioFile(fileName) { const std::fstream fs(fileName.c_str(), std::ios_base::in); if (!fs) throw AudioFileException("File " + fileName + " doesn't exist"); - filepath_ = fileName; std::fstream fileStream; fileStream.open(fileName.c_str(), std::ios::in | std::ios::binary); char riff[4] = { 0, 0, 0, 0 }; - fileStream.read(riff, sizeof riff / sizeof riff[0]); + fileStream.read(riff, sizeof riff / sizeof *riff); - if (strncmp("RIFF", riff, sizeof riff / sizeof riff[0]) != 0) + if (strncmp("RIFF", riff, sizeof riff / sizeof *riff) != 0) throw AudioFileException("File is not of RIFF format"); char fmt[4] = { 0, 0, 0, 0 }; int maxIteration = 10; - while (maxIteration-- and strncmp("fmt ", fmt, sizeof fmt / sizeof fmt[0])) - fileStream.read(fmt, sizeof fmt / sizeof fmt[0]); + while (maxIteration-- and strncmp("fmt ", fmt, sizeof fmt / sizeof *fmt)) + fileStream.read(fmt, sizeof fmt / sizeof *fmt); if (maxIteration == 0) throw AudioFileException("Could not find \"fmt \" chunk"); @@ -177,8 +170,8 @@ WaveFile::WaveFile(const std::string& fileName, int newRate) char data[4] = { 0, 0, 0, 0 }; maxIteration = 10; - while (maxIteration-- && strncmp("data", data, sizeof data / sizeof data[0])) - fileStream.read(data, sizeof data / sizeof data[0]); + while (maxIteration-- && strncmp("data", data, sizeof data / sizeof *data)) + fileStream.read(data, sizeof data / sizeof *data); // Samplerate converter initialized with 88200 sample long SamplerateConverter converter(std::max(fileRate, newRate)); @@ -190,7 +183,7 @@ WaveFile::WaveFile(const std::string& fileName, int newRate) // sample frames, should not be longer than a minute int nbSamples = std::min(60 * fileRate, 8 * bytes / dt / chan); - DEBUG("WaveFile: frame size %ld, data size %d align %d rate %d avgbyte %d " + DEBUG("Frame size %ld, data size %d align %d rate %d avgbyte %d " "chunk size %d dt %d", nbSamples, bytes, blockal, fileRate, avgb, chunkSize, dt); @@ -212,7 +205,7 @@ WaveFile::WaveFile(const std::string& fileName, int newRate) const int outSamples = ceil(nbSamples * ratio); size_ = outSamples; buffer_ = new SFLDataFormat[size_]; - converter.resample(tempBuffer, buffer_, fileRate, newRate, nbSamples); + converter.resample(tempBuffer, buffer_, size_, fileRate, newRate, nbSamples); delete [] tempBuffer; } else buffer_ = tempBuffer; diff --git a/daemon/src/audio/sound/audiofile.h b/daemon/src/audio/sound/audiofile.h index 0963e40dd26b5cb401a2301287897f2639f87656..a914f1cbc4f633b35406aae2827752eb125b8da0 100644 --- a/daemon/src/audio/sound/audiofile.h +++ b/daemon/src/audio/sound/audiofile.h @@ -43,7 +43,7 @@ class AudioCodec; class AudioFileException : public std::runtime_error { public: - AudioFileException(const std::string& str = "") : + AudioFileException(const std::string &str) : std::runtime_error("AudioFile: AudioFileException occured: " + str) {} }; @@ -52,7 +52,7 @@ class AudioFileException : public std::runtime_error { */ class AudioFile : public AudioLoop { public: - AudioFile() : filepath_() {} + AudioFile(const std::string &filepath) : filepath_(filepath) {} std::string getFilePath() const { return filepath_; } diff --git a/daemon/src/audio/sound/tone.cpp b/daemon/src/audio/sound/tone.cpp index 5f0086373155048ccc3a1d9825eaee781592cd1e..8a3eee76bf0eee2245c7ba899d721209abc15146 100644 --- a/daemon/src/audio/sound/tone.cpp +++ b/daemon/src/audio/sound/tone.cpp @@ -35,10 +35,13 @@ * YM: 2006-11-15: changes unsigned int to std::string::size_type, thanks to Pierre Pomes (AMD64 compilation) */ #include "tone.h" +#include "logger.h" +#include "sfl_types.h" #include <cmath> #include <cassert> #include <cstdlib> #include <cstring> +#include <vector> Tone::Tone(const std::string& definition, unsigned int sampleRate) : sampleRate_(sampleRate), xhigher_(0.0), xlower_(0.0) @@ -55,8 +58,8 @@ Tone::genBuffer(const std::string& definition) size_ = 0; - SFLDataFormat* buffer = new SFLDataFormat[SIZEBUF]; //1kb - SFLDataFormat* bufferPos = buffer; + std::vector<SFLDataFormat> buffer(SIZEBUF); // 1kb + SFLDataFormat* bufferPos = &(*buffer.begin()); // Number of format sections std::string::size_type posStart = 0; // position of precedent comma @@ -123,9 +126,7 @@ Tone::genBuffer(const std::string& definition) assert(!buffer_); buffer_ = new SFLDataFormat[size_]; - memcpy(buffer_, buffer, size_ * sizeof(SFLDataFormat)); // copy char, not SFLDataFormat. - - delete [] buffer; + memcpy(buffer_, &(*buffer.begin()), size_ * sizeof(SFLDataFormat)); // copy char, not SFLDataFormat. } void @@ -139,7 +140,7 @@ Tone::fillWavetable() } double -Tone::interpolate(double x) +Tone::interpolate(double x) const { int xi_0 = x; int xi_1 = xi_0 + 1; diff --git a/daemon/src/audio/sound/tone.h b/daemon/src/audio/sound/tone.h index bf6eeee85302759d711150a94007853eacefe3b9..55422bd0f508a76d26f209a639f5a785abf54614 100644 --- a/daemon/src/audio/sound/tone.h +++ b/daemon/src/audio/sound/tone.h @@ -73,8 +73,7 @@ class Tone : public AudioLoop { */ void fillWavetable(); - double interpolate(double x); - + double interpolate(double x) const; private: diff --git a/daemon/src/audio/speexechocancel.cpp b/daemon/src/audio/speexechocancel.cpp index c5daacddafa48bead5b0b74c6b9af7e380eef5f3..4fc2531843977099c880ff14161df0253d6c3836 100644 --- a/daemon/src/audio/speexechocancel.cpp +++ b/daemon/src/audio/speexechocancel.cpp @@ -21,6 +21,7 @@ #include <climits> #include "speexechocancel.h" +#include "logger.h" #include <speex/speex_echo.h> #include <speex/speex_preprocess.h> #include "manager.h" @@ -40,38 +41,40 @@ SpeexEchoCancel::SpeexEchoCancel() : echoTailLength_(Manager::instance().getEchoCancelTailLength() * SPEEX_SAMPLE_RATE / 1000), echoState_(speex_echo_state_init(EC_FRAME_SIZE, echoTailLength_)), preState_(speex_preprocess_state_init(EC_FRAME_SIZE, SPEEX_SAMPLE_RATE)), - micData_(new RingBuffer(RINGBUFFER_SIZE)), - spkrData_(new RingBuffer(RINGBUFFER_SIZE)), - spkrStopped_(true) + micData_(RINGBUFFER_SIZE, MainBuffer::DEFAULT_ID), + spkrData_(RINGBUFFER_SIZE, MainBuffer::DEFAULT_ID), + spkrStopped_(true), + tmpSpkr_(), + tmpMic_(), + tmpOut_() { - DEBUG("EchoCancel: Initializing echo canceller with delay: %d, filter length: %d, frame size: %d and samplerate %d", - echoDelay_, echoTailLength_, EC_FRAME_SIZE, SPEEX_SAMPLE_RATE); + DEBUG("Initializing echo canceller with delay: %d, filter " + "length: %d, frame size: %d and samplerate %d", echoDelay_, + echoTailLength_, EC_FRAME_SIZE, SPEEX_SAMPLE_RATE); int rate = SPEEX_SAMPLE_RATE; speex_echo_ctl(echoState_, SPEEX_ECHO_SET_SAMPLING_RATE, &rate); speex_preprocess_ctl(preState_, SPEEX_PREPROCESS_SET_ECHO_STATE, echoState_); - micData_->createReadPointer(); - spkrData_->createReadPointer(); + micData_.createReadPointer(MainBuffer::DEFAULT_ID); + spkrData_.createReadPointer(MainBuffer::DEFAULT_ID); } SpeexEchoCancel::~SpeexEchoCancel() { speex_echo_state_destroy(echoState_); speex_preprocess_state_destroy(preState_); - delete spkrData_; - delete micData_; } void SpeexEchoCancel::putData(SFLDataFormat *inputData, int samples) { if (spkrStopped_) { - micData_->flushAll(); - spkrData_->flushAll(); + micData_.flushAll(); + spkrData_.flushAll(); spkrStopped_ = false; } - spkrData_->Put(inputData, samples * sizeof(SFLDataFormat)); + spkrData_.Put(inputData, samples * sizeof(SFLDataFormat)); } int SpeexEchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int samples) @@ -87,19 +90,19 @@ int SpeexEchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData memset(tmpOut_, 0, sizeof(tmpOut_)); // Put mic data in ringbuffer - micData_->Put(inputData, samples * sizeof(SFLDataFormat)); + micData_.Put(inputData, samples * sizeof(SFLDataFormat)); // Store data for synchronization - int spkrAvail = spkrData_->AvailForGet(); - int micAvail = micData_->AvailForGet(); + int spkrAvail = spkrData_.AvailForGet(MainBuffer::DEFAULT_ID); + int micAvail = micData_.AvailForGet(MainBuffer::DEFAULT_ID); - if (spkrAvail < (echoDelay_+byteSize) || micAvail < byteSize) { - micData_->Discard(byteSize); + if ((spkrAvail < (echoDelay_ + byteSize)) or micAvail < byteSize) { + micData_.Discard(byteSize, MainBuffer::DEFAULT_ID); return 0; } - spkrData_->Get(tmpSpkr_, byteSize); - micData_->Get(tmpMic_, byteSize); + spkrData_.Get(tmpSpkr_, byteSize, MainBuffer::DEFAULT_ID); + micData_.Get(tmpMic_, byteSize, MainBuffer::DEFAULT_ID); for (int i = 0; i < EC_FRAME_SIZE; i++) { int32_t tmp = tmpSpkr_[i] * 3; @@ -120,8 +123,8 @@ int SpeexEchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData memcpy(outputData, tmpOut_, byteSize); - spkrAvail = spkrData_->AvailForGet(); - micAvail = micData_->AvailForGet(); + spkrAvail = spkrData_.AvailForGet(MainBuffer::DEFAULT_ID); + micAvail = micData_.AvailForGet(MainBuffer::DEFAULT_ID); return EC_FRAME_SIZE; } diff --git a/daemon/src/audio/speexechocancel.h b/daemon/src/audio/speexechocancel.h index 48d945384f90322897968ee7e89f166f4a09da15..51b1cc583c5a31a93ff7080758f8d07e3c09337a 100644 --- a/daemon/src/audio/speexechocancel.h +++ b/daemon/src/audio/speexechocancel.h @@ -20,10 +20,10 @@ #ifndef SPEEXECHOCANCEL_H #define SPEEXECHOCANCEL_H -#include "global.h" +#include "sfl_types.h" #include "noncopyable.h" +#include "ringbuffer.h" -class RingBuffer; class SpeexEchoState_; typedef SpeexEchoState_ SpeexEchoState; class SpeexPreprocessState_; @@ -57,8 +57,8 @@ class SpeexEchoCancel { SpeexEchoState *echoState_; SpeexPreprocessState *preState_; - RingBuffer *micData_; - RingBuffer *spkrData_; + RingBuffer micData_; + RingBuffer spkrData_; bool spkrStopped_; diff --git a/daemon/src/call.cpp b/daemon/src/call.cpp index f2f4a6172e947df829694d973d5987b7b7c38efc..20b95afa6aa40d7aa5a1f6cac99a43b1e2ee527d 100644 --- a/daemon/src/call.cpp +++ b/daemon/src/call.cpp @@ -33,8 +33,6 @@ #include "audio/mainbuffer.h" #include "history/historyitem.h" -const char * const Call::DEFAULT_ID = "audiolayer_id"; - Call::Call(const std::string& id, Call::CallType type) : callMutex_() , localIPAddress_("") @@ -147,12 +145,12 @@ Call::setRecording() if (!recordStatus) { mbuffer->bindHalfDuplexOut(process_id, id_); - mbuffer->bindHalfDuplexOut(process_id); + mbuffer->bindHalfDuplexOut(process_id, MainBuffer::DEFAULT_ID); Recordable::recorder_.start(); } else { mbuffer->unBindHalfDuplexOut(process_id, id_); - mbuffer->unBindHalfDuplexOut(process_id); + mbuffer->unBindHalfDuplexOut(process_id, MainBuffer::DEFAULT_ID); } Manager::instance().getMainBuffer()->stateInfo(); diff --git a/daemon/src/call.h b/daemon/src/call.h index 784acd9e7d2935ea8234c1cf96175ef0b57bed53..2c6b688a4d81d6998902e0d74656862ef0b9be2d 100644 --- a/daemon/src/call.h +++ b/daemon/src/call.h @@ -32,9 +32,9 @@ #ifndef CALL_H #define CALL_H -#include <cc++/thread.h> // for mutex #include <sstream> - +#include <map> +#include "cc_thread.h" #include "audio/recordable.h" /* @@ -174,6 +174,8 @@ class Call : public Recordable { isIPToIP_ = IPToIP; } + virtual void answer() = 0; + /** * Set my IP [not protected] * @param ip The local IP address @@ -202,10 +204,6 @@ class Call : public Recordable { */ unsigned int getLocalAudioPort(); - std::string getRecFileId() const { - return getDisplayName(); - } - void time_stop(); std::map<std::string, std::string> createHistoryEntry() const; virtual bool setRecording(); diff --git a/daemon/src/cc_config.h b/daemon/src/cc_config.h new file mode 100644 index 0000000000000000000000000000000000000000..5f391d0b809c104b0423c7d1dbacd2429670ab0e --- /dev/null +++ b/daemon/src/cc_config.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef CC_CONFIG_H_ +#define CC_CONFIG_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CCPP_PREFIX +#include <cc++/config.h> +#elif defined COMMONCPP_PREFIX +#include <commoncpp/config.h> +#else +#error No CCGNU2 include directory found. +#endif + +#endif // CC_CONFIG_H_ diff --git a/daemon/src/cc_thread.h b/daemon/src/cc_thread.h new file mode 100644 index 0000000000000000000000000000000000000000..fbbaf277e5c08b203ddfdc15374097b37e420a9b --- /dev/null +++ b/daemon/src/cc_thread.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef CC_THREAD_H_ +#define CC_THREAD_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CCPP_PREFIX +#include <cc++/thread.h> // for mutex +#elif defined COMMONCPP_PREFIX +#include <commoncpp/thread.h> // for mutex +#else +#error No CCGNU2 include directory found. +#endif + +#endif // CC_THREAD_H_ diff --git a/daemon/src/codec.h b/daemon/src/codec.h index 95817cd371dbc8b225add5ebf73c66189f6378ed..713ac9a1d9ba5a29636f456e78a5859918276408 100644 --- a/daemon/src/codec.h +++ b/daemon/src/codec.h @@ -27,10 +27,10 @@ * as that of the covered work. */ -#ifndef __SFL_CODEC_H__ -#define __SFL_CODEC_H__ +#ifndef CODEC_H_ +#define CODEC_H_ -#include <cc++/config.h> // for types +#include "cc_config.h" // for types /** * Interface for both audio codecs as well as video codecs. @@ -39,11 +39,6 @@ namespace sfl { class Codec { public: virtual ~Codec() {} - /** - * @return The mimesubtype for this codec. Eg. : "video" - */ - virtual std::string getMimeType() const = 0; - /** * @return The mimesubtype for this codec. Eg. : "theora" */ @@ -70,4 +65,4 @@ typedef sfl::Codec* create_t(); typedef void destroy_t (sfl::Codec*); -#endif +#endif // CODEC_H_ diff --git a/daemon/src/conference.cpp b/daemon/src/conference.cpp index d40da64e58d3e9642801456af5c7409aff7b3137..f2850f99bba4fb0cb3e0e878d54cac595f180961 100644 --- a/daemon/src/conference.cpp +++ b/daemon/src/conference.cpp @@ -71,7 +71,7 @@ void Conference::bindParticipant(const std::string &participant_id) if (participant_id != *iter) Manager::instance().getMainBuffer()->bindCallID(participant_id, *iter); - Manager::instance().getMainBuffer()->bindCallID(participant_id); + Manager::instance().getMainBuffer()->bindCallID(participant_id, MainBuffer::DEFAULT_ID); } std::string Conference::getStateStr() const @@ -113,23 +113,19 @@ bool Conference::setRecording() for (ParticipantSet::const_iterator iter = participants_.begin(); iter != participants_.end(); ++iter) mbuffer->bindHalfDuplexOut(process_id, *iter); - mbuffer->bindHalfDuplexOut(process_id); + mbuffer->bindHalfDuplexOut(process_id, MainBuffer::DEFAULT_ID); Recordable::recorder_.start(); } else { for (ParticipantSet::const_iterator iter = participants_.begin(); iter != participants_.end(); ++iter) mbuffer->unBindHalfDuplexOut(process_id, *iter); - mbuffer->unBindHalfDuplexOut(process_id); + mbuffer->unBindHalfDuplexOut(process_id, MainBuffer::DEFAULT_ID); } return recordStatus; } -std::string Conference::getRecFileId() const { - return getConfID(); -} - std::string Conference::getConfID() const { return id_; } diff --git a/daemon/src/conference.h b/daemon/src/conference.h index 4ce74de722d1363ceae5e4d3ae1a9935d57788ba..56ba840ddea8e43397608461ab3f05b20fd31055 100644 --- a/daemon/src/conference.h +++ b/daemon/src/conference.h @@ -86,11 +86,6 @@ class Conference : public Recordable { */ ParticipantSet getParticipantList() const; - /** - * Get recording file ID - */ - std::string getRecFileId() const; - /** * Start/stop recording toggle */ diff --git a/daemon/src/config/Makefile.am b/daemon/src/config/Makefile.am index f64c876291d13ed2c4f69c956136123553d6df9f..a790afe67de424c15ce3853783bcc1c2b336d1aa 100644 --- a/daemon/src/config/Makefile.am +++ b/daemon/src/config/Makefile.am @@ -1,18 +1,16 @@ noinst_LTLIBRARIES = libconfig.la libconfig_la_SOURCES = \ - config.cpp \ + sfl_config.cpp \ yamlemitter.cpp \ yamlparser.cpp \ yamlnode.cpp noinst_HEADERS = \ - config.h \ + sfl_config.h \ serializable.h \ yamlemitter.h \ yamlparser.h \ yamlnode.h -libconfig_la_LDFLAGS = @yaml_LIBS@ - -libconfig_la_CXXFLAGS = @yaml_CFLAGS@ -I $(top_srcdir)/src +libconfig_la_CXXFLAGS = -I $(top_srcdir)/src diff --git a/daemon/src/config/serializable.h b/daemon/src/config/serializable.h index 26684f85f3104adc3ca3cd3de723c848c8fcff4a..24d008b25275a3cd1781edd37bd0b5000fa78263 100644 --- a/daemon/src/config/serializable.h +++ b/daemon/src/config/serializable.h @@ -28,21 +28,20 @@ * as that of the covered work. */ -#ifndef __SERIALIZABLE_H__ -#define __SERIALIZABLE_H__ +#ifndef SERIALIZABLE_H__ +#define SERIALIZABLE_H__ - -#include "yamlparser.h" -#include "yamlemitter.h" -#include "yamlnode.h" +namespace Conf { + class YamlEmitter; + class MappingNode; +} class Serializable { public: virtual ~Serializable() {}; - virtual void serialize(Conf::YamlEmitter *emitter) = 0; - - virtual void unserialize(Conf::MappingNode *map) = 0; + virtual void serialize(Conf::YamlEmitter &emitter) = 0; + virtual void unserialize(const Conf::MappingNode &map) = 0; }; #endif diff --git a/daemon/src/config/config.cpp b/daemon/src/config/sfl_config.cpp similarity index 79% rename from daemon/src/config/config.cpp rename to daemon/src/config/sfl_config.cpp index 32d56f9481e0f132afc80c1e805ca8653ab76323..c7e5ac31027d9e8302107eeb30a4b7a34698900c 100644 --- a/daemon/src/config/config.cpp +++ b/daemon/src/config/sfl_config.cpp @@ -29,8 +29,8 @@ * as that of the covered work. */ -#include "config.h" -#include "../global.h" +#include "sfl_config.h" +#include "logger.h" #include <fstream> #include <cstdlib> #include <sys/types.h> @@ -102,7 +102,7 @@ ConfigTree::getSections() const * If the section doesn't exists, create it */ void -ConfigTree::addConfigTreeItem(const std::string& section, const ConfigTreeItem item) +ConfigTree::addConfigTreeItem(const std::string& section, const ConfigTreeItem &item) { // if we doesn't find the item, create it SectionMap::iterator iter = sections_.find(section); @@ -132,40 +132,6 @@ ConfigTree::getConfigTreeItemValue(const std::string& section, const std::string return getDefaultValue(itemName); } -// throw a ConfigTreeItemException if not found -int -ConfigTree::getConfigTreeItemIntValue(const std::string& section, const std::string& itemName) const -{ - std::string configItem = getConfigTreeItemValue(section, itemName); - int retval = atoi(configItem.data()); - - return retval; -} - -bool -ConfigTree::getConfigTreeItemBoolValue(const std::string& section, const std::string& itemName) const -{ - return getConfigTreeItemValue(section, itemName) == "true"; -} - -bool -ConfigTree::getConfigTreeItemToken(const std::string& section, const std::string& itemName, std::list<std::string>& arg) const -{ - const ConfigTreeItem *item = getConfigTreeItem(section, itemName); - - if (item) { - arg.clear(); - arg.push_back(section); - arg.push_back(itemName); - arg.push_back(item->getType()); - arg.push_back(item->getValue()); - arg.push_back(item->getDefaultValue()); - return true; - } - else - return false; -} - /** * Return a ConfigTreeItem or NULL if not found */ @@ -223,50 +189,13 @@ void ConfigTree::setConfigTreeItem(const std::string& section, return; } -// Save config to a file (ini format) -// return false if empty, no config, or enable to open -// return true if everything is ok -bool -ConfigTree::saveConfigTree(const std::string& fileName) const -{ - DEBUG("ConfigTree: Save %s", fileName.c_str()); - - if (fileName.empty() and sections_.begin() == sections_.end()) - return false; - - std::fstream file; - - file.open(fileName.data(), std::fstream::out); - - if (!file.is_open()) { - ERROR("ConfigTree: Error: Could not open %s configuration file", fileName.c_str()); - return false; - } - - // for each section, for each item... - for (SectionMap::const_iterator iter = sections_.begin(); iter != sections_.end(); ++iter) { - file << "[" << iter->first << "]" << std::endl; - for (ItemMap::const_iterator iterItem = iter->second.begin(); iterItem != iter->second.end(); ++iterItem) - file << iterItem->first << "=" << iterItem->second.getValue() << std::endl; - - file << std::endl; - } - - file.close(); - - if (chmod(fileName.c_str(), S_IRUSR | S_IWUSR)) - ERROR("ConfigTree: Error: Failed to set permission on configuration: %m"); - - return true; -} - // Create the tree from an existing ini file // false = error // true = OK bool ConfigTree::populateFromFile(const std::string& fileName) { - DEBUG("ConfigTree: Populate from file %s", fileName.c_str()); + DEBUG("Populate from file %s", fileName.c_str()); if (fileName.empty()) return false; @@ -393,4 +322,3 @@ ConfigTreeIterator::next() return tk; } } // end namespace ConfigTree - diff --git a/daemon/src/config/config.h b/daemon/src/config/sfl_config.h similarity index 93% rename from daemon/src/config/config.h rename to daemon/src/config/sfl_config.h index 6c1643aa19886b5596bf05098a6a58a951f62871..d24f1c5b8269d66459979b1115d49ad9994ace64 100644 --- a/daemon/src/config/config.h +++ b/daemon/src/config/sfl_config.h @@ -106,7 +106,7 @@ class ConfigTree { */ std::list<std::string> getSections() const; - void addConfigTreeItem(const std::string& section, const ConfigTreeItem item); + void addConfigTreeItem(const std::string& section, const ConfigTreeItem &item); /** * Set a configuration value. * @@ -129,21 +129,12 @@ class ConfigTree { * but the item doesn't. */ std::string getConfigTreeItemValue(const std::string& section, const std::string& itemName) const; - int getConfigTreeItemIntValue(const std::string& section, const std::string& itemName) const; - bool getConfigTreeItemBoolValue(const std::string& section, const std::string& itemName) const; - - /** - * Flush data to .ini file - */ - bool saveConfigTree(const std::string& fileName) const; /** * Load data (and fill ConfigTree) from disk */ bool populateFromFile(const std::string& fileName); - bool getConfigTreeItemToken(const std::string& section, const std::string& itemName, std::list<std::string>& arg) const; - private: std::string getDefaultValue(const std::string& key) const; const ConfigTreeItem* getConfigTreeItem(const std::string& section, const std::string& itemName) const; diff --git a/daemon/src/config/yamlemitter.cpp b/daemon/src/config/yamlemitter.cpp index cc6a93b1c874c7b1c283fe592fce8228f661e15f..9713bba467a7c137547623662566c6f522cd9a0c 100644 --- a/daemon/src/config/yamlemitter.cpp +++ b/daemon/src/config/yamlemitter.cpp @@ -29,8 +29,9 @@ */ #include "yamlemitter.h" -#include <stdio.h> -#include "../global.h" +#include "yamlnode.h" +#include <cstdio> +#include "logger.h" namespace Conf { @@ -73,11 +74,13 @@ void YamlEmitter::close() { yaml_emitter_delete(&emitter_); + // Refererence: + // http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.9 if (!fd_) - throw YamlEmitterException("File descriptor not valid"); + ERROR("File descriptor not valid"); if (fclose(fd_)) - throw YamlEmitterException("Error closing file descriptor"); + ERROR("Error closing file descriptor"); } void YamlEmitter::serializeData() @@ -89,14 +92,12 @@ void YamlEmitter::serializeData() void YamlEmitter::serializeAccount(MappingNode *map) { - int accountmapping; - if (map->getType() != MAPPING) throw YamlEmitterException("Node type is not a mapping while writing account"); if (isFirstAccount_) { int accountid; - DEBUG("YamlEmitter: Create account sequence"); + DEBUG("Create account sequence"); // accountSequence_ need to be static outside this scope since reused each time an account is written if ((accountid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) "accounts", -1, YAML_PLAIN_SCALAR_STYLE)) == 0) @@ -111,162 +112,47 @@ void YamlEmitter::serializeAccount(MappingNode *map) isFirstAccount_ = false; } - if ((accountmapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) + int accountMapping; + if ((accountMapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) throw YamlEmitterException("Could not add account mapping to document"); - if (yaml_document_append_sequence_item(&document_, accountSequence_, accountmapping) == 0) + if (yaml_document_append_sequence_item(&document_, accountSequence_, accountMapping) == 0) throw YamlEmitterException("Could not append account mapping to sequence"); - Mapping *internalmap = map->getMapping(); - for (Mapping::iterator iter = internalmap->begin(); iter != internalmap->end(); ++iter) - addMappingItem(accountmapping, iter->first, iter->second); -} - -void YamlEmitter::serializePreference(MappingNode *map) -{ - if (map->getType() != MAPPING) - throw YamlEmitterException("Node type is not a mapping while writing preferences"); - - static const char * const PREFERENCE_STR = "preferences"; - int preferenceid; - - if ((preferenceid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) PREFERENCE_STR, -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - int preferencemapping; - if ((preferencemapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add mapping to document"); - - if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, preferenceid, preferencemapping) == 0) - throw YamlEmitterException("Could not add mapping pair to top leve mapping"); - - Mapping *internalmap = map->getMapping(); - for (Mapping::iterator iter = internalmap->begin(); iter != internalmap->end(); ++iter) - addMappingItem(preferencemapping, iter->first, iter->second); -} - -void YamlEmitter::serializeVoipPreference(MappingNode *map) -{ - if (map->getType() != MAPPING) - throw YamlEmitterException("Node type is not a mapping while writing preferences"); - - - static const char *const PREFERENCE_STR = "voipPreferences"; - int preferenceid; - if ((preferenceid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) PREFERENCE_STR, -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - int preferencemapping; - if ((preferencemapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add mapping to document"); - - if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, preferenceid, preferencemapping) == 0) - throw YamlEmitterException("Could not add mapping pair to top leve mapping"); - - Mapping *internalmap = map->getMapping(); - Mapping::iterator iter = internalmap->begin(); - - while (iter != internalmap->end()) { - addMappingItem(preferencemapping, iter->first, iter->second); - iter++; - } -} - -void YamlEmitter::serializeAddressbookPreference(MappingNode *map) -{ - if (map->getType() != MAPPING) - throw YamlEmitterException("Node type is not a mapping while writing preferences"); - - static const char * const PREFERENCE_STR = "addressbook"; - int preferenceid; - if ((preferenceid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) PREFERENCE_STR, -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - int preferencemapping; - if ((preferencemapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add mapping to document"); - - if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, preferenceid, preferencemapping) == 0) - throw YamlEmitterException("Could not add mapping pair to top leve mapping"); - - Mapping *internalmap = map->getMapping(); - for (Mapping::iterator iter = internalmap->begin(); iter != internalmap->end(); ++iter) - addMappingItem(preferencemapping, iter->first, iter->second); + addMappingItems(accountMapping, map->getMapping()); } -void YamlEmitter::serializeHooksPreference(MappingNode *map) +void YamlEmitter::serializePreference(MappingNode *map, const char *preference_str) { if (map->getType() != MAPPING) throw YamlEmitterException("Node type is not a mapping while writing preferences"); - static const char * const PREFERENCE_STR = "hooks"; int preferenceid; - if ((preferenceid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) PREFERENCE_STR, -1, YAML_PLAIN_SCALAR_STYLE)) == 0) + if ((preferenceid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) preference_str, -1, YAML_PLAIN_SCALAR_STYLE)) == 0) throw YamlEmitterException("Could not add scalar to document"); - int preferencemapping; - if ((preferencemapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) + int preferenceMapping; + if ((preferenceMapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) throw YamlEmitterException("Could not add mapping to document"); - if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, preferenceid, preferencemapping) == 0) + if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, preferenceid, preferenceMapping) == 0) throw YamlEmitterException("Could not add mapping pair to top leve mapping"); - Mapping *internalmap = map->getMapping(); - for (Mapping::iterator iter = internalmap->begin(); iter != internalmap->end(); ++iter) - addMappingItem(preferencemapping, iter->first, iter->second); + addMappingItems(preferenceMapping, map->getMapping()); } +typedef std::map<std::string, YamlNode*> Mapping; -void YamlEmitter::serializeAudioPreference(MappingNode *map) +void YamlEmitter::addMappingItems(int mappingID, Mapping *iMap) { - static const char *const PREFERENCE_STR = "audio"; - - int preferenceid, preferencemapping; - - if (map->getType() != MAPPING) - throw YamlEmitterException("Node type is not a mapping while writing preferences"); - - if ((preferenceid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) PREFERENCE_STR, -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - if ((preferencemapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add mapping to document"); - - if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, preferenceid, preferencemapping) == 0) - throw YamlEmitterException("Could not add mapping pair to top leve mapping"); - - Mapping *internalmap = map->getMapping(); - for (Mapping::iterator iter = internalmap->begin(); iter != internalmap->end(); ++iter) - addMappingItem(preferencemapping, iter->first, iter->second); + for (Mapping::const_iterator i = iMap->begin(); i != iMap->end(); ++i) + addMappingItem(mappingID, i->first, i->second); } - -void YamlEmitter::serializeShortcutPreference(MappingNode *map) -{ - if (map->getType() != MAPPING) - throw YamlEmitterException("Node type is not a mapping while writing preferences"); - - static const char *const PREFERENCE_STR = "shortcuts"; - int preferenceid; - if ((preferenceid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) PREFERENCE_STR, -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - int preferencemapping; - if ((preferencemapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add mapping to document"); - - if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, preferenceid, preferencemapping) == 0) - throw YamlEmitterException("Could not add mapping pair to top leve mapping"); - - Mapping *internalmap = map->getMapping(); - for (Mapping::iterator iter = internalmap->begin(); iter != internalmap->end(); ++iter) - addMappingItem(preferencemapping, iter->first, iter->second); -} - - -void YamlEmitter::addMappingItem(int mappingid, std::string key, YamlNode *node) +void YamlEmitter::addMappingItem(int mappingid, const std::string &key, YamlNode *node) { if (node->getType() == SCALAR) { - ScalarNode *sclr = (ScalarNode *) node; + ScalarNode *sclr = static_cast<ScalarNode *>(node); int temp1; if ((temp1 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) key.c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0) @@ -280,7 +166,7 @@ void YamlEmitter::addMappingItem(int mappingid, std::string key, YamlNode *node) throw YamlEmitterException("Could not append mapping pair to mapping"); } else if (node->getType() == MAPPING) { - MappingNode *map = (MappingNode *) node; + MappingNode *map = static_cast<MappingNode *>(node); int temp1; if ((temp1 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) key.c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0) @@ -293,9 +179,7 @@ void YamlEmitter::addMappingItem(int mappingid, std::string key, YamlNode *node) if (yaml_document_append_mapping_pair(&document_, mappingid, temp1, temp2) == 0) throw YamlEmitterException("Could not add mapping pair to mapping"); - Mapping *internalmap = map->getMapping(); - for (Mapping::iterator iter = internalmap->begin(); iter != internalmap->end(); ++iter) - addMappingItem(temp2, iter->first, iter->second); + addMappingItems(temp2, map->getMapping()); } else if (node->getType() == SEQUENCE) { SequenceNode *seqnode = static_cast<SequenceNode *>(node); @@ -322,11 +206,7 @@ void YamlEmitter::addMappingItem(int mappingid, std::string key, YamlNode *node) throw YamlEmitterException("Could not append account mapping to sequence"); MappingNode *mapnode = static_cast<MappingNode*>(yamlNode); - Mapping *map = mapnode->getMapping(); - Mapping::iterator mapit; - - for (mapit = map->begin(); mapit != map->end() ; ++mapit) - addMappingItem(id, mapit->first, mapit->second); + addMappingItems(id, mapnode->getMapping()); } } else throw YamlEmitterException("Unknown node type while adding mapping node"); diff --git a/daemon/src/config/yamlemitter.h b/daemon/src/config/yamlemitter.h index 7cbd4f7ec516333aeebf7cd1a17545eb966e20ad..4f6234e63c878223dc220cb68b6718be669803ed 100644 --- a/daemon/src/config/yamlemitter.h +++ b/daemon/src/config/yamlemitter.h @@ -28,24 +28,26 @@ * as that of the covered work. */ -#ifndef __YAMLEMITTER_H__ -#define __YAMLEMITTER_H__ +#ifndef YAMLEMITTER_H__ +#define YAMLEMITTER_H__ #include <yaml.h> #include <stdexcept> #include <string> +#include <map> #include "noncopyable.h" -#include "yamlnode.h" namespace Conf { #define EMITTER_BUFFERSIZE 65536 #define EMITTER_MAXEVENT 1024 +class MappingNode; +class YamlNode; + class YamlEmitterException : public std::runtime_error { public: - YamlEmitterException(const std::string& str="") : - std::runtime_error("YamlEmitterException occured: " + str) {} + YamlEmitterException(const char *err) : std::runtime_error(err) {} }; class YamlEmitter { @@ -61,17 +63,7 @@ class YamlEmitter { void serializeAccount(MappingNode *map); - void serializePreference(MappingNode *map); - - void serializeVoipPreference(MappingNode *map); - - void serializeAddressbookPreference(MappingNode *map); - - void serializeHooksPreference(MappingNode *map); - - void serializeAudioPreference(MappingNode *map); - - void serializeShortcutPreference(MappingNode *map); + void serializePreference(MappingNode *map, const char *preference_str); void writeAudio(); @@ -84,7 +76,8 @@ class YamlEmitter { private: NON_COPYABLE(YamlEmitter); - void addMappingItem(int mappingid, std::string key, YamlNode *node); + void addMappingItems(int mappingid, std::map<std::string, YamlNode*> *mapping); + void addMappingItem(int mappingid, const std::string &key, YamlNode *node); std::string filename_; @@ -126,4 +119,4 @@ class YamlEmitter { }; } -#endif +#endif // YAMLEMITTER_H__ diff --git a/daemon/src/config/yamlnode.cpp b/daemon/src/config/yamlnode.cpp index 5bae6cf3016703496b4eda765826462a29022b2b..e20f870ae7c8592dad356c982d2415f8676d2d61 100644 --- a/daemon/src/config/yamlnode.cpp +++ b/daemon/src/config/yamlnode.cpp @@ -29,32 +29,30 @@ */ #include "yamlnode.h" -#include "global.h" +#include <cstdlib> +#include "logger.h" namespace Conf { - void YamlDocument::addNode(YamlNode *node) { - Sequence::iterator it = doc.end(); - doc.insert(it, node); + Sequence::iterator it = doc_.end(); + doc_.insert(it, node); } YamlNode *YamlDocument::popNode() { - YamlNode *node = doc.front(); + YamlNode *node = doc_.front(); //removed element's destructor is called - doc.pop_front(); + doc_.pop_front(); return node; } void YamlDocument::deleteChildNodes() { - Sequence::iterator it = doc.begin(); - - while (it != doc.end()) { + for (Sequence::iterator it = doc_.begin(); it != doc_.end(); ++it) { YamlNode *yamlNode = static_cast<YamlNode *>(*it); switch (yamlNode->getType()) { @@ -83,48 +81,42 @@ void YamlDocument::deleteChildNodes() default: break; } - - it++; } } void MappingNode::addNode(YamlNode *node) { - Mapping::iterator it = map.end(); - map.insert(it, std::pair<std::string, YamlNode *> (tmpKey, node)); + setKeyValue(tmpKey_, node); } +typedef std::map<std::string, YamlNode*> Mapping; + void MappingNode::setKeyValue(const std::string &key, YamlNode *value) { - Mapping::iterator it = map.end(); - map.insert(it, std::pair<std::string, YamlNode *> (key, value)); + map_[key] = value; } void MappingNode::removeKeyValue(const std::string &key) { - - Mapping::iterator it = map.find(key); - map.erase(it); + Mapping::iterator it = map_.find(key); + map_.erase(it); } - -YamlNode *MappingNode::getValue(const std::string &key) +YamlNode *MappingNode::getValue(const std::string &key) const { + Mapping::const_iterator it = map_.find(key); - Mapping::iterator it = map.find(key); - if (it != map.end()) { + + if (it != map_.end()) return it->second; - } else { - DEBUG("MappingNode: Could not find %s", key.c_str()); + else return NULL; - } } -void MappingNode::getValue(const std::string &key, bool *b) +void MappingNode::getValue(const std::string &key, bool *b) const { - ScalarNode *node = (ScalarNode*)getValue(key); - + ScalarNode *node = static_cast<ScalarNode*>(getValue(key)); if (!node) return; @@ -132,23 +124,25 @@ void MappingNode::getValue(const std::string &key, bool *b) *b = v == "true"; } -void MappingNode::getValue(const std::string &key, int *i) +void MappingNode::getValue(const std::string &key, int *i) const { - ScalarNode *node = (ScalarNode*)getValue(key); - - if (!node) + ScalarNode *node = dynamic_cast<ScalarNode*>(getValue(key)); + if (!node) { + ERROR("node %s not found", key.c_str()); return; + } - const std::string &v = node->getValue(); - *i = atoi(v.c_str()); + *i = std::atoi(node->getValue().c_str()); } -void MappingNode::getValue(const std::string &key, std::string *v) +void MappingNode::getValue(const std::string &key, std::string *v) const { - ScalarNode *node = (ScalarNode*)getValue(key); + ScalarNode *node = dynamic_cast<ScalarNode*>(getValue(key)); - if (!node) + if (!node) { + ERROR("node %s not found", key.c_str()); return; + } *v = node->getValue(); } @@ -156,10 +150,8 @@ void MappingNode::getValue(const std::string &key, std::string *v) void MappingNode::deleteChildNodes() { - Mapping::iterator it; - - for (it = map.begin(); it != map.end(); ++it) { - YamlNode *yamlNode = static_cast<YamlNode *>(it->second); + for (Mapping::iterator it = map_.begin(); it != map_.end(); ++it) { + YamlNode *yamlNode = dynamic_cast<YamlNode *>(it->second); if (!yamlNode) continue; @@ -168,21 +160,21 @@ void MappingNode::deleteChildNodes() case DOCUMENT: break; case SEQUENCE: { - SequenceNode *sequence = static_cast<SequenceNode *>(yamlNode); + SequenceNode *sequence = dynamic_cast<SequenceNode *>(yamlNode); sequence->deleteChildNodes(); delete sequence; sequence = NULL; } break; case MAPPING: { - MappingNode *mapping = static_cast<MappingNode *>(yamlNode); + MappingNode *mapping = dynamic_cast<MappingNode *>(yamlNode); mapping->deleteChildNodes(); delete mapping; mapping = NULL; } break; case SCALAR: { - ScalarNode *scalar = static_cast<ScalarNode *>(yamlNode); + ScalarNode *scalar = dynamic_cast<ScalarNode *>(yamlNode); delete scalar; scalar = NULL; } @@ -195,16 +187,13 @@ void MappingNode::deleteChildNodes() void SequenceNode::addNode(YamlNode *node) { - Sequence::iterator it = seq.end(); - seq.insert(it, node); + Sequence::iterator it = seq_.end(); + seq_.insert(it, node); } - void SequenceNode::deleteChildNodes() { - Sequence::iterator it; - - for (it = seq.begin(); it != seq.end(); ++it) { + for (Sequence::iterator it = seq_.begin(); it != seq_.end(); ++it) { YamlNode *yamlNode = static_cast<YamlNode *>(*it); switch (yamlNode->getType()) { diff --git a/daemon/src/config/yamlnode.h b/daemon/src/config/yamlnode.h index 1a7850d0669f34e408e25bc450524614fd9d80ea..990b23733ccf4372fc7a96a4c22ec9437baa938a 100644 --- a/daemon/src/config/yamlnode.h +++ b/daemon/src/config/yamlnode.h @@ -42,58 +42,56 @@ namespace Conf { class YamlNode; typedef std::list<YamlNode *> Sequence; -typedef std::map<std::string, YamlNode *> Mapping; enum NodeType { DOCUMENT, SCALAR, MAPPING, SEQUENCE }; class YamlNode { public: - - YamlNode(NodeType t, YamlNode *top=NULL) : type(t), topNode(top) {} + YamlNode(NodeType t, YamlNode *top = NULL) : type_(t), topNode_(top) {} virtual ~YamlNode() {} - NodeType getType() { - return type; + NodeType getType() const { + return type_; } YamlNode *getTopNode() { - return topNode; + return topNode_; } virtual void deleteChildNodes() = 0; private: NON_COPYABLE(YamlNode); - NodeType type; - YamlNode *topNode; + NodeType type_; + YamlNode *topNode_; }; -class YamlDocument : YamlNode { +class YamlDocument : public YamlNode { public: - YamlDocument(YamlNode* top=NULL) : YamlNode(DOCUMENT, top), doc() {} + YamlDocument(YamlNode* top = NULL) : YamlNode(DOCUMENT, top), doc_() {} void addNode(YamlNode *node); YamlNode *popNode(); Sequence *getSequence() { - return &doc; + return &doc_; } virtual void deleteChildNodes(); private: - Sequence doc; + Sequence doc_; }; class SequenceNode : public YamlNode { public: - SequenceNode(YamlNode *top) : YamlNode(SEQUENCE, top), seq() {} + SequenceNode(YamlNode *top) : YamlNode(SEQUENCE, top), seq_() {} Sequence *getSequence() { - return &seq; + return &seq_; } void addNode(YamlNode *node); @@ -101,57 +99,59 @@ class SequenceNode : public YamlNode { virtual void deleteChildNodes(); private: - Sequence seq; + Sequence seq_; }; class MappingNode : public YamlNode { public: - MappingNode(YamlNode *top) : YamlNode(MAPPING, top), map(), tmpKey() {} + MappingNode(YamlNode *top) : + YamlNode(MAPPING, top), map_(), tmpKey_() {} - Mapping *getMapping() { - return ↦ + std::map<std::string, YamlNode*> * + getMapping() { + return &map_; } void addNode(YamlNode *node); void setTmpKey(std::string key) { - tmpKey = key; + tmpKey_ = key; } - void setKeyValue(const std::string &key, YamlNode *value); + void setKeyValue(const std::string &key, YamlNode *value); void removeKeyValue(const std::string &key); - YamlNode *getValue(const std::string &key); - void getValue(const std::string &key, bool *b); - void getValue(const std::string &key, int *i); - void getValue(const std::string &key, std::string *s); + YamlNode *getValue(const std::string &key) const; + void getValue(const std::string &key, bool *b) const; + void getValue(const std::string &key, int *i) const; + void getValue(const std::string &key, std::string *s) const; virtual void deleteChildNodes(); private: - Mapping map; - std::string tmpKey; + std::map<std::string, YamlNode*> map_; + std::string tmpKey_; }; class ScalarNode : public YamlNode { public: - ScalarNode(std::string s="", YamlNode *top=NULL) : YamlNode(SCALAR, top), str(s) {} - ScalarNode(bool b, YamlNode *top=NULL) : YamlNode(SCALAR, top), str(b ? "true" : "false") {} + ScalarNode(std::string s="", YamlNode *top=NULL) : YamlNode(SCALAR, top), str_(s) {} + ScalarNode(bool b, YamlNode *top=NULL) : YamlNode(SCALAR, top), str_(b ? "true" : "false") {} - const std::string &getValue() { - return str; + const std::string &getValue() const { + return str_; } void setValue(const std::string &s) { - str = s; + str_ = s; } virtual void deleteChildNodes() {} private: - std::string str; + std::string str_; }; } diff --git a/daemon/src/config/yamlparser.cpp b/daemon/src/config/yamlparser.cpp index 44ba3e29bb10f7753ca515109a726982e3911293..03a48f26903f837e78dc4c8fa02779dbeb53ea1a 100644 --- a/daemon/src/config/yamlparser.cpp +++ b/daemon/src/config/yamlparser.cpp @@ -31,8 +31,9 @@ #include "yamlparser.h" #include "../global.h" -#include "config.h" +#include "sfl_config.h" #include "yamlnode.h" +#include "logger.h" #include <cstdio> namespace Conf { @@ -219,21 +220,18 @@ void YamlParser::processStream() void YamlParser::processDocument() { - doc_ = new YamlDocument(); - - if (!doc_) - throw YamlParserException("Not able to create new document"); + doc_ = new YamlDocument; for (; (eventIndex_ < eventNumber_) and (events_[eventIndex_].type != YAML_DOCUMENT_END_EVENT); ++eventIndex_) { switch (events_[eventIndex_].type) { case YAML_SCALAR_EVENT: - processScalar((YamlNode *) doc_); + processScalar(doc_); break; case YAML_SEQUENCE_START_EVENT: - processSequence((YamlNode *) doc_); + processSequence(doc_); break; case YAML_MAPPING_START_EVENT: - processMapping((YamlNode *) doc_); + processMapping(doc_); break; default: break; @@ -250,7 +248,7 @@ void YamlParser::processScalar(YamlNode *topNode) if (!topNode) throw YamlParserException("No container for scalar"); - ScalarNode *sclr = new ScalarNode(std::string((const char*)events_[eventIndex_].data.scalar.value), topNode); + ScalarNode *sclr = new ScalarNode(std::string((const char*) events_[eventIndex_].data.scalar.value), topNode); switch (topNode->getType()) { case DOCUMENT: @@ -261,6 +259,7 @@ void YamlParser::processScalar(YamlNode *topNode) break; case MAPPING: ((MappingNode *)(topNode))->addNode(sclr); + break; case SCALAR: default: break; @@ -366,6 +365,8 @@ void YamlParser::processMapping(YamlNode *topNode) void YamlParser::constructNativeData() { + if (!doc_) + throw YamlParserException("YAML Document not initialized"); Sequence *seq = doc_->getSequence(); for (Sequence::iterator iter = seq->begin(); iter != seq->end(); ++iter) { @@ -390,7 +391,7 @@ void YamlParser::constructNativeData() void YamlParser::mainNativeDataMapping(MappingNode *map) { - Mapping *mapping = map->getMapping(); + std::map<std::string, YamlNode*> *mapping = map->getMapping(); accountSequence_ = (SequenceNode*)(*mapping)["accounts"]; addressbookNode_ = (MappingNode*)(*mapping)["addressbook"]; diff --git a/daemon/src/dbus/Makefile.am b/daemon/src/dbus/Makefile.am index 53ab8b9d24154deabefcaa9fd9f8220b2fa4d53e..992b691253687eb5ba8a379511ba210da8e3a8ae 100644 --- a/daemon/src/dbus/Makefile.am +++ b/daemon/src/dbus/Makefile.am @@ -29,6 +29,7 @@ libdbus_la_CXXFLAGS = \ -DPROGSHAREDIR=\"${datadir}/sflphone\" \ $(NETWORKMANAGER) + noinst_HEADERS = \ callmanager.h \ configurationmanager.h \ diff --git a/daemon/src/dbus/callmanager-introspec.xml b/daemon/src/dbus/callmanager-introspec.xml index a742426b77507d01a447521eca94b2237ad136f1..5c48b6262df854a5c95324c3d6052cf248be620b 100644 --- a/daemon/src/dbus/callmanager-introspec.xml +++ b/daemon/src/dbus/callmanager-introspec.xml @@ -313,6 +313,24 @@ </arg> </method> + <method name="getConferenceId" tp:name-for-bindings="getConferenceId"> + <tp:added version="1.1.0"/> + <tp:docstring> + If thsi call participate to a conference, return the conference id. + Return an empty string elsewhere. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call id. + </tp:docstring> + </arg> + <arg type="s" name="confID" direction="out"> + <tp:docstring> + A string containing the conference ID, or an empty string. + </tp:docstring> + </arg> + </method> + <method name="setRecording" tp:name-for-bindings="setRecording"> <tp:docstring> Start recording a call. @@ -375,6 +393,7 @@ <li>DISPLAY_NAME</li> <li>CALL_STATE</li> <li>CALL_TYPE</li> + <li>CONF_ID</li> </ul> </tp:docstring> </arg> diff --git a/daemon/src/dbus/callmanager.cpp b/daemon/src/dbus/callmanager.cpp index 809e0628edde25ef9b6c42703c929406caad15c7..c09da3affa2a622ef6f0ba3cbc3fb9fab2ef3326 100644 --- a/daemon/src/dbus/callmanager.cpp +++ b/daemon/src/dbus/callmanager.cpp @@ -35,9 +35,11 @@ #include "sip/sipcall.h" #include "sip/sipvoiplink.h" +#include "audio/audiolayer.h" #include "audio/audiortp/audio_rtp_factory.h" #include "audio/audiortp/audio_zrtp_session.h" +#include "logger.h" #include "manager.h" CallManager::CallManager(DBus::Connection& connection) @@ -72,7 +74,7 @@ void CallManager::placeCallFirstAccount(const std::string& callID, accountList = Manager::instance().getAccountList(); for (vector<string>::const_iterator iter = accountList.begin(); iter != accountList.end(); ++iter) { - if ((*iter != IP2IP_PROFILE) && Manager::instance().getAccount(*iter)->isEnabled()) { + if ((*iter != SIPAccount::IP2IP_PROFILE) && Manager::instance().getAccount(*iter)->isEnabled()) { Manager::instance().outgoingCall(*iter, callID, to); return; } @@ -128,10 +130,20 @@ void CallManager::attendedTransfer(const std::string& transferID, const std::str void CallManager::setVolume(const std::string& device, const double& value) { - if (device == "speaker") - Manager::instance().setSpkrVolume((int)(value * 100.0)); - else if (device == "mic") - Manager::instance().setMicVolume((int)(value * 100.0)); + AudioLayer *audiolayer = Manager::instance().getAudioDriver(); + + if(!audiolayer) { + ERROR("Audio layer not valid while updating volume"); + return; + } + + DEBUG("DBUS set volume for %s: %f", device.c_str(), value); + + if (device == "speaker") { + audiolayer->setPlaybackGain((int)(value * 100.0)); + } else if (device == "mic") { + audiolayer->setCaptureGain((int)(value * 100.0)); + } volumeChanged(device, value); } @@ -139,10 +151,17 @@ void CallManager::setVolume(const std::string& device, const double& value) double CallManager::getVolume(const std::string& device) { + AudioLayer *audiolayer = Manager::instance().getAudioDriver(); + + if(!audiolayer) { + ERROR("Audio layer not valid while updating volume"); + return 0.0; + } + if (device == "speaker") - return Manager::instance().getSpkrVolume() / 100.0; + return audiolayer->getPlaybackGain() / 100.0; else if (device == "mic") - return Manager::instance().getMicVolume() / 100.0; + return audiolayer->getCaptureGain() / 100.0; return 0; } @@ -213,6 +232,12 @@ CallManager::getParticipantList(const std::string& confID) return Manager::instance().getParticipantList(confID); } +std::string +CallManager::getConferenceId(const std::string& callID) +{ + return Manager::instance().getConferenceId(callID); +} + bool CallManager::startRecordedFilePlayback(const std::string& filepath) { diff --git a/daemon/src/dbus/callmanager.h b/daemon/src/dbus/callmanager.h index 7758fa7235dbd86918b1d63a9025600f4b27b817..ce613f00ad08adec6a2a2c13549d0a82d634b5dd 100644 --- a/daemon/src/dbus/callmanager.h +++ b/daemon/src/dbus/callmanager.h @@ -99,6 +99,7 @@ class CallManager void unholdConference(const std::string& confID); std::vector< std::string > getConferenceList(); std::vector< std::string > getParticipantList(const std::string& confID); + std::string getConferenceId(const std::string& callID); std::map< std::string, std::string > getConferenceDetails(const std::string& callID); /* File Playback methods */ diff --git a/daemon/src/dbus/configurationmanager-introspec.xml b/daemon/src/dbus/configurationmanager-introspec.xml index 926ff774de75a99636920b3dc711ab6914695cb9..edf5883da5b183ae0cf1989ddbc73a07b8017dfd 100644 --- a/daemon/src/dbus/configurationmanager-introspec.xml +++ b/daemon/src/dbus/configurationmanager-introspec.xml @@ -37,9 +37,9 @@ <li>DISPLAY_NAMEL: The display name</li> <li>STUN_ENABLE: True or False (Default: False)</li> <li>STUN_SERVER: The STUN server address</li> - <li>REGISTRATION_STATUS: The account registration status. Should be Registered to make calls.</li> - <li>REGISTRATION_STATE_CODE</li> - <li>REGISTRATION_STATE_DESCRIPTION</li> + <li>ACCOUNT_REGISTRATION_STATUS: The account registration status. Should be Registered to make calls.</li> + <li>ACCOUNT_REGISTRATION_STATE_CODE</li> + <li>ACCOUNT_REGISTRATION_STATE_DESC</li> <li>SRTP_KEY_EXCHANGE</li> <li>SRTP_ENABLE: Whether or not voice communication are encrypted - True or False (Default: False)</li> <li>SRTP_RTP_FALLBACK</li> @@ -91,7 +91,6 @@ Get configuration settings of the IP2IP_PROFILE. They are sligthly different from account settings since no VoIP accounts are involved. </tp:docstring> <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <!--<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/>--> <arg type="a{ss}" name="details" direction="out" tp:type="String_String_Map"> <tp:docstring> Available parameters are: @@ -447,6 +446,24 @@ <signal name="accountsChanged" tp:name-for-bindings="accountsChanged"> </signal> + <signal name="historyChanged" tp:name-for-bindings="historyChanged"> + </signal> + + <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged"> + <arg type="s" name="accountID"/> + <arg type="i" name="registration_state"/> + </signal> + + <signal name="stunStatusFailure" tp:name-for_bindings="stunStatusFailure"> + <arg type="s" name="reason"> + </arg> + </signal> + + <signal name="stunStatusSuccess" tp:name-for_bindings="stunStatusSuccess"> + <arg type="s" name="message"> + </arg> + </signal> + <signal name="errorAlert" tp:name-for-bindings="errorAlert"> <arg type="i" name="code"> </arg> diff --git a/daemon/src/dbus/configurationmanager.cpp b/daemon/src/dbus/configurationmanager.cpp index 08e0c6ebdace35b4d5e72acb27e457ff5d7f76b2..32d44dac01ac7e1dd8be3ca7794d372bedfc2151 100644 --- a/daemon/src/dbus/configurationmanager.cpp +++ b/daemon/src/dbus/configurationmanager.cpp @@ -30,14 +30,17 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #include "configurationmanager.h" #include <sstream> -#include "config.h" #include "../manager.h" #include "sip/sipvoiplink.h" +#include "sip/siptransport.h" #include "account.h" +#include "logger.h" #include "sip/sipaccount.h" const char* ConfigurationManager::SERVER_PATH = @@ -50,15 +53,15 @@ ConfigurationManager::ConfigurationManager(DBus::Connection& connection) : std::map<std::string, std::string> ConfigurationManager::getIp2IpDetails() { std::map<std::string, std::string> ip2ipAccountDetails; - SIPAccount *sipaccount = static_cast<SIPAccount *>(Manager::instance().getAccount(IP2IP_PROFILE)); + SIPAccount *sipaccount = Manager::instance().getIP2IPAccount(); if (!sipaccount) { - ERROR("ConfigurationManager: could not find account"); + ERROR("Could not find IP2IP account"); return ip2ipAccountDetails; } else return sipaccount->getIp2IpDetails(); - std::map<std::string, std::string> tlsSettings = getTlsSettings(); + std::map<std::string, std::string> tlsSettings(getTlsSettings()); std::copy(tlsSettings.begin(), tlsSettings.end(), std::inserter(ip2ipAccountDetails, ip2ipAccountDetails.end())); @@ -79,19 +82,19 @@ ConfigurationManager::getTlsSettingsDefault() portstr << DEFAULT_SIP_TLS_PORT; std::map<std::string, std::string> tlsSettingsDefault; - tlsSettingsDefault[TLS_LISTENER_PORT] = portstr.str(); - tlsSettingsDefault[TLS_CA_LIST_FILE] = ""; - tlsSettingsDefault[TLS_CERTIFICATE_FILE] = ""; - tlsSettingsDefault[TLS_PRIVATE_KEY_FILE] = ""; - tlsSettingsDefault[TLS_PASSWORD] = ""; - tlsSettingsDefault[TLS_METHOD] = "TLSv1"; - tlsSettingsDefault[TLS_CIPHERS] = ""; - tlsSettingsDefault[TLS_SERVER_NAME] = ""; - tlsSettingsDefault[TLS_VERIFY_SERVER] = "true"; - tlsSettingsDefault[TLS_VERIFY_CLIENT] = "true"; - tlsSettingsDefault[TLS_REQUIRE_CLIENT_CERTIFICATE] = "true"; - tlsSettingsDefault[TLS_NEGOTIATION_TIMEOUT_SEC] = "2"; - tlsSettingsDefault[TLS_NEGOTIATION_TIMEOUT_MSEC] = "0"; + tlsSettingsDefault[CONFIG_TLS_LISTENER_PORT] = portstr.str(); + tlsSettingsDefault[CONFIG_TLS_CA_LIST_FILE] = ""; + tlsSettingsDefault[CONFIG_TLS_CERTIFICATE_FILE] = ""; + tlsSettingsDefault[CONFIG_TLS_PRIVATE_KEY_FILE] = ""; + tlsSettingsDefault[CONFIG_TLS_PASSWORD] = ""; + tlsSettingsDefault[CONFIG_TLS_METHOD] = "TLSv1"; + tlsSettingsDefault[CONFIG_TLS_CIPHERS] = ""; + tlsSettingsDefault[CONFIG_TLS_SERVER_NAME] = ""; + tlsSettingsDefault[CONFIG_TLS_VERIFY_SERVER] = "true"; + tlsSettingsDefault[CONFIG_TLS_VERIFY_CLIENT] = "true"; + tlsSettingsDefault[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = "true"; + tlsSettingsDefault[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC] = "2"; + tlsSettingsDefault[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC] = "0"; return tlsSettingsDefault; } @@ -100,7 +103,7 @@ std::map<std::string, std::string> ConfigurationManager::getTlsSettings() { std::map<std::string, std::string> tlsSettings; - SIPAccount *sipaccount = (SIPAccount *) Manager::instance().getAccount(IP2IP_PROFILE); + SIPAccount *sipaccount = Manager::instance().getIP2IPAccount(); if (!sipaccount) return tlsSettings; @@ -110,10 +113,10 @@ std::map<std::string, std::string> ConfigurationManager::getTlsSettings() void ConfigurationManager::setTlsSettings(const std::map<std::string, std::string>& details) { - SIPAccount * sipaccount = (SIPAccount *) Manager::instance().getAccount(IP2IP_PROFILE); + SIPAccount * sipaccount = Manager::instance().getIP2IPAccount(); if (!sipaccount) { - DEBUG("ConfigurationManager: Error: No valid account in set TLS settings"); + DEBUG("No valid account in set TLS settings"); return; } @@ -261,7 +264,7 @@ int32_t ConfigurationManager::getAudioDeviceIndex(const std::string& name) std::string ConfigurationManager::getCurrentAudioOutputPlugin() { - DEBUG("ConfigurationManager: Get audio plugin %s", Manager::instance().getCurrentAudioOutputPlugin().c_str()); + DEBUG("Get audio plugin %s", Manager::instance().getCurrentAudioOutputPlugin().c_str()); return Manager::instance().getCurrentAudioOutputPlugin(); } @@ -389,13 +392,13 @@ void ConfigurationManager::setAddressbookList( std::map<std::string, std::string> ConfigurationManager::getHookSettings() { - return Manager::instance().getHookSettings(); + return Manager::instance().hookPreference.toMap(); } void ConfigurationManager::setHookSettings(const std::map<std::string, std::string>& settings) { - Manager::instance().setHookSettings(settings); + Manager::instance().hookPreference = HookPreference(settings); } void ConfigurationManager::setAccountsOrder(const std::string& order) @@ -411,17 +414,17 @@ std::vector<std::map<std::string, std::string> > ConfigurationManager::getHistor std::string ConfigurationManager::getAddrFromInterfaceName(const std::string& interface) { - return SIPVoIPLink::getInterfaceAddrFromName(interface); + return SipTransport::getInterfaceAddrFromName(interface); } std::vector<std::string> ConfigurationManager::getAllIpInterface() { - return SIPVoIPLink::getAllIpInterface(); + return SipTransport::getAllIpInterface(); } std::vector<std::string> ConfigurationManager::getAllIpInterfaceByName() { - return SIPVoIPLink::getAllIpInterfaceByName(); + return SipTransport::getAllIpInterfaceByName(); } std::map<std::string, std::string> ConfigurationManager::getShortcuts() @@ -439,23 +442,19 @@ void ConfigurationManager::setShortcuts( std::vector<std::map<std::string, std::string> > ConfigurationManager::getCredentials( const std::string& accountID) { - Account *account = Manager::instance().getAccount(accountID); + SIPAccount *account = dynamic_cast<SIPAccount*>(Manager::instance().getAccount(accountID)); std::vector<std::map<std::string, std::string> > credentialInformation; - if (!account or account->getType() != "SIP") + if (!account) return credentialInformation; - - SIPAccount *sipaccount = static_cast<SIPAccount *>(account); - return sipaccount->getCredentials(); + else + return account->getCredentials(); } void ConfigurationManager::setCredentials(const std::string& accountID, const std::vector<std::map<std::string, std::string> >& details) { - Account *account = Manager::instance().getAccount(accountID); - - if (account and account->getType() == "SIP") { - SIPAccount *sipaccount = static_cast<SIPAccount*>(account); - sipaccount->setCredentials(details); - } + SIPAccount *account = dynamic_cast<SIPAccount*>(Manager::instance().getAccount(accountID)); + if (account) + account->setCredentials(details); } diff --git a/daemon/src/dbus/dbusmanager.cpp b/daemon/src/dbus/dbusmanager.cpp index becd522679892b2a071910dc9c30c3e3c23223f7..9fe55663e90b155fdce1484a23248d87c977e09c 100644 --- a/daemon/src/dbus/dbusmanager.cpp +++ b/daemon/src/dbus/dbusmanager.cpp @@ -32,6 +32,7 @@ #include "dbusmanager.h" #include "global.h" #include "manager.h" +#include "logger.h" #include "instance.h" #include "callmanager.h" @@ -50,7 +51,7 @@ DBusManager::DBusManager() : callManager_(0) DBus::_init_threading(); DBus::default_dispatcher = &dispatcher_; - DBus::Connection sessionConnection = DBus::Connection::SessionBus(); + DBus::Connection sessionConnection(DBus::Connection::SessionBus()); sessionConnection.request_name("org.sflphone.SFLphone"); callManager_ = new CallManager(sessionConnection); @@ -58,7 +59,7 @@ DBusManager::DBusManager() : callManager_(0) instanceManager_ = new Instance(sessionConnection); #ifdef USE_NETWORKMANAGER - DBus::Connection systemConnection = DBus::Connection::SystemBus(); + DBus::Connection systemConnection(DBus::Connection::SystemBus()); networkManager_ = new NetworkManager(systemConnection, "/org/freedesktop/NetworkManager", ""); #endif @@ -86,7 +87,7 @@ void DBusManager::exec() ERROR("%s: %s, exiting\n", err.name(), err.what()); ::exit(EXIT_FAILURE); } catch (const std::exception &err) { - ERROR("%s: %s, exiting\n", err.what()); + ERROR("%s: exiting\n", err.what()); ::exit(EXIT_FAILURE); } } @@ -100,7 +101,7 @@ DBusManager::exit() ERROR("%s: %s, exiting\n", err.name(), err.what()); ::exit(EXIT_FAILURE); } catch (const std::exception &err) { - ERROR("%s: %s, exiting\n", err.what()); + ERROR("%s: exiting\n", err.what()); ::exit(EXIT_FAILURE); } } diff --git a/daemon/src/dbus/networkmanager.cpp b/daemon/src/dbus/networkmanager.cpp index 9f7288069262b05e94ad927d373d821a100c6235..7333066a751f69464c8ce42d8f947560b37665f1 100644 --- a/daemon/src/dbus/networkmanager.cpp +++ b/daemon/src/dbus/networkmanager.cpp @@ -29,34 +29,37 @@ */ #include "networkmanager.h" - -#include <iostream> - -#include "global.h" -#include "instance.h" #include "../manager.h" +#include "array_size.h" +#include "logger.h" -const std::string NetworkManager::statesString[5] = {"unknown", "asleep", "connecting", "connected", "disconnected"}; +namespace { + const char *stateAsString(uint32_t state) + { + static const char * STATES[] = {"unknown", "asleep", "connecting", + "connected", "disconnected"}; -std::string NetworkManager::stateAsString(const uint32_t& state) -{ - return statesString[state]; + const size_t idx = state < ARRAYSIZE(STATES) ? state : 0; + return STATES[idx]; + } } -void NetworkManager::StateChanged(const uint32_t& state) +void NetworkManager::StateChanged(const uint32_t &state) { - WARN("Network state changed: %s", stateAsString(state).c_str()); + WARN("Network state changed: %s", stateAsString(state)); } -void NetworkManager::PropertiesChanged(const std::map< std::string, ::DBus::Variant >& argin0) +void NetworkManager::PropertiesChanged(const std::map<std::string, ::DBus::Variant> &argin0) { - const std::map< std::string, ::DBus::Variant >::const_iterator iter = argin0.begin(); - - WARN("Properties changed: %s", iter->first.c_str()); - + WARN("Properties changed: "); + for (std::map<std::string, ::DBus::Variant>::const_iterator iter = argin0.begin(); + iter != argin0.end(); ++iter) + WARN("%s", iter->first.c_str()); Manager::instance().registerAccounts(); } -NetworkManager::NetworkManager(DBus::Connection& connection, const DBus::Path& dbus_path, const char* destination) : DBus::ObjectProxy(connection, dbus_path, destination) -{ -} +NetworkManager::NetworkManager(DBus::Connection &connection, + const DBus::Path &dbus_path, + const char *destination) : + DBus::ObjectProxy(connection, dbus_path, destination) +{} diff --git a/daemon/src/dbus/networkmanager.h b/daemon/src/dbus/networkmanager.h index 4bc5ca48eefc831e46cb8f454b3bf9459403c703..252ec739a46be807b4b0d80a729bcba48a0808b9 100644 --- a/daemon/src/dbus/networkmanager.h +++ b/daemon/src/dbus/networkmanager.h @@ -28,8 +28,8 @@ * as that of the covered work. */ -#ifndef NETWORKMANAGER_H -#define NETWORKMANAGER_H +#ifndef NETWORKMANAGER_H_ +#define NETWORKMANAGER_H_ #pragma GCC diagnostic ignored "-Wignored-qualifiers" #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -37,17 +37,16 @@ #pragma GCC diagnostic warning "-Wignored-qualifiers" #pragma GCC diagnostic warning "-Wunused-parameter" -class NetworkManager - : public org::freedesktop::NetworkManager_proxy, - public DBus::IntrospectableProxy, - public DBus::ObjectProxy { +class NetworkManager : public org::freedesktop::NetworkManager_proxy, + public DBus::IntrospectableProxy, + // cppcheck-suppress unusedFunction + public DBus::ObjectProxy { public: + NetworkManager(DBus::Connection &, const DBus::Path &, const char*); + void StateChanged(const uint32_t &state); + void PropertiesChanged(const std::map<std::string, ::DBus::Variant> &argin0); - NetworkManager(DBus::Connection&, const DBus::Path&, const char*); - void StateChanged(const uint32_t& state); - void PropertiesChanged(const std::map< std::string, ::DBus::Variant >& argin0); - std::string stateAsString(const uint32_t& state); - + private: enum NMState { NM_STATE_UNKNOWN = 0, NM_STATE_ASLEEP, @@ -55,8 +54,6 @@ class NetworkManager NM_STATE_CONNECTED, NM_STATE_DISCONNECTED }; - - static const std::string statesString[5]; }; #endif diff --git a/daemon/src/eventthread.cpp b/daemon/src/eventthread.cpp index f4e76bbd9b4e98c135fcbab401cc685e779f8440..36fbd7be5cf279315a8127b6dd5b2d6ff90fa40a 100644 --- a/daemon/src/eventthread.cpp +++ b/daemon/src/eventthread.cpp @@ -31,18 +31,13 @@ #include "eventthread.h" #include "voiplink.h" -EventThread::EventThread(VoIPLink *link) : Thread(), link_(link) -{ - setCancel(cancelDeferred); -} - -EventThread::~EventThread() { - ost::Thread::terminate(); -} +EventThread::EventThread(VoIPLink *link) : ost::Thread(), link_(link) +{} void EventThread::run() { - while (!testCancel()) - link_->getEvent(); + while (link_->getEvent()) + ; // noop + ost::Thread::exit(); } diff --git a/daemon/src/eventthread.h b/daemon/src/eventthread.h index 8d1b20e5ddb26fd6c84b81af1bcae6034d1bb895..af3aee58efb191202860f86bbe79fe7f3d4a2cb8 100644 --- a/daemon/src/eventthread.h +++ b/daemon/src/eventthread.h @@ -31,7 +31,7 @@ #ifndef EVENT_THREAD_H_ #define EVENT_THREAD_H_ -#include <cc++/thread.h> +#include "cc_thread.h" #include "noncopyable.h" class VoIPLink; @@ -44,8 +44,7 @@ class VoIPLink; class EventThread : public ost::Thread { public: EventThread(VoIPLink* link); - ~EventThread(); - virtual void run(); + void run(); private: NON_COPYABLE(EventThread); diff --git a/daemon/src/fileutils.cpp b/daemon/src/fileutils.cpp index e03ff6df20cceee5df27e464d6a757e0c042f702..7a7240abd2c8cce14e1fd14a95f15d872f11762f 100644 --- a/daemon/src/fileutils.cpp +++ b/daemon/src/fileutils.cpp @@ -29,9 +29,33 @@ */ #include <libgen.h> +#include <dirent.h> +#include <sys/stat.h> +#include <fstream> #include <cstdlib> +#include <signal.h> +#include <string> +#include <sstream> +#include <iostream> +#include "fileutils.h" namespace fileutils { +// returns true if directory exists +bool check_dir(const char *path) +{ + DIR *dir = opendir(path); + + if (!dir) { // doesn't exist + if (mkdir(path, 0755) != 0) { // couldn't create the dir + perror(path); + return false; + } + } else + closedir(dir); + + return true; +} + static char *program_dir = NULL; void set_program_dir(char *program_path) @@ -44,4 +68,46 @@ const char *get_program_dir() return program_dir; } +bool create_pidfile() +{ + const char * const xdg_env = XDG_CACHE_HOME; + std::string path = xdg_env ? xdg_env : std::string(HOMEDIR) + DIR_SEPARATOR_STR ".cache/"; + + if (!check_dir(path.c_str())) + return false; + + path += "sflphone"; + + if (!check_dir(path.c_str())) + return false; + + std::string pidfile = path + "/" PIDFILE; + std::ifstream is(pidfile.c_str()); + + if (is) { + // PID file exists. Check if the former process is still alive or + // not. If alive, give user a hint. + int oldPid; + is >> oldPid; + + if (kill(oldPid, 0) == 0) { + // Use cerr because logging has not been initialized + std::cerr << "There is already a sflphoned daemon running in " << + "the system. Starting Failed." << std::endl; + return false; + } + } + + // write pid file + std::ofstream os(pidfile.c_str()); + + if (!os) { + perror(pidfile.c_str()); + return false; + } else { + os << getpid(); + } + + return true; +} } diff --git a/daemon/src/fileutils.h b/daemon/src/fileutils.h index c7188cb0d70242943b48b4ce641c41be96c7157b..c513daed12d902efc88f53e81fa67ad865fe7c63 100644 --- a/daemon/src/fileutils.h +++ b/daemon/src/fileutils.h @@ -28,12 +28,24 @@ * as that of the covered work. */ -#ifndef __FILEUTILS_H__ -#define __FILEUTILS_H__ +#ifndef FILEUTILS_H_ +#define FILEUTILS_H_ + +#define HOMEDIR (getenv ("HOME")) /** Home directory */ +#define XDG_DATA_HOME (getenv ("XDG_DATA_HOME")) +#define XDG_CONFIG_HOME (getenv ("XDG_CONFIG_HOME")) +#define XDG_CACHE_HOME (getenv ("XDG_CACHE_HOME")) +#define PIDFILE "sfl.pid" + + +#define DIR_SEPARATOR_STR "/" // Directory separator char +#define DIR_SEPARATOR_CH = '/' // Directory separator string namespace fileutils { + bool check_dir(const char *path); void set_program_dir(char *program_path); const char *get_program_dir(); + bool create_pidfile(); } -#endif // __FILEUTILS_H__ +#endif // FILEUTILS_H_ diff --git a/daemon/src/global.h b/daemon/src/global.h index ef8b085fe4dcce223cc4c254cd4007aae3149ceb..fd766c1a2448837b9d89b6bc2be473377a68a5c6 100644 --- a/daemon/src/global.h +++ b/daemon/src/global.h @@ -33,33 +33,18 @@ #ifndef __GLOBAL_H__ #define __GLOBAL_H__ -#include <stdio.h> +#include <cstdio> #include <libintl.h> #include <locale.h> #include <string> -#include <stdlib.h> +#include <cstdlib> #include <sstream> #include <map> #include <vector> -#include "logger.h" -#define HOMEDIR (getenv ("HOME")) /** Home directory */ -#define XDG_DATA_HOME (getenv ("XDG_DATA_HOME")) -#define XDG_CONFIG_HOME (getenv ("XDG_CONFIG_HOME")) -#define XDG_CACHE_HOME (getenv ("XDG_CACHE_HOME")) const char * const ZRTP_ZID_FILENAME = "sfl.zid"; -//useful typedefs. -typedef signed short SINT16; -typedef signed int SINT32; - -#define PIDFILE "sfl.pid" - -typedef short SFLDataFormat; - -#define SIZEBUF 400000 /** About 12 sec of buffering at 8000 Hz*/ - -#define ALSA_DFT_CARD_ID 0 /** Index of the default soundcard */ +#define ALSA_DFT_CARD_ID 0 /** Index of the default soundcard */ #define PCM_PLUGHW "plughw" /** Alsa plugin */ #define PCM_DEFAULT "default" /** Default ALSA plugin */ @@ -121,8 +106,4 @@ enum { /** The struct to reflect the order the user wants to use the codecs */ typedef std::vector<int> CodecOrder; -#define IP2IP_PROFILE "IP2IP" -#define DIR_SEPARATOR_STR "/" // Directory separator char -#define DIR_SEPARATOR_CH = '/' /** Directory separator string */ - #endif // __GLOBAL_H__ diff --git a/daemon/src/history/history.cpp b/daemon/src/history/history.cpp index 16482fde4656b9ef4b1dd872780aec13e57ce5bb..d812d04e3c88f47c6424c7c25a61beb82932340c 100644 --- a/daemon/src/history/history.cpp +++ b/daemon/src/history/history.cpp @@ -33,29 +33,18 @@ #include "history.h" #include <cerrno> #include <algorithm> +#include <fstream> #include <sys/stat.h> // for mkdir #include <ctime> -#include "global.h" +#include "fileutils.h" #include "logger.h" #include "call.h" -namespace { - int oldestAllowed(int days) - { - time_t currentTimestamp; - time(¤tTimestamp); - // Number of seconds in one day: 60 sec/min x 60 min/hr x 24hr/day - static const int DAY_UNIX_TIMESTAMP = 60 * 60 * 24; - return static_cast<int>(currentTimestamp) - (days * DAY_UNIX_TIMESTAMP); - } - - using std::map; - using std::string; - using std::vector; -} +using std::map; +using std::string; +using std::vector; -History::History() : - items_(), path_("") +History::History() : items_(), path_("") {} bool History::load(int limit) @@ -75,7 +64,7 @@ bool History::load(int limit) bool History::save() { - DEBUG("History: Saving history in XDG directory: %s", path_.c_str()); + DEBUG("Saving history in XDG directory: %s", path_.c_str()); ensurePath(); std::sort(items_.begin(), items_.end()); std::ofstream outfile(path_.c_str()); @@ -110,7 +99,7 @@ void History::ensurePath() if (mkdir(userdata.data(), 0755) != 0) { // If directory creation failed if (errno != EEXIST) { - DEBUG("History: Cannot create directory: %m"); + DEBUG("Cannot create directory: %m"); return; } } @@ -137,7 +126,7 @@ void History::setPath(const std::string &path) void History::addCall(Call *call, int limit) { if (!call) { - ERROR("History: Call is NULL, ignoring"); + ERROR("Call is NULL, ignoring"); return; } call->time_stop(); diff --git a/daemon/src/iax/iaxaccount.cpp b/daemon/src/iax/iaxaccount.cpp index 5c653c037a5dee506c1df23e2cf296f55013e1b0..411330db50981217b27951c2b3a57d94f5d60f95 100644 --- a/daemon/src/iax/iaxaccount.cpp +++ b/daemon/src/iax/iaxaccount.cpp @@ -31,30 +31,23 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #include "iaxaccount.h" #include "iaxvoiplink.h" +#include "logger.h" #include "manager.h" +#include "config/yamlnode.h" +#include "config/yamlemitter.h" IAXAccount::IAXAccount(const std::string& accountID) - : Account(accountID, "iax2"), password_(), - link_(new IAXVoIPLink(accountID)) + : Account(accountID, "iax2"), password_(), link_(accountID) {} - -IAXAccount::~IAXAccount() -{ - delete link_; -} - -void IAXAccount::serialize(Conf::YamlEmitter *emitter) +void IAXAccount::serialize(Conf::YamlEmitter &emitter) { - if (emitter == NULL) { - ERROR("IAXAccount: Error: emitter is NULL in serialize"); - return; - } - Conf::MappingNode accountmap(NULL); Conf::ScalarNode id(accountID_); @@ -69,44 +62,39 @@ void IAXAccount::serialize(Conf::YamlEmitter *emitter) Conf::ScalarNode codecs(codecStr_); Conf::ScalarNode displayName(displayName_); - accountmap.setKeyValue(aliasKey, &alias); - accountmap.setKeyValue(typeKey, &type); - accountmap.setKeyValue(idKey, &id); - accountmap.setKeyValue(usernameKey, &username); - accountmap.setKeyValue(passwordKey, &password); - accountmap.setKeyValue(hostnameKey, &hostname); - accountmap.setKeyValue(accountEnableKey, &enable); - accountmap.setKeyValue(mailboxKey, &mailbox); + accountmap.setKeyValue(ALIAS_KEY, &alias); + accountmap.setKeyValue(TYPE_KEY, &type); + accountmap.setKeyValue(ID_KEY, &id); + accountmap.setKeyValue(USERNAME_KEY, &username); + accountmap.setKeyValue(PASSWORD_KEY, &password); + accountmap.setKeyValue(HOSTNAME_KEY, &hostname); + accountmap.setKeyValue(ACCOUNT_ENABLE_KEY, &enable); + accountmap.setKeyValue(MAILBOX_KEY, &mailbox); - accountmap.setKeyValue(displayNameKey, &displayName); - accountmap.setKeyValue(codecsKey, &codecs); + accountmap.setKeyValue(DISPLAY_NAME_KEY, &displayName); + accountmap.setKeyValue(CODECS_KEY, &codecs); try { - emitter->serializeAccount(&accountmap); + emitter.serializeAccount(&accountmap); } catch (const Conf::YamlEmitterException &e) { ERROR("ConfigTree: %s", e.what()); } } -void IAXAccount::unserialize(Conf::MappingNode *map) +void IAXAccount::unserialize(const Conf::MappingNode &map) { - if (map == NULL) { - ERROR("IAXAccount: Error: Map is NULL in unserialize"); - return; - } - - map->getValue(aliasKey, &alias_); - map->getValue(typeKey, &type_); - map->getValue(usernameKey, &username_); - map->getValue(passwordKey, &password_); - map->getValue(hostnameKey, &hostname_); - map->getValue(accountEnableKey, &enabled_); - map->getValue(mailboxKey, &mailBox_); - map->getValue(codecsKey, &codecStr_); + map.getValue(ALIAS_KEY, &alias_); + map.getValue(TYPE_KEY, &type_); + map.getValue(USERNAME_KEY, &username_); + map.getValue(PASSWORD_KEY, &password_); + map.getValue(HOSTNAME_KEY, &hostname_); + map.getValue(ACCOUNT_ENABLE_KEY, &enabled_); + map.getValue(MAILBOX_KEY, &mailBox_); + map.getValue(CODECS_KEY, &codecStr_); // Update codec list which one is used for SDP offer - setActiveCodecs(ManagerImpl::unserialize(codecStr_)); - map->getValue(displayNameKey, &displayName_); + setActiveCodecs(ManagerImpl::split_string(codecStr_)); + map.getValue(DISPLAY_NAME_KEY, &displayName_); } void IAXAccount::setAccountDetails(std::map<std::string, std::string> details) @@ -114,32 +102,32 @@ void IAXAccount::setAccountDetails(std::map<std::string, std::string> details) // Account setting common to SIP and IAX alias_ = details[CONFIG_ACCOUNT_ALIAS]; type_ = details[CONFIG_ACCOUNT_TYPE]; - username_ = details[USERNAME]; - hostname_ = details[HOSTNAME]; - password_ = details[PASSWORD]; + username_ = details[CONFIG_ACCOUNT_USERNAME]; + hostname_ = details[CONFIG_ACCOUNT_HOSTNAME]; + password_ = details[CONFIG_ACCOUNT_PASSWORD]; enabled_ = details[CONFIG_ACCOUNT_ENABLE] == "true"; mailBox_ = details[CONFIG_ACCOUNT_MAILBOX]; - displayName_ = details[DISPLAY_NAME]; - userAgent_ = details[USERAGENT]; + displayName_ = details[CONFIG_DISPLAY_NAME]; + userAgent_ = details[CONFIG_ACCOUNT_USERAGENT]; } std::map<std::string, std::string> IAXAccount::getAccountDetails() const { std::map<std::string, std::string> a; - a[ACCOUNT_ID] = accountID_; + a[CONFIG_ACCOUNT_ID] = accountID_; a[CONFIG_ACCOUNT_ALIAS] = alias_; a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? "true" : "false"; a[CONFIG_ACCOUNT_TYPE] = type_; - a[HOSTNAME] = hostname_; - a[USERNAME] = username_; - a[PASSWORD] = password_; + a[CONFIG_ACCOUNT_HOSTNAME] = hostname_; + a[CONFIG_ACCOUNT_USERNAME] = username_; + a[CONFIG_ACCOUNT_PASSWORD] = password_; a[CONFIG_ACCOUNT_MAILBOX] = mailBox_; RegistrationState state(registrationState_); - a[REGISTRATION_STATUS] = mapStateNumberToString(state); - a[USERAGENT] = userAgent_; + a[CONFIG_ACCOUNT_REGISTRATION_STATUS] = mapStateNumberToString(state); + a[CONFIG_ACCOUNT_USERAGENT] = userAgent_; return a; } @@ -147,8 +135,8 @@ std::map<std::string, std::string> IAXAccount::getAccountDetails() const void IAXAccount::registerVoIPLink() { try { - link_->init(); - link_->sendRegister(this); + link_.init(); + link_.sendRegister(this); } catch (const VoipLinkException &e) { ERROR("IAXAccount: %s", e.what()); } @@ -158,8 +146,8 @@ void IAXAccount::unregisterVoIPLink() { try { - link_->sendUnregister(this); - link_->terminate(); + link_.sendUnregister(this); + link_.terminate(); } catch (const VoipLinkException &e) { ERROR("IAXAccount: %s", e.what()); } @@ -176,5 +164,5 @@ IAXAccount::loadConfig() VoIPLink* IAXAccount::getVoIPLink() { - return link_; + return &link_; } diff --git a/daemon/src/iax/iaxaccount.h b/daemon/src/iax/iaxaccount.h index 7df121d90c36d5f0251546aa6819ff8e632ec51b..35871972bb7051b5f26ebc04a99d7b99f55dce26 100644 --- a/daemon/src/iax/iaxaccount.h +++ b/daemon/src/iax/iaxaccount.h @@ -32,9 +32,7 @@ #define IAXACCOUNT_H #include "account.h" -#include "noncopyable.h" - -class IAXVoIPLink; +#include "iaxvoiplink.h" /** * @file: iaxaccount.h @@ -43,11 +41,9 @@ class IAXVoIPLink; class IAXAccount : public Account { public: IAXAccount(const std::string& accountID); - ~IAXAccount(); - - virtual void serialize(Conf::YamlEmitter *emitter); - virtual void unserialize(Conf::MappingNode *map); + virtual void serialize(Conf::YamlEmitter &emitter); + virtual void unserialize(const Conf::MappingNode &map); void setAccountDetails(std::map<std::string, std::string> details); @@ -67,10 +63,9 @@ class IAXAccount : public Account { } private: - NON_COPYABLE(IAXAccount); // Account login information: password std::string password_; - IAXVoIPLink *link_; + IAXVoIPLink link_; virtual VoIPLink* getVoIPLink(); }; diff --git a/daemon/src/iax/iaxcall.cpp b/daemon/src/iax/iaxcall.cpp index a1eb21ec93ac7f467f43094922af9eb1d4301402..488dec90815037e4a6cff917a090913637a734b2 100644 --- a/daemon/src/iax/iaxcall.cpp +++ b/daemon/src/iax/iaxcall.cpp @@ -29,8 +29,12 @@ * as that of the covered work. */ +#include <cstring> +#include <sys/socket.h> +#include <iax-client.h> #include "iaxcall.h" #include "iax2/frame.h" +#include "logger.h" #include "account.h" #include "manager.h" @@ -115,3 +119,8 @@ int IAXCall::getAudioCodec() const return -1; } } + +void IAXCall::answer() +{ + iax_answer(session); +} diff --git a/daemon/src/iax/iaxcall.h b/daemon/src/iax/iaxcall.h index b2822520398726543001c18ad02f581f2462f43e..d97b838d35cabb04b377ae3183b7262c5932303e 100644 --- a/daemon/src/iax/iaxcall.h +++ b/daemon/src/iax/iaxcall.h @@ -74,6 +74,7 @@ class IAXCall : public Call { int format; iax_session* session; private: + virtual void answer(); NON_COPYABLE(IAXCall); }; diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp index 1f926e7790c825f91303165cd438e9ada4c5f7fb..0f929f17ad339dd8a8f68d50ae14d5b271b6316e 100644 --- a/daemon/src/iax/iaxvoiplink.cpp +++ b/daemon/src/iax/iaxvoiplink.cpp @@ -33,22 +33,27 @@ #include "eventthread.h" #include "im/instant_messaging.h" #include "iaxaccount.h" +#include "logger.h" #include "manager.h" #include "hooks/urlhook.h" #include "audio/audiolayer.h" #include "audio/samplerateconverter.h" +#include "array_size.h" #include <cmath> #include <dlfcn.h> IAXVoIPLink::IAXVoIPLink(const std::string& accountID) : - evThread_(new EventThread(this)) - , regSession_(NULL) + regSession_(NULL) , nextRefreshStamp_(0) , mutexIAX_() + , decData_() + , resampledData_() + , encodedData_() , converter_(44100) , initDone_(false) , accountID_(accountID) + , evThread_(this) { srand(time(NULL)); // to get random number for RANDOM_PORT } @@ -56,8 +61,7 @@ IAXVoIPLink::IAXVoIPLink(const std::string& accountID) : IAXVoIPLink::~IAXVoIPLink() { - delete evThread_; - + handlingEvents_ = false; regSession_ = NULL; // shall not delete it // XXX: but why? terminate(); } @@ -70,7 +74,8 @@ IAXVoIPLink::init() for (int port = IAX_DEFAULT_PORTNO, nbTry = 0; nbTry < 3 ; port = rand() % 64000 + 1024, nbTry++) { if (iax_init(port) >= 0) { - evThread_->start(); + handlingEvents_ = true; + evThread_.start(); initDone_ = true; break; } @@ -100,13 +105,14 @@ IAXVoIPLink::terminate() initDone_ = false; } -void +bool IAXVoIPLink::getEvent() { mutexIAX_.enter(); iax_event *event; while ((event = iax_get_event(0)) != NULL) { + // If we received an 'ACK', libiax2 tells apps to ignore them. if (event->etype == IAX_EVENT_NULL) { iax_event_free(event); @@ -115,10 +121,12 @@ IAXVoIPLink::getEvent() IAXCall *call = iaxFindCallBySession(event->session); - if (call) + if (call) { iaxHandleCallEvent(event, call); - else if (event->session && event->session == regSession_) + } + else if (event->session && event->session == regSession_) { iaxHandleRegReply(event); // This is a registration session, deal with it + } else // We've got an event before it's associated with any call iaxHandlePrecallEvent(event); @@ -133,7 +141,8 @@ IAXVoIPLink::getEvent() sendAudioFromMic(); // thread wait 3 millisecond - evThread_->sleep(3); + ost::Thread::sleep(3); + return handlingEvents_; } void @@ -163,7 +172,7 @@ IAXVoIPLink::sendAudioFromMic() continue; // Get bytes from micRingBuffer to data_from_mic - int bytes = Manager::instance().getMainBuffer()->getData(decData, bytesNeeded, currentCall->getCallId()); + int bytes = Manager::instance().getMainBuffer()->getData(decData_, bytesNeeded, currentCall->getCallId()); int samples = bytes / sizeof(SFLDataFormat); int compSize; @@ -172,20 +181,21 @@ IAXVoIPLink::sendAudioFromMic() SFLDataFormat *in; if (audioRate != mainBufferSampleRate) { - converter_.resample(decData, resampledData, audioRate, mainBufferSampleRate, samples); - in = resampledData; + converter_.resample(decData_, resampledData_, ARRAYSIZE(resampledData_), + audioRate, mainBufferSampleRate, samples); + in = resampledData_; outSamples = 0; } else { outSamples = samples; - in = decData; + in = decData_; } - compSize = audioCodec->encode(encodedData, in, DEC_BUFFER_SIZE); + compSize = audioCodec->encode(encodedData_, in, DEC_BUFFER_SIZE); if (currentCall->session and bytes > 0) { ost::MutexLock m(mutexIAX_); - if (iax_send_voice(currentCall->session, currentCall->format, encodedData, compSize, outSamples) == -1) + if (iax_send_voice(currentCall->session, currentCall->format, encodedData_, compSize, outSamples) == -1) ERROR("IAX: Error sending voice data."); } } @@ -255,14 +265,12 @@ IAXVoIPLink::newOutgoingCall(const std::string& id, const std::string& toUrl) void -IAXVoIPLink::answer(Call *c) +IAXVoIPLink::answer(Call *call) { - IAXCall* call = dynamic_cast<IAXCall*>(c); - Manager::instance().addStream(call->getCallId()); mutexIAX_.enter(); - iax_answer(call->session); + call->answer(); mutexIAX_.leave(); call->setState(Call::ACTIVE); @@ -274,8 +282,6 @@ IAXVoIPLink::answer(Call *c) void IAXVoIPLink::hangup(const std::string& id) { - DEBUG("IAXVoIPLink: Hangup"); - IAXCall* call = getIAXCall(id); if (call == NULL) @@ -296,8 +302,6 @@ IAXVoIPLink::hangup(const std::string& id) void IAXVoIPLink::peerHungup(const std::string& id) { - DEBUG("IAXVoIPLink: Peer hung up"); - IAXCall* call = getIAXCall(id); if (call == NULL) @@ -396,21 +400,18 @@ IAXVoIPLink::carryingDTMFdigits(const std::string& id, char code) } void -IAXVoIPLink::sendTextMessage(sfl::InstantMessaging *module, - const std::string& callID, +IAXVoIPLink::sendTextMessage(const std::string& callID, const std::string& message, const std::string& /*from*/) { IAXCall* call = getIAXCall(callID); if (call) { - mutexIAX_.enter(); - module->send_iax_message(call->session, callID, message.c_str()); - mutexIAX_.leave(); + ost::MutexLock lock(mutexIAX_); + sfl::InstantMessaging::send_iax_message(call->session, callID, message.c_str()); } } - std::string IAXVoIPLink::getCurrentCodecName(Call *c) const { @@ -419,7 +420,6 @@ IAXVoIPLink::getCurrentCodecName(Call *c) const return audioCodec ? audioCodec->getMimeSubtype() : ""; } - void IAXVoIPLink::iaxOutgoingInvite(IAXCall* call) { @@ -564,15 +564,16 @@ void IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, IAXCall* call) if (size > max) size = max; - int samples = audioCodec->decode(decData, data , size); + int samples = audioCodec->decode(decData_, data , size); int outSize = samples * sizeof(SFLDataFormat); - SFLDataFormat *out = decData; + SFLDataFormat *out = decData_; unsigned int audioRate = audioCodec->getClockRate(); if (audioRate != mainBufferSampleRate) { outSize = (double)outSize * (mainBufferSampleRate / audioRate); - converter_.resample(decData, resampledData, mainBufferSampleRate, audioRate, samples); - out = resampledData; + converter_.resample(decData_, resampledData_, ARRAYSIZE(resampledData_), + mainBufferSampleRate, audioRate, samples); + out = resampledData_; } Manager::instance().getMainBuffer()->putData(out, outSize, call->getCallId()); @@ -620,7 +621,7 @@ void IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event) // if peerNumber exist append it to the name string call->initRecFilename(std::string(event->ies.calling_number)); - Manager::instance().incomingCall(call, accountID_); + Manager::instance().incomingCall(*call, accountID_); format = call->getFirstMatchingFormat(event->ies.format, accountID_); diff --git a/daemon/src/iax/iaxvoiplink.h b/daemon/src/iax/iaxvoiplink.h index b8da8b90326376891537a65a6c6f8bf3ad38d00c..0d84828a8993f810805c100a2b426d043745892a 100644 --- a/daemon/src/iax/iaxvoiplink.h +++ b/daemon/src/iax/iaxvoiplink.h @@ -33,24 +33,20 @@ #define IAXVOIPLINK_H #include "voiplink.h" -#include <iax-client.h> #include "audio/codecs/audiocodec.h" // for DEC_BUFFER_SIZE -#include "global.h" +#include "sfl_types.h" #include "noncopyable.h" #include "audio/samplerateconverter.h" +#include "eventthread.h" -namespace sfl { -class InstantMessaging; -} +#include <iax-client.h> -class EventThread; class IAXCall; +class IAXAccount; class AudioCodec; class AudioLayer; -class IAXAccount; - /** * @file iaxvoiplink.h * @brief VoIPLink contains a thread that listen to external events @@ -66,7 +62,7 @@ class IAXVoIPLink : public VoIPLink { /** * Listen to events sent by the call manager ( asterisk, etc .. ) */ - void getEvent(); + bool getEvent(); /** * Init the voip link @@ -76,7 +72,7 @@ class IAXVoIPLink : public VoIPLink { /** * Terminate a voip link by clearing the call list */ - virtual void terminate(); + void terminate(); /** * Send out registration @@ -120,7 +116,7 @@ class IAXVoIPLink : public VoIPLink { * Cancel a call * @param id The ID of the call */ - virtual void cancel(const std::string& id UNUSED) {} + virtual void cancel(const std::string& /*id*/) {} /** * Put a call on hold @@ -167,7 +163,7 @@ class IAXVoIPLink : public VoIPLink { virtual void carryingDTMFdigits(const std::string& id, char code); - virtual void sendTextMessage(sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from); + virtual void sendTextMessage(const std::string& callID, const std::string& message, const std::string& from); /** * Return the codec protocol used for this call @@ -238,9 +234,6 @@ class IAXVoIPLink : public VoIPLink { */ void iaxOutgoingInvite(IAXCall* call); - /** Threading object */ - EventThread* evThread_; - /** registration session : 0 if not register */ iax_session* regSession_; @@ -254,9 +247,10 @@ class IAXVoIPLink : public VoIPLink { ost::Mutex mutexIAX_; /** encoder/decoder/resampler buffers */ - SFLDataFormat decData[DEC_BUFFER_SIZE]; - SFLDataFormat resampledData[DEC_BUFFER_SIZE]; - unsigned char encodedData[DEC_BUFFER_SIZE]; + SFLDataFormat decData_[DEC_BUFFER_SIZE]; +#warning FIXME: resampled buffer should be resized as appropriate + SFLDataFormat resampledData_[DEC_BUFFER_SIZE * 4]; + unsigned char encodedData_[DEC_BUFFER_SIZE]; /** Sample rate converter object */ SamplerateConverter converter_; @@ -268,6 +262,11 @@ class IAXVoIPLink : public VoIPLink { bool initDone_; const std::string accountID_; + + /** + * Threading object + */ + EventThread evThread_; }; #endif diff --git a/daemon/src/im/instant_messaging.cpp b/daemon/src/im/instant_messaging.cpp index 8c4de04741019cb3d66e5e1755d76d244c31b216..9b86d996538871454e78bcd3e02a4395d9cdc650 100644 --- a/daemon/src/im/instant_messaging.cpp +++ b/daemon/src/im/instant_messaging.cpp @@ -33,9 +33,9 @@ #include "logger.h" #include "expat.h" -namespace sfl { - -static void XMLCALL startElementCallback(void *userData, const char *name, const char **atts) +namespace { +void XMLCALL +startElementCallback(void *userData, const char *name, const char **atts) { if (strcmp(name, "entry")) return; @@ -45,13 +45,15 @@ static void XMLCALL startElementCallback(void *userData, const char *name, const for (const char **att = atts; *att; att += 2) entry.insert(std::pair<std::string, std::string> (*att, *(att+1))); - (static_cast<sfl::InstantMessaging::UriList *>(userData))->push_back(entry); + static_cast<sfl::InstantMessaging::UriList *>(userData)->push_back(entry); } -static void XMLCALL endElementCallback(void * /*userData*/, const char * /*name*/) +void XMLCALL endElementCallback(void * /*userData*/, const char * /*name*/) {} +} // end anonymous namespace -bool InstantMessaging::saveMessage(const std::string& message, const std::string& author, const std::string& id, int mode) +namespace sfl { +bool InstantMessaging::saveMessage(const std::string &message, const std::string &author, const std::string &id, int mode) { std::ofstream File; std::string filename = "im:" + id; @@ -81,24 +83,22 @@ void InstantMessaging::sip_send(pjsip_inv_session *session, const std::string& i return; } - const pj_str_t type = pj_str((char*)"text"); - - const pj_str_t subtype = pj_str((char*)"plain"); + const pj_str_t type = pj_str((char*) "text"); + const pj_str_t subtype = pj_str((char*) "plain"); pj_str_t message = pj_str((char*) text.c_str()); tdata->msg->body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &message); pjsip_dlg_send_request(dialog, tdata, -1, NULL); - pjsip_dlg_dec_lock(dialog); saveMessage(text, "Me", id); } -void InstantMessaging::send_sip_message(pjsip_inv_session *session, const std::string& id, const std::string& message) +void InstantMessaging::send_sip_message(pjsip_inv_session *session, const std::string &id, const std::string &message) { - std::vector<std::string> msgs = split_message(message); + std::vector<std::string> msgs(split_message(message)); std::vector<std::string>::const_iterator iter; for (iter = msgs.begin(); iter != msgs.end(); ++iter) @@ -106,9 +106,9 @@ void InstantMessaging::send_sip_message(pjsip_inv_session *session, const std::s } -void InstantMessaging::send_iax_message(iax_session* session, const std::string& /* id */, const std::string& message) +void InstantMessaging::send_iax_message(iax_session *session, const std::string &/* id */, const std::string &message) { - std::vector<std::string> msgs = split_message(message); + std::vector<std::string> msgs(split_message(message)); std::vector<std::string>::const_iterator iter; for (iter = msgs.begin(); iter != msgs.end(); ++iter) @@ -119,7 +119,7 @@ void InstantMessaging::send_iax_message(iax_session* session, const std::string& std::vector<std::string> InstantMessaging::split_message(std::string text) { std::vector<std::string> messages; - size_t len = getMessageMaximumSize(); + size_t len = MAXIMUM_MESSAGE_LENGTH; while (text.length() > len - 2) { messages.push_back(text.substr(len - 2) + "\n\n"); @@ -131,11 +131,11 @@ std::vector<std::string> InstantMessaging::split_message(std::string text) return messages; } -std::string InstantMessaging::generateXmlUriList(UriList& list) +std::string InstantMessaging::generateXmlUriList(UriList &list) { std::string xmlbuffer = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">" - "<list>"; + "<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">" + "<list>"; for (UriList::iterator iter = list.begin(); iter != list.end(); ++iter) xmlbuffer += "<entry uri=" + (*iter)[sfl::IM_XML_URI] + " cp:copyControl=\"to\" />"; @@ -144,7 +144,8 @@ std::string InstantMessaging::generateXmlUriList(UriList& list) } -InstantMessaging::UriList InstantMessaging::parseXmlUriList(std::string& urilist) +InstantMessaging::UriList +InstantMessaging::parseXmlUriList(const std::string &urilist) { InstantMessaging::UriList list; @@ -161,27 +162,22 @@ InstantMessaging::UriList InstantMessaging::parseXmlUriList(std::string& urilist return list; } -std::string InstantMessaging::appendUriList(std::string text, UriList& list) +std::string InstantMessaging::appendUriList(const std::string &text, UriList& list) { - return - "--boundary Content-Type: text/plain" + - text + - "--boundary Content-Type: application/resource-lists+xml" + - "Content-Disposition: recipient-list" + - generateXmlUriList(list) + - "--boundary--"; + return "--boundary Content-Type: text/plain" + text + + "--boundary Content-Type: application/resource-lists+xml" + + "Content-Disposition: recipient-list" + generateXmlUriList(list) + + "--boundary--"; } -std::string InstantMessaging::findTextUriList(std::string& text) +std::string InstantMessaging::findTextUriList(const std::string &text) { - std::string ctype = "Content-Type: application/resource-lists+xml"; - std::string cdispo = "Content-Disposition: recipient-list"; - std::string boundary = ("--boundary--"); + const std::string ctype("Content-Type: application/resource-lists+xml"); + const std::string cdispo("Content-Disposition: recipient-list"); + const std::string boundary("--boundary--"); // init position pointer size_t pos = 0; - size_t begin = 0; - size_t end = 0; // find the content type if ((pos = text.find(ctype)) == std::string::npos) @@ -192,32 +188,30 @@ std::string InstantMessaging::findTextUriList(std::string& text) throw InstantMessageException("Could not find Content-Disposition tag while parsing sip message for recipient-list"); // xml content start after content disposition tag (plus \n\n) - begin = pos+cdispo.size(); + const size_t begin = pos + cdispo.size(); // find final boundary + size_t end; if ((end = text.find(boundary, begin)) == std::string::npos) throw InstantMessageException("Could not find final \"boundary\" while parsing sip message for recipient-list"); - return text.substr(begin, end-begin); + return text.substr(begin, end - begin); } -std::string InstantMessaging::findTextMessage(std::string& text) +std::string InstantMessaging::findTextMessage(const std::string &text) { std::string ctype = "Content-Type: text/plain"; - - size_t pos = text.find(ctype); - + const size_t pos = text.find(ctype); if (pos == std::string::npos) throw InstantMessageException("Could not find Content-Type tag while parsing sip message for text"); - size_t begin = pos+ctype.size(); - - size_t end = text.find("--boundary", begin); + const size_t begin = pos + ctype.size(); + const size_t end = text.find("--boundary", begin); if (end == std::string::npos) throw InstantMessageException("Could not find end of text \"boundary\" while parsing sip message for text"); - return text.substr(begin, end-begin); + return text.substr(begin, end - begin); } diff --git a/daemon/src/im/instant_messaging.h b/daemon/src/im/instant_messaging.h index 17018b56ca0a03eef17d1620de1c4e51eb8b4267..7e9b0ee20f510369766692db90f2d843dad2ab2c 100644 --- a/daemon/src/im/instant_messaging.h +++ b/daemon/src/im/instant_messaging.h @@ -34,15 +34,13 @@ #include <string> #include <iostream> +#include <vector> #include <fstream> #include <pjsip.h> #include <pjlib.h> #include <pjsip_ua.h> #include <pjlib-util.h> -#include "call.h" -#include "sip/sipcall.h" - #include <map> #include <list> #include <stdexcept> @@ -66,18 +64,9 @@ class InstantMessageException : public std::runtime_error { std::runtime_error("InstantMessageException occured: " + str) {} }; -class InstantMessaging { - public: - typedef std::map <std::string, std::string> UriEntry; - typedef std::list <UriEntry> UriList; - - /** - * Return the maximum number if character for a single SIP MESSAGE. - * Longer messages should be splitted in several smaller messages using split_message - */ - static size_t getMessageMaximumSize() { - return MAXIMUM_MESSAGE_LENGTH; - } +namespace InstantMessaging { + typedef std::map<std::string, std::string> UriEntry; + typedef std::list<UriEntry> UriList; /* * Write the text message to the right file @@ -102,7 +91,6 @@ class InstantMessaging { std::vector<std::string> split_message(std::string); - /** * Generate Xml participant list for multi recipient based on RFC Draft 5365 * @@ -111,7 +99,7 @@ class InstantMessaging { * @return A string containing the full XML formated information to be included in the * sip instant message. */ - std::string generateXmlUriList(UriList& list); + std::string generateXmlUriList(UriList &list); /** * Parse the Urilist from a SIP Instant Message provided by a UriList service. @@ -120,7 +108,7 @@ class InstantMessaging { * * @return An UriList of UriEntry containing parsed XML information as a map. */ - UriList parseXmlUriList(std::string& urilist); + UriList parseXmlUriList(const std::string &urilist); /** * Format text message according to RFC 5365, append recipient-list to the message @@ -130,7 +118,7 @@ class InstantMessaging { * * @return formated text stored into a string to be included in sip MESSAGE */ - std::string appendUriList(std::string text, UriList& list); + std::string appendUriList(const std::string &text, UriList &list); /** * Retreive the xml formated uri list in formated text data according to RFC 5365 @@ -139,7 +127,7 @@ class InstantMessaging { * * @return A string containing the XML content */ - std::string findTextUriList(std::string& text); + std::string findTextUriList(const std::string &text); /** * Retrive the plain text message in formated text data according to RFC 5365 @@ -148,7 +136,7 @@ class InstantMessaging { * * @return A string containing the actual message */ - std::string findTextMessage(std::string& text); -}; + std::string findTextMessage(const std::string &text); +} // end namespace InstantMessaging } #endif // __INSTANT_MESSAGING_H_ diff --git a/daemon/src/logger.h b/daemon/src/logger.h index 353d4abb42a4105fe497b52c03af797bb4fde545..f40f00ce0242adbdff5c560c5cf4f7ba552a368d 100644 --- a/daemon/src/logger.h +++ b/daemon/src/logger.h @@ -28,8 +28,8 @@ * as that of the covered work. */ -#ifndef __LOGGER_H__ -#define __LOGGER_H__ +#ifndef LOGGER_H_ +#define LOGGER_H_ #include <syslog.h> @@ -41,10 +41,13 @@ void setDebugMode(bool); bool getDebugMode(); }; -#define ERROR(...) Logger::log(LOG_ERR, __VA_ARGS__) -#define WARN(...) Logger::log(LOG_WARNING, __VA_ARGS__) -#define INFO(...) Logger::log(LOG_INFO, __VA_ARGS__) -#define DEBUG(...) Logger::log(LOG_DEBUG, __VA_ARGS__) +#define LOGGER(M, LEVEL, ...) Logger::log(LEVEL, "%s:%d: " M, __FILE__, \ + __LINE__, ##__VA_ARGS__) + +#define ERROR(M, ...) LOGGER(M, LOG_ERR, ##__VA_ARGS__) +#define WARN(M, ...) LOGGER(M, LOG_WARNING, ##__VA_ARGS__) +#define INFO(M, ...) LOGGER(M, LOG_INFO, ##__VA_ARGS__) +#define DEBUG(M, ...) LOGGER(M, LOG_DEBUG, ##__VA_ARGS__) #define BLACK "\033[22;30m" #define RED "\033[22;31m" @@ -64,5 +67,5 @@ bool getDebugMode(); #define WHITE "\033[01;37m" #define END_COLOR "\033[0m" -#endif +#endif // LOGGER_H_ diff --git a/daemon/src/main.cpp b/daemon/src/main.cpp index 1d92cfbb5f7f7ca584a30db0e7d10b798059c4c8..bd7df2d020b79d1a8f496c66638edc68ce866a9e 100644 --- a/daemon/src/main.cpp +++ b/daemon/src/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> @@ -30,126 +30,116 @@ * as that of the covered work. */ -#include <libintl.h> -#include <cstring> +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <iostream> -#include <memory> // for auto_ptr -#include <string> -#include <dirent.h> -#include <sys/stat.h> -#include <cc++/common.h> -#include "global.h" +#include <getopt.h> #include "fileutils.h" - #include "dbus/dbusmanager.h" +#include "logger.h" #include "manager.h" -#include "audio/audiolayer.h" - -ost::CommandOptionNoArg console( - "console", "c", "Log in console (instead of syslog)" -); - -ost::CommandOptionNoArg debug( - "debug", "d", "Debug mode (more verbose)" -); +namespace { + void print_title() + { + std::cout << "SFLphone Daemon " << VERSION << + ", by Savoir-Faire Linux 2004-2012" << std::endl << + "http://www.sflphone.org/" << std::endl; + } -ost::CommandOptionNoArg help( - "help", "h", "Print help" -); + void print_usage() + { + std::cout << std::endl << + "-c, --console \t- Log in console (instead of syslog)" << std::endl << + "-d, --debug \t- Debug mode (more verbose)" << std::endl << + "-h, --help \t- Print help" << std::endl; + } -// returns true if directory exists -static bool check_dir(const char *path) -{ - DIR *dir = opendir(path); + // Parse command line arguments, setting debug options or printing a help + // message accordingly. + // returns true if we should quit (i.e. help was printed), false otherwise + bool parse_args(int argc, char *argv[]) + { + int consoleFlag = false; + int debugFlag = false; + int helpFlag = false; + int versionFlag = false; + static const struct option long_options[] = { + /* These options set a flag. */ + {"debug", no_argument, NULL, 'd'}, + {"console", no_argument, NULL, 'c'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {0, 0, 0, 0} /* Sentinel */ + }; + + while (true) { + /* getopt_long stores the option index here. */ + int option_index = 0; + int c = getopt_long(argc, argv, "dchv", long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) { + case 'd': + debugFlag = true; + break; + + case 'c': + consoleFlag = true; + break; + + case 'h': + case '?': + helpFlag = true; + break; + + case 'v': + versionFlag = true; + break; + + default: + break; + } + } - if (!dir) { // doesn't exist - if (mkdir(path, 0755) != 0) { // couldn't create the dir - perror(path); - return false; + bool quit = false; + if (helpFlag) { + print_usage(); + quit = true; + } else if (versionFlag) { + // We've always print the title/version, so we can just exit + quit = true; + } else { + Logger::setConsoleLog(consoleFlag); + Logger::setDebugMode(debugFlag); } - } else { - closedir(dir); + return quit; } - - return true; } -int -main(int argc, char **argv) +int main(int argc, char *argv []) { fileutils::set_program_dir(argv[0]); - // makeCommandOptionParse allocates the object with operator new, so - // auto_ptr is fine in this context. - // TODO: This should eventually be replaced with std::unique_ptr for C++0x - std::auto_ptr<ost::CommandOptionParse> args(ost::makeCommandOptionParse(argc, argv, "")); - - printf("SFLphone Daemon "VERSION", by Savoir-Faire Linux 2004-2011\n" \ - "http://www.sflphone.org/\n"); - - if (help.numSet) { - std::cerr << args->printUsage(); + print_title(); + if (parse_args(argc, argv)) return 0; - } else if (args->argsHaveError()) { - std::cerr << args->printErrors(); - std::cerr << args->printUsage(); - return 1; - } - - Logger::setConsoleLog(console.numSet); - Logger::setDebugMode(debug.numSet); - const char *xdg_env = XDG_CACHE_HOME; - std::string path = xdg_env ? xdg_env : std::string(HOMEDIR) + DIR_SEPARATOR_STR ".cache/"; - - if (!check_dir(path.c_str())) + if (!fileutils::create_pidfile()) return 1; - path = path + "sflphone"; - - if (!check_dir(path.c_str())) - return 1; - - std::string pidfile = path + "/" PIDFILE; - FILE *fp = fopen(pidfile.c_str(),"r"); - - if (fp) { // PID file exists. Check the former process still alive or not. If alive, give user a hint. - int oldPid; - - if (fscanf(fp, "%d", &oldPid) != 1) { - std::cerr << "Couldn't read pidfile " << pidfile << std::endl; - return 1; - } - - fclose(fp); - - if (kill(oldPid, 0) == 0) { - std::cerr << "There is already a sflphoned daemon running in the system. Starting Failed." << std::endl; - return 1; - } - } - - // write pid file - fp = fopen(pidfile.c_str(),"w"); - - if (!fp) { - perror(pidfile.c_str()); - return 1; - } else { - std::ostringstream pidstr; - pidstr << getpid(); - - fputs(pidstr.str().c_str() , fp); - fclose(fp); - } - try { - Manager::instance().init(); + Manager::instance().init(""); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { - std::cerr << "An exception occured when initializing the system." << std::endl; + std::cerr << "An exception occured when initializing " PACKAGE << + std::endl; return 1; } diff --git a/daemon/test/ringtonetest.h b/daemon/src/manager.cpp similarity index 52% rename from daemon/test/ringtonetest.h rename to daemon/src/manager.cpp index 8791629c2b0a20541d9533f87fe3a97c7eeed42f..b09fde7606417d2f2e8d59a30027dbf061d98627 100644 --- a/daemon/test/ringtonetest.h +++ b/daemon/src/manager.cpp @@ -1,6 +1,6 @@ /* - * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Savoir-Faire Linux Inc. - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * Author : Tristan Matthews <tristan.matthews@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,47 +28,11 @@ * as that of the covered work. */ -/* - * @file ringtonetest.cpp - * @brief Regroups unitary tests related to the ringtones. - * Check if the wave file has been successfully loaded - */ - -#ifndef _RINGTONE_TEST_ -#define _RINGTONE_TEST_ - -// Cppunit import -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/TestCaller.h> -#include <cppunit/TestCase.h> -#include <cppunit/TestSuite.h> - -#include <assert.h> - -// Application import #include "manager.h" -#include "audio/sound/audiofile.h" -#include "global.h" -#include "user_cfg.h" - -class RingtoneTest: public CppUnit::TestFixture { - - /* - * Use cppunit library macros to add unit test the factory - */ - CPPUNIT_TEST_SUITE(RingtoneTest); - CPPUNIT_TEST(testLoadWavefile); - CPPUNIT_TEST_SUITE_END(); - - public: - /* - * Unit tests related to the audio preferences - */ - void testLoadWavefile(); - -}; -/* Register our test module */ -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(RingtoneTest, "RingtoneTest"); -CPPUNIT_TEST_SUITE_REGISTRATION(RingtoneTest); -#endif +ManagerImpl& Manager::instance() +{ + // Meyers singleton + static ManagerImpl instance_; + return instance_; +} diff --git a/daemon/src/manager.h b/daemon/src/manager.h index 730b4d0b3f7376679745b83ed217119cb1b46a84..50d740679fdddb376934f7ddfcdaa537d8ee7d47 100644 --- a/daemon/src/manager.h +++ b/daemon/src/manager.h @@ -29,13 +29,16 @@ * as that of the covered work. */ -#ifndef SFLPHONE_MANAGER_H -#define SFLPHONE_MANAGER_H +#ifndef MANAGER_H_ +#define MANAGER_H_ -#include "utilspp/singleton.hpp" +// we could forward declare ManagerImpl BUT anyone who will call instance +// will need this include. #include "managerimpl.h" -typedef utilspp::SingletonHolder<ManagerImpl> Manager; +namespace Manager { + ManagerImpl& instance(); +} -#endif +#endif // MANAGER_H_ diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index 1f9f3283bbb85cc90c4a92b7195b5d28e6141c67..fc557935d3d1a9595b2d35b8fedcde81869ef337 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -32,24 +32,27 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif +#include "logger.h" #include "managerimpl.h" #include "account.h" #include "dbus/callmanager.h" #include "global.h" +#include "fileutils.h" #include "sip/sipaccount.h" #include "im/instant_messaging.h" #include "iax/iaxaccount.h" #include "numbercleaner.h" - +#include "config/yamlparser.h" +#include "config/yamlemitter.h" #include "audio/alsa/alsalayer.h" -#include "audio/pulseaudio/pulselayer.h" #include "audio/sound/tonelist.h" #include "audio/sound/audiofile.h" #include "audio/sound/dtmf.h" -#include "history/history.h" #include "sip/sipvoiplink.h" #include "iax/iaxvoiplink.h" #include "manager.h" @@ -59,9 +62,11 @@ #include "conference.h" #include <cerrno> +#include <algorithm> #include <ctime> #include <cstdlib> #include <iostream> +#include <tr1/functional> #include <iterator> #include <fstream> #include <sstream> @@ -71,82 +76,65 @@ ManagerImpl::ManagerImpl() : preferences(), voipPreferences(), addressbookPreference(), hookPreference(), audioPreference(), shortcutPreferences(), - hasTriedToRegister_(false), audioCodecFactory(), dbus_(), config_(), currentCallId_(), - currentCallMutex_(), audiodriver_(0), dtmfKey_(0), toneMutex_(), - telephoneTone_(0), audiofile_(0), speakerVolume_(0), micVolume_(0), - audioLayerMutex_(), waitingCall_(), waitingCallMutex_(), - nbIncomingWaitingCall_(0), path_(), callAccountMap_(), - callAccountMapMutex_(), IPToIPMap_(), accountMap_(), - mainBuffer_(), conferenceMap_(), history_(new History), - imModule_(new sfl::InstantMessaging) + hasTriedToRegister_(false), audioCodecFactory(), dbus_(), config_(), + currentCallId_(), currentCallMutex_(), audiodriver_(0), dtmfKey_(), + toneMutex_(), telephoneTone_(), audiofile_(), audioLayerMutex_(), + waitingCall_(), waitingCallMutex_(), nbIncomingWaitingCall_(0), path_(), + callAccountMap_(), callAccountMapMutex_(), IPToIPMap_(), accountMap_(), + mainBuffer_(), conferenceMap_(), history_() { // initialize random generator for call id srand(time(NULL)); } -// never call if we use only the singleton... -ManagerImpl::~ManagerImpl() -{ - delete imModule_; - delete history_; - delete audiofile_; -} - -void ManagerImpl::init(std::string config_file) +void ManagerImpl::init(const std::string &config_file) { - if (config_file.empty()) - config_file = getConfigFile(); - - path_ = config_file; - - DEBUG("Manager: configuration file path: %s", path_.c_str()); - - Conf::YamlParser *parser = NULL; + path_ = config_file.empty() ? createConfigFile() : config_file; + DEBUG("Configuration file path: %s", path_.c_str()); try { - parser = new Conf::YamlParser(path_.c_str()); - parser->serializeEvents(); - parser->composeEvents(); - parser->constructNativeData(); - } catch (Conf::YamlParserException &e) { - ERROR("Manager: %s", e.what()); + Conf::YamlParser parser(path_.c_str()); + parser.serializeEvents(); + parser.composeEvents(); + parser.constructNativeData(); + loadAccountMap(parser); + } catch (const Conf::YamlParserException &e) { + ERROR("%s", e.what()); fflush(stderr); - delete parser; - parser = NULL; + loadDefaultAccountMap(); } - loadAccountMap(parser); - delete parser; - - initVolume(); initAudioDriver(); { ost::MutexLock lock(audioLayerMutex_); if (audiodriver_) { - telephoneTone_ = new TelephoneTone(preferences.getZoneToneChoice(), audiodriver_->getSampleRate()); - dtmfKey_ = new DTMF(8000); + telephoneTone_.reset(new TelephoneTone(preferences.getZoneToneChoice(), audiodriver_->getSampleRate())); + dtmfKey_.reset(new DTMF(getMainBuffer()->getInternalSamplingRate())); } } - history_->load(preferences.getHistoryLimit()); + history_.load(preferences.getHistoryLimit()); registerAccounts(); } void ManagerImpl::terminate() { std::vector<std::string> callList(getCallList()); - DEBUG("Manager: Hangup %zu remaining call", callList.size()); + DEBUG("Hangup %zu remaining call", callList.size()); - for (std::vector<std::string>::iterator iter = callList.begin(); iter != callList.end(); ++iter) + for (std::vector<std::string>::iterator iter = callList.begin(); + iter != callList.end(); ++iter) hangupCall(*iter); - unloadAccountMap(); + saveConfig(); + + unregisterAllAccounts(); - delete SIPVoIPLink::instance(); - delete dtmfKey_; - delete telephoneTone_; - telephoneTone_ = NULL; + SIPVoIPLink::destroy(); + // Unload account map AFTER destroying + // the SIPVoIPLink, the link still needs the accounts for pjsip cleanup + unloadAccountMap(); ost::MutexLock lock(audioLayerMutex_); @@ -188,79 +176,58 @@ bool ManagerImpl::outgoingCall(const std::string& account_id, const std::string& conf_id) { if (call_id.empty()) { - DEBUG("Manager: New outgoing call abort, missing callid"); + DEBUG("New outgoing call abort, missing callid"); return false; } // Call ID must be unique if (not getAccountFromCall(call_id).empty()) { - ERROR("Manager: Error: Call id already exists in outgoing call"); + ERROR("Call id already exists in outgoing call"); return false; } - DEBUG("Manager: New outgoing call %s to %s", call_id.c_str(), to.c_str()); + DEBUG("New outgoing call %s to %s", call_id.c_str(), to.c_str()); stopTone(); std::string current_call_id(getCurrentCallId()); - std::string prefix; - if (hookPreference.getNumberEnabled()) - prefix = hookPreference.getNumberAddPrefix(); + std::string prefix(hookPreference.getNumberAddPrefix()); std::string to_cleaned(NumberCleaner::clean(to, prefix)); - static const char * const SIP_SCHEME = "sip:"; - static const char * const SIPS_SCHEME = "sips:"; - - bool IPToIP = to_cleaned.find(SIP_SCHEME) == 0 or - to_cleaned.find(SIPS_SCHEME) == 0; - - setIPToIPForCall(call_id, IPToIP); - // in any cases we have to detach from current communication if (hasCurrentCall()) { - DEBUG("Manager: Has current call (%s) put it onhold", current_call_id.c_str()); + DEBUG("Has current call (%s) put it onhold", current_call_id.c_str()); // if this is not a conferenceand this and is not a conference participant if (not isConference(current_call_id) and not isConferenceParticipant(current_call_id)) onHoldCall(current_call_id); else if (isConference(current_call_id) and not isConferenceParticipant(call_id)) - detachParticipant(Call::DEFAULT_ID, current_call_id); + detachParticipant(MainBuffer::DEFAULT_ID, current_call_id); } - if (IPToIP) { - DEBUG("Manager: Start IP2IP call"); - - /* We need to retrieve the sip voiplink instance */ - if (SIPVoIPLink::instance()->SIPNewIpToIpCall(call_id, to_cleaned)) { - switchCall(call_id); - return true; - } else - callFailure(call_id); - - return false; - } + DEBUG("Selecting account %s", account_id.c_str()); - DEBUG("Manager: Selecting account %s", account_id.c_str()); - - // Is this account exist + // fallback using the default sip account if the specied doesn't exist + std::string use_account_id = ""; if (!accountExists(account_id)) { - ERROR("Manager: Error: Account doesn't exist in new outgoing call"); - return false; + WARN("Account does not exist, trying with default SIP account"); + use_account_id = SIPAccount::IP2IP_PROFILE; + } + else { + use_account_id = account_id; } - if (!associateCallToAccount(call_id, account_id)) - WARN("Manager: Warning: Could not associate call id %s to account id %s", call_id.c_str(), account_id.c_str()); + associateCallToAccount(call_id, use_account_id); try { Call *call = getAccountLink(account_id)->newOutgoingCall(call_id, to_cleaned); - switchCall(call_id); call->setConfId(conf_id); } catch (const VoipLinkException &e) { callFailure(call_id); - ERROR("Manager: %s", e.what()); + ERROR("%s", e.what()); return false; } @@ -272,7 +239,7 @@ bool ManagerImpl::outgoingCall(const std::string& account_id, //THREAD=Main : for outgoing Call bool ManagerImpl::answerCall(const std::string& call_id) { - DEBUG("Manager: Answer call %s", call_id.c_str()); + DEBUG("Answer call %s", call_id.c_str()); // If sflphone is ringing stopTone(); @@ -285,28 +252,28 @@ bool ManagerImpl::answerCall(const std::string& call_id) Call *call = getAccountLink(account_id)->getCall(call_id); if (call == NULL) { - ERROR("Manager: Error: Call is null"); + ERROR("Call is NULL"); } // in any cases we have to detach from current communication if (hasCurrentCall()) { - DEBUG("Manager: Currently conversing with %s", current_call_id.c_str()); + DEBUG("Currently conversing with %s", current_call_id.c_str()); if (not isConference(current_call_id) and not isConferenceParticipant(current_call_id)) { - DEBUG("Manager: Answer call: Put the current call (%s) on hold", current_call_id.c_str()); + DEBUG("Answer call: Put the current call (%s) on hold", current_call_id.c_str()); onHoldCall(current_call_id); } else if (isConference(current_call_id) and not isConferenceParticipant(call_id)) { // if we are talking to a conference and we are answering an incoming call - DEBUG("Manager: Detach main participant from conference"); - detachParticipant(Call::DEFAULT_ID, current_call_id); + DEBUG("Detach main participant from conference"); + detachParticipant(MainBuffer::DEFAULT_ID, current_call_id); } } try { getAccountLink(account_id)->answer(call); - } catch (const VoipLinkException &e) { - ERROR("Manager: Error: %s", e.what()); + } catch (const std::runtime_error &e) { + ERROR("%s", e.what()); } // if it was waiting, it's waiting no more @@ -339,7 +306,7 @@ bool ManagerImpl::answerCall(const std::string& call_id) //THREAD=Main void ManagerImpl::hangupCall(const std::string& callId) { - DEBUG("Manager: Hangup call %s", callId.c_str()); + DEBUG("Hangup call %s", callId.c_str()); // store the current call id std::string currentCallId(getCurrentCallId()); @@ -347,11 +314,11 @@ void ManagerImpl::hangupCall(const std::string& callId) stopTone(); /* Broadcast a signal over DBus */ - DEBUG("Manager: Send DBUS call state change (HUNGUP) for id %s", callId.c_str()); + DEBUG("Send DBUS call state change (HUNGUP) for id %s", callId.c_str()); dbus_.getCallManager()->callStateChanged(callId, "HUNGUP"); if (not isValidCall(callId) and not isIPToIP(callId)) { - ERROR("Manager: Error: Could not hang up call, call not valid"); + ERROR("Could not hang up call, call not valid"); return; } @@ -376,8 +343,9 @@ void ManagerImpl::hangupCall(const std::string& callId) /* Direct IP to IP call */ try { Call * call = SIPVoIPLink::instance()->getCall(callId); - history_->addCall(call, preferences.getHistoryLimit()); + history_.addCall(call, preferences.getHistoryLimit()); SIPVoIPLink::instance()->hangup(callId); + saveHistory(); } catch (const VoipLinkException &e) { ERROR("%s", e.what()); } @@ -385,9 +353,10 @@ void ManagerImpl::hangupCall(const std::string& callId) std::string accountId(getAccountFromCall(callId)); VoIPLink *link = getAccountLink(accountId); Call * call = link->getCall(callId); - history_->addCall(call, preferences.getHistoryLimit()); + history_.addCall(call, preferences.getHistoryLimit()); link->hangup(callId); removeCallAccount(callId); + saveHistory(); } getMainBuffer()->stateInfo(); @@ -395,7 +364,7 @@ void ManagerImpl::hangupCall(const std::string& callId) bool ManagerImpl::hangupConference(const std::string& id) { - DEBUG("Manager: Hangup conference %s", id.c_str()); + DEBUG("Hangup conference %s", id.c_str()); ConferenceMap::iterator iter_conf = conferenceMap_.find(id); @@ -409,7 +378,7 @@ bool ManagerImpl::hangupConference(const std::string& id) iter != participants.end(); ++iter) hangupCall(*iter); } else { - ERROR("Manager: No such conference %s", id.c_str()); + ERROR("No such conference %s", id.c_str()); return false; } } @@ -425,7 +394,7 @@ bool ManagerImpl::hangupConference(const std::string& id) //THREAD=Main void ManagerImpl::onHoldCall(const std::string& callId) { - DEBUG("Manager: Put call %s on hold", callId.c_str()); + DEBUG("Put call %s on hold", callId.c_str()); stopTone(); @@ -439,14 +408,14 @@ void ManagerImpl::onHoldCall(const std::string& callId) std::string account_id(getAccountFromCall(callId)); if (account_id.empty()) { - DEBUG("Manager: Account ID %s or callid %s doesn't exists in call onHold", account_id.c_str(), callId.c_str()); + DEBUG("Account ID %s or callid %s doesn't exists in call onHold", account_id.c_str(), callId.c_str()); return; } getAccountLink(account_id)->onhold(callId); } } catch (const VoipLinkException &e) { - ERROR("Manager: Error: %s", e.what()); + ERROR("%s", e.what()); } // Unbind calls in main buffer @@ -471,7 +440,7 @@ void ManagerImpl::offHoldCall(const std::string& callId) std::string accountId; std::string codecName; - DEBUG("Manager: Put call %s off hold", callId.c_str()); + DEBUG("Put call %s off hold", callId.c_str()); stopTone(); @@ -482,10 +451,10 @@ void ManagerImpl::offHoldCall(const std::string& callId) if (hasCurrentCall()) { if (not isConference(currentCallId) and not isConferenceParticipant(currentCallId)) { - DEBUG("Manager: Has current call (%s), put on hold", currentCallId.c_str()); + DEBUG("Has current call (%s), put on hold", currentCallId.c_str()); onHoldCall(currentCallId); } else if (isConference(currentCallId) and not isConferenceParticipant(callId)) - detachParticipant(Call::DEFAULT_ID, currentCallId); + detachParticipant(MainBuffer::DEFAULT_ID, currentCallId); } bool isRec = false; @@ -496,7 +465,7 @@ void ManagerImpl::offHoldCall(const std::string& callId) /* Classic call, attached to an account */ accountId = getAccountFromCall(callId); - DEBUG("Manager: Setting offhold, Account %s, callid %s", accountId.c_str(), callId.c_str()); + DEBUG("Setting offhold, Account %s, callid %s", accountId.c_str(), callId.c_str()); Call * call = getAccountLink(accountId)->getCall(callId); @@ -616,7 +585,7 @@ void ManagerImpl::refuseCall(const std::string& id) Conference* ManagerImpl::createConference(const std::string& id1, const std::string& id2) { - DEBUG("Manager: Create conference with call %s and %s", id1.c_str(), id2.c_str()); + DEBUG("Create conference with call %s and %s", id1.c_str(), id2.c_str()); Conference* conf = new Conference; @@ -634,8 +603,8 @@ ManagerImpl::createConference(const std::string& id1, const std::string& id2) void ManagerImpl::removeConference(const std::string& conference_id) { - DEBUG("Manager: Remove conference %s", conference_id.c_str()); - DEBUG("Manager: number of participants: %u", conferenceMap_.size()); + DEBUG("Remove conference %s", conference_id.c_str()); + DEBUG("number of participants: %u", conferenceMap_.size()); ConferenceMap::iterator iter = conferenceMap_.find(conference_id); Conference* conf = 0; @@ -644,7 +613,7 @@ void ManagerImpl::removeConference(const std::string& conference_id) conf = iter->second; if (conf == NULL) { - ERROR("Manager: Error: Conference not found"); + ERROR("Conference not found"); return; } @@ -654,7 +623,7 @@ void ManagerImpl::removeConference(const std::string& conference_id) // We now need to bind the audio to the remain participant // Unbind main participant audio from conference - getMainBuffer()->unBindAll(Call::DEFAULT_ID); + getMainBuffer()->unBindAll(MainBuffer::DEFAULT_ID); ParticipantSet participants(conf->getParticipantList()); @@ -662,13 +631,13 @@ void ManagerImpl::removeConference(const std::string& conference_id) ParticipantSet::iterator iter_p = participants.begin(); if (iter_p != participants.end()) - getMainBuffer()->bindCallID(*iter_p, Call::DEFAULT_ID); + getMainBuffer()->bindCallID(*iter_p, MainBuffer::DEFAULT_ID); // Then remove the conference from the conference map if (conferenceMap_.erase(conference_id) == 1) - DEBUG("Manager: Conference %s removed successfully", conference_id.c_str()); + DEBUG("Conference %s removed successfully", conference_id.c_str()); else - ERROR("Manager: Error: Cannot remove conference: %s", conference_id.c_str()); + ERROR("Cannot remove conference: %s", conference_id.c_str()); delete conf; } @@ -753,11 +722,11 @@ bool ManagerImpl::isConferenceParticipant(const std::string& call_id) void ManagerImpl::addParticipant(const std::string& callId, const std::string& conferenceId) { - DEBUG("Manager: Add participant %s to %s", callId.c_str(), conferenceId.c_str()); + DEBUG("Add participant %s to %s", callId.c_str(), conferenceId.c_str()); ConferenceMap::iterator iter = conferenceMap_.find(conferenceId); if (iter == conferenceMap_.end()) { - ERROR("Manager: Error: Conference id is not valid"); + ERROR("Conference id is not valid"); return; } @@ -765,7 +734,7 @@ void ManagerImpl::addParticipant(const std::string& callId, const std::string& c Call *call = getAccountLink(currentAccountId)->getCall(callId); if (call == NULL) { - ERROR("Manager: Error: Call id is not valid"); + ERROR("Call id is not valid"); return; } @@ -775,7 +744,7 @@ void ManagerImpl::addParticipant(const std::string& callId, const std::string& c // detach from prior communication and switch to this conference if (current_call_id != callId) { if (isConference(current_call_id)) - detachParticipant(Call::DEFAULT_ID, current_call_id); + detachParticipant(MainBuffer::DEFAULT_ID, current_call_id); else onHoldCall(current_call_id); } @@ -813,7 +782,7 @@ void ManagerImpl::addParticipant(const std::string& callId, const std::string& c ParticipantSet participants(conf->getParticipantList()); if (participants.empty()) - ERROR("Manager: Error: Participant list is empty for this conference"); + ERROR("Participant list is empty for this conference"); // reset ring buffer for all conference participant // flush conference participants only @@ -821,7 +790,7 @@ void ManagerImpl::addParticipant(const std::string& callId, const std::string& c p != participants.end(); ++p) getMainBuffer()->flush(*p); - getMainBuffer()->flush(Call::DEFAULT_ID); + getMainBuffer()->flush(MainBuffer::DEFAULT_ID); // Connect stream addStream(callId); @@ -833,7 +802,7 @@ void ManagerImpl::addMainParticipant(const std::string& conference_id) std::string current_call_id(getCurrentCallId()); if (isConference(current_call_id)) - detachParticipant(Call::DEFAULT_ID, current_call_id); + detachParticipant(MainBuffer::DEFAULT_ID, current_call_id); else onHoldCall(current_call_id); } @@ -850,19 +819,19 @@ void ManagerImpl::addMainParticipant(const std::string& conference_id) for (ParticipantSet::const_iterator iter_p = participants.begin(); iter_p != participants.end(); ++iter_p) { - getMainBuffer()->bindCallID(*iter_p, Call::DEFAULT_ID); + getMainBuffer()->bindCallID(*iter_p, MainBuffer::DEFAULT_ID); // Reset ringbuffer's readpointers getMainBuffer()->flush(*iter_p); } - getMainBuffer()->flush(Call::DEFAULT_ID); + getMainBuffer()->flush(MainBuffer::DEFAULT_ID); if (conf->getState() == Conference::ACTIVE_DETACHED) conf->setState(Conference::ACTIVE_ATTACHED); else if (conf->getState() == Conference::ACTIVE_DETACHED_REC) conf->setState(Conference::ACTIVE_ATTACHED_REC); else - WARN("Manager: Warning: Invalid conference state while adding main participant"); + WARN("Invalid conference state while adding main participant"); dbus_.getCallManager()->conferenceChanged(conference_id, conf->getStateStr()); } @@ -873,19 +842,23 @@ void ManagerImpl::addMainParticipant(const std::string& conference_id) void ManagerImpl::joinParticipant(const std::string& callId1, const std::string& callId2) { - DEBUG("Manager: Join participants %s, %s", callId1.c_str(), callId2.c_str()); + DEBUG("Join participants %s, %s", callId1.c_str(), callId2.c_str()); + if (callId1 == callId2) { + ERROR("Cannot join participant %s to itself", callId1.c_str()); + return; + } std::map<std::string, std::string> call1Details(getCallDetails(callId1)); std::map<std::string, std::string> call2Details(getCallDetails(callId2)); std::string current_call_id(getCurrentCallId()); - DEBUG("Manager: Current Call ID %s", current_call_id.c_str()); + DEBUG("Current Call ID %s", current_call_id.c_str()); // detach from the conference and switch to this conference if ((current_call_id != callId1) and (current_call_id != callId2)) { // If currently in a conference if (isConference(current_call_id)) - detachParticipant(Call::DEFAULT_ID, current_call_id); + detachParticipant(MainBuffer::DEFAULT_ID, current_call_id); else onHoldCall(current_call_id); // currently in a call } @@ -897,7 +870,7 @@ void ManagerImpl::joinParticipant(const std::string& callId1, const std::string& Call *call1 = getAccountLink(currentAccountId1)->getCall(callId1); if (call1 == NULL) { - ERROR("Manager: Could not find call %s", callId1.c_str()); + ERROR("Could not find call %s", callId1.c_str()); return; } @@ -909,7 +882,7 @@ void ManagerImpl::joinParticipant(const std::string& callId1, const std::string& Call *call2 = getAccountLink(currentAccountId2)->getCall(callId2); if (call2 == NULL) { - ERROR("Manager: Could not find call %s", callId2.c_str()); + ERROR("Could not find call %s", callId2.c_str()); return; } @@ -918,7 +891,7 @@ void ManagerImpl::joinParticipant(const std::string& callId1, const std::string& // Process call1 according to its state std::string call1_state_str(call1Details.find("CALL_STATE")->second); - DEBUG("Manager: Process call %s state: %s", callId1.c_str(), call1_state_str.c_str()); + DEBUG("Process call %s state: %s", callId1.c_str(), call1_state_str.c_str()); if (call1_state_str == "HOLD") { conf->bindParticipant(callId1); @@ -934,11 +907,11 @@ void ManagerImpl::joinParticipant(const std::string& callId1, const std::string& conf->bindParticipant(callId1); answerCall(callId1); } else - WARN("Manager: Call state not recognized"); + WARN("Call state not recognized"); // Process call2 according to its state std::string call2_state_str(call2Details.find("CALL_STATE")->second); - DEBUG("Manager: Process call %s state: %s", callId2.c_str(), call2_state_str.c_str()); + DEBUG("Process call %s state: %s", callId2.c_str(), call2_state_str.c_str()); if (call2_state_str == "HOLD") { conf->bindParticipant(callId2); @@ -954,7 +927,7 @@ void ManagerImpl::joinParticipant(const std::string& callId1, const std::string& conf->bindParticipant(callId2); answerCall(callId2); } else - WARN("Manager: Call state not recognized"); + WARN("Call state not recognized"); // Switch current call id to this conference switchCall(conf->getConfID()); @@ -974,7 +947,7 @@ void ManagerImpl::createConfFromParticipantList(const std::vector< std::string > { // we must at least have 2 participant for a conference if (participantList.size() <= 1) { - ERROR("Manager: Error: Participant number must be higher or equal to 2"); + ERROR("Participant number must be higher or equal to 2"); return; } @@ -1027,23 +1000,23 @@ void ManagerImpl::createConfFromParticipantList(const std::vector< std::string > void ManagerImpl::detachParticipant(const std::string& call_id, const std::string& current_id) { - DEBUG("Manager: Detach participant %s (current id: %s)", call_id.c_str(), + DEBUG("Detach participant %s (current id: %s)", call_id.c_str(), current_id.c_str()); std::string current_call_id(getCurrentCallId()); - if (call_id != Call::DEFAULT_ID) { + if (call_id != MainBuffer::DEFAULT_ID) { std::string currentAccountId(getAccountFromCall(call_id)); Call *call = getAccountLink(currentAccountId)->getCall(call_id); if (call == NULL) { - ERROR("Manager: Error: Could not find call %s", call_id.c_str()); + ERROR("Could not find call %s", call_id.c_str()); return; } Conference *conf = getConferenceFromCallID(call_id); if (conf == NULL) { - ERROR("Manager: Error: Call is not conferencing, cannot detach"); + ERROR("Call is not conferencing, cannot detach"); return; } @@ -1051,7 +1024,7 @@ void ManagerImpl::detachParticipant(const std::string& call_id, std::map<std::string, std::string>::iterator iter_details(call_details.find("CALL_STATE")); if (iter_details == call_details.end()) { - ERROR("Manager: Error: Could not find CALL_STATE"); + ERROR("Could not find CALL_STATE"); return; } @@ -1063,25 +1036,25 @@ void ManagerImpl::detachParticipant(const std::string& call_id, // Conference may have been deleted and set to 0 above processRemainingParticipants(current_call_id, conf); if (conf == 0) { - ERROR("Manager: Error: Call is not conferencing, cannot detach"); + ERROR("Call is not conferencing, cannot detach"); return; } } dbus_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr()); } else { - DEBUG("Manager: Unbind main participant from conference %d"); - getMainBuffer()->unBindAll(Call::DEFAULT_ID); + DEBUG("Unbind main participant from conference %d"); + getMainBuffer()->unBindAll(MainBuffer::DEFAULT_ID); if (not isConference(current_call_id)) { - ERROR("Manager: Warning: Current call id (%s) is not a conference", current_call_id.c_str()); + ERROR("Current call id (%s) is not a conference", current_call_id.c_str()); return; } ConferenceMap::iterator iter = conferenceMap_.find(current_call_id); if (iter == conferenceMap_.end() or iter->second == 0) { - DEBUG("Manager: Error: Conference is NULL"); + DEBUG("Conference is NULL"); return; } Conference *conf = iter->second; @@ -1091,7 +1064,7 @@ void ManagerImpl::detachParticipant(const std::string& call_id, else if (conf->getState() == Conference::ACTIVE_ATTACHED_REC) conf->setState(Conference::ACTIVE_DETACHED_REC); else - WARN("Manager: Warning: Undefined behavior, invalid conference state in detach participant"); + WARN("Undefined behavior, invalid conference state in detach participant"); dbus_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr()); @@ -1102,7 +1075,7 @@ void ManagerImpl::detachParticipant(const std::string& call_id, void ManagerImpl::removeParticipant(const std::string& call_id) { - DEBUG("Manager: Remove participant %s", call_id.c_str()); + DEBUG("Remove participant %s", call_id.c_str()); // this call is no more a conference participant const std::string currentAccountId(getAccountFromCall(call_id)); @@ -1112,12 +1085,12 @@ void ManagerImpl::removeParticipant(const std::string& call_id) ConferenceMap::const_iterator iter = conf_map.find(call->getConfId()); if (iter == conf_map.end() or iter->second == 0) { - ERROR("Manager: Error: No conference with id %s, cannot remove participant", call->getConfId().c_str()); + ERROR("No conference with id %s, cannot remove participant", call->getConfId().c_str()); return; } Conference *conf = iter->second; - DEBUG("Manager: Remove participant %s", call_id.c_str()); + DEBUG("Remove participant %s", call_id.c_str()); conf->remove(call_id); call->setConfId(""); @@ -1130,7 +1103,7 @@ void ManagerImpl::processRemainingParticipants(const std::string ¤t_call_i { ParticipantSet participants(conf->getParticipantList()); size_t n = participants.size(); - DEBUG("Manager: Process remaining %d participant(s) from conference %s", + DEBUG("Process remaining %d participant(s) from conference %s", n, conf->getConfID().c_str()); if (n > 1) { @@ -1139,7 +1112,7 @@ void ManagerImpl::processRemainingParticipants(const std::string ¤t_call_i p != participants.end(); ++p) getMainBuffer()->flush(*p); - getMainBuffer()->flush(Call::DEFAULT_ID); + getMainBuffer()->flush(MainBuffer::DEFAULT_ID); } else if (n == 1) { ParticipantSet::iterator p = participants.begin(); @@ -1161,7 +1134,7 @@ void ManagerImpl::processRemainingParticipants(const std::string ¤t_call_i removeConference(conf->getConfID()); conf = 0; } else { - DEBUG("Manager: No remaining participants, remove conference"); + DEBUG("No remaining participants, remove conference"); removeConference(conf->getConfID()); conf = 0; switchCall(""); @@ -1171,39 +1144,37 @@ void ManagerImpl::processRemainingParticipants(const std::string ¤t_call_i void ManagerImpl::joinConference(const std::string& conf_id1, const std::string& conf_id2) { - ConferenceMap::iterator iter(conferenceMap_.find(conf_id1)); + DEBUG("Join conferences %s and %s", conf_id1.c_str(), conf_id2.c_str()); - if (iter == conferenceMap_.end()) { - ERROR("Manager: Error: Not a valid conference ID: %s", conf_id1.c_str()); + if (conferenceMap_.find(conf_id1) == conferenceMap_.end()) { + ERROR("Not a valid conference ID: %s", conf_id1.c_str()); return; } - if (conferenceMap_.find(conf_id2) != conferenceMap_.end()) { - ERROR("Manager: Error: Not a valid conference ID: %s", conf_id2.c_str()); + if (conferenceMap_.find(conf_id2) == conferenceMap_.end()) { + ERROR("Not a valid conference ID: %s", conf_id2.c_str()); return; } - if (iter->second) { - Conference *conf = iter->second; - ParticipantSet participants(conf->getParticipantList()); + Conference *conf = conferenceMap_.find(conf_id1)->second; + ParticipantSet participants(conf->getParticipantList()); - for (ParticipantSet::const_iterator p = participants.begin(); - p != participants.end(); ++p) { - detachParticipant(*p, ""); - addParticipant(*p, conf_id2); - } + for (ParticipantSet::const_iterator p = participants.begin(); + p != participants.end(); ++p) { + detachParticipant(*p, ""); + addParticipant(*p, conf_id2); } } void ManagerImpl::addStream(const std::string& call_id) { - DEBUG("Manager: Add audio stream %s", call_id.c_str()); + DEBUG("Add audio stream %s", call_id.c_str()); std::string currentAccountId(getAccountFromCall(call_id)); Call *call = getAccountLink(currentAccountId)->getCall(call_id); if (call and isConferenceParticipant(call_id)) { - DEBUG("Manager: Add stream to conference"); + DEBUG("Add stream to conference"); // bind to conference participant ConferenceMap::iterator iter = conferenceMap_.find(call->getConfId()); @@ -1220,14 +1191,14 @@ void ManagerImpl::addStream(const std::string& call_id) iter_p != participants.end(); ++iter_p) getMainBuffer()->flush(*iter_p); - getMainBuffer()->flush(Call::DEFAULT_ID); + getMainBuffer()->flush(MainBuffer::DEFAULT_ID); } } else { - DEBUG("Manager: Add stream to call"); + DEBUG("Add stream to call"); // bind to main - getMainBuffer()->bindCallID(call_id); + getMainBuffer()->bindCallID(call_id, MainBuffer::DEFAULT_ID); ost::MutexLock lock(audioLayerMutex_); audiodriver_->flushUrgent(); @@ -1239,7 +1210,7 @@ void ManagerImpl::addStream(const std::string& call_id) void ManagerImpl::removeStream(const std::string& call_id) { - DEBUG("Manager: Remove audio stream %s", call_id.c_str()); + DEBUG("Remove audio stream %s", call_id.c_str()); getMainBuffer()->unBindAll(call_id); getMainBuffer()->stateInfo(); } @@ -1247,27 +1218,25 @@ void ManagerImpl::removeStream(const std::string& call_id) //THREAD=Main void ManagerImpl::saveConfig() { - DEBUG("Manager: Saving Configuration to XDG directory %s", path_.c_str()); - audioPreference.setVolumemic(getMicVolume()); - audioPreference.setVolumespkr(getSpkrVolume()); + DEBUG("Saving Configuration to XDG directory %s", path_.c_str()); + AudioLayer *audiolayer = getAudioDriver(); + if (audiolayer != NULL) { + audioPreference.setVolumemic(audiolayer->getCaptureGain()); + audioPreference.setVolumespkr(audiolayer->getPlaybackGain()); + } try { Conf::YamlEmitter emitter(path_.c_str()); - for (AccountMap::iterator iter = accountMap_.begin(); iter != accountMap_.end(); ++iter) { - // Skip the "" account ID (which refer to the IP2IP account) - if (iter->first.empty()) - continue; - else - iter->second->serialize(&emitter); - } + for (AccountMap::iterator iter = accountMap_.begin(); iter != accountMap_.end(); ++iter) + iter->second->serialize(emitter); - preferences.serialize(&emitter); - voipPreferences.serialize(&emitter); - addressbookPreference.serialize(&emitter); - hookPreference.serialize(&emitter); - audioPreference.serialize(&emitter); - shortcutPreferences.serialize(&emitter); + preferences.serialize(emitter); + voipPreferences.serialize(emitter); + addressbookPreference.serialize(emitter); + hookPreference.serialize(emitter); + audioPreference.serialize(emitter); + shortcutPreferences.serialize(emitter); emitter.serializeData(); } catch (const Conf::YamlEmitterException &e) { @@ -1289,7 +1258,7 @@ void ManagerImpl::playDtmf(char code) stopTone(); if (not voipPreferences.getPlayDtmf()) { - DEBUG("Manager: playDtmf: Do not have to play a tone..."); + DEBUG("Do not have to play a tone..."); return; } @@ -1297,7 +1266,7 @@ void ManagerImpl::playDtmf(char code) int pulselen = voipPreferences.getPulseLength(); if (pulselen == 0) { - DEBUG("Manager: playDtmf: Pulse length is not set..."); + DEBUG("Pulse length is not set..."); return; } @@ -1307,8 +1276,8 @@ void ManagerImpl::playDtmf(char code) // = number of seconds * SAMPLING_RATE by SECONDS // fast return, no sound, so no dtmf - if (audiodriver_ == NULL || dtmfKey_ == NULL) { - DEBUG("Manager: playDtmf: Error no audio layer..."); + if (audiodriver_ == NULL || dtmfKey_.get() == 0) { + DEBUG("No audio layer..."); return; } @@ -1361,47 +1330,41 @@ void ManagerImpl::removeWaitingCall(const std::string& id) nbIncomingWaitingCall_--; } -bool ManagerImpl::isWaitingCall(const std::string &id) const -{ - return waitingCall_.find(id) != waitingCall_.end(); -} - /////////////////////////////////////////////////////////////////////////////// // Management of event peer IP-phone //////////////////////////////////////////////////////////////////////////////// // SipEvent Thread -void ManagerImpl::incomingCall(Call* call, const std::string& accountId) +void ManagerImpl::incomingCall(Call &call, const std::string& accountId) { - assert(call); stopTone(); - associateCallToAccount(call->getCallId(), accountId); + associateCallToAccount(call.getCallId(), accountId); if (accountId.empty()) - setIPToIPForCall(call->getCallId(), true); + setIPToIPForCall(call.getCallId(), true); else { // strip sip: which is not required and bring confusion with ip to ip calls // when placing new call from history (if call is IAX, do nothing) - std::string peerNumber(call->getPeerNumber()); + std::string peerNumber(call.getPeerNumber()); const char SIP_PREFIX[] = "sip:"; size_t startIndex = peerNumber.find(SIP_PREFIX); if (startIndex != std::string::npos) - call->setPeerNumber(peerNumber.substr(startIndex + sizeof(SIP_PREFIX) - 1)); + call.setPeerNumber(peerNumber.substr(startIndex + sizeof(SIP_PREFIX) - 1)); } if (not hasCurrentCall()) { - call->setConnectionState(Call::RINGING); + call.setConnectionState(Call::RINGING); ringtone(accountId); } - addWaitingCall(call->getCallId()); + addWaitingCall(call.getCallId()); - std::string number(call->getPeerNumber()); + std::string number(call.getPeerNumber()); std::string from("<" + number + ">"); - dbus_.getCallManager()->incomingCall(accountId, call->getCallId(), call->getDisplayName() + " " + from); + dbus_.getCallManager()->incomingCall(accountId, call.getCallId(), call.getDisplayName() + " " + from); } @@ -1423,16 +1386,16 @@ void ManagerImpl::incomingMessage(const std::string& callID, std::string accountId(getAccountFromCall(*iter_p)); - DEBUG("Manager: Send message to %s, (%s)", (*iter_p).c_str(), accountId.c_str()); + DEBUG("Send message to %s, (%s)", (*iter_p).c_str(), accountId.c_str()); Account *account = getAccount(accountId); if (!account) { - ERROR("Manager: Failed to get account while sending instant message"); + ERROR("Failed to get account while sending instant message"); return; } - account->getVoIPLink()->sendTextMessage(imModule_, callID, message, from); + account->getVoIPLink()->sendTextMessage(callID, message, from); } // in case of a conference we must notify client using conference id @@ -1447,7 +1410,7 @@ void ManagerImpl::incomingMessage(const std::string& callID, bool ManagerImpl::sendTextMessage(const std::string& callID, const std::string& message, const std::string& from) { if (isConference(callID)) { - DEBUG("Manager: Is a conference, send instant message to everyone"); + DEBUG("Is a conference, send instant message to everyone"); ConferenceMap::iterator it = conferenceMap_.find(callID); if (it == conferenceMap_.end()) @@ -1468,18 +1431,18 @@ bool ManagerImpl::sendTextMessage(const std::string& callID, const std::string& Account *account = getAccount(accountId); if (!account) { - DEBUG("Manager: Failed to get account while sending instant message"); + DEBUG("Failed to get account while sending instant message"); return false; } - account->getVoIPLink()->sendTextMessage(imModule_, *iter_p, message, from); + account->getVoIPLink()->sendTextMessage(*iter_p, message, from); } return true; } if (isConferenceParticipant(callID)) { - DEBUG("Manager: Call is participant in a conference, send instant message to everyone"); + DEBUG("Call is participant in a conference, send instant message to everyone"); Conference *conf = getConferenceFromCallID(callID); if (!conf) @@ -1495,21 +1458,21 @@ bool ManagerImpl::sendTextMessage(const std::string& callID, const std::string& Account *account = getAccount(accountId); if (!account) { - DEBUG("Manager: Failed to get account while sending instant message"); + DEBUG("Failed to get account while sending instant message"); return false; } - account->getVoIPLink()->sendTextMessage(imModule_, *iter_p, message, from); + account->getVoIPLink()->sendTextMessage(*iter_p, message, from); } } else { Account *account = getAccount(getAccountFromCall(callID)); if (!account) { - DEBUG("Manager: Failed to get account while sending instant message"); + DEBUG("Failed to get account while sending instant message"); return false; } - account->getVoIPLink()->sendTextMessage(imModule_, callID, message, from); + account->getVoIPLink()->sendTextMessage(callID, message, from); } return true; @@ -1518,7 +1481,7 @@ bool ManagerImpl::sendTextMessage(const std::string& callID, const std::string& //THREAD=VoIP CALL=Outgoing void ManagerImpl::peerAnsweredCall(const std::string& id) { - DEBUG("Manager: Peer answered call %s", id.c_str()); + DEBUG("Peer answered call %s", id.c_str()); // The if statement is usefull only if we sent two calls at the same time. if (isCurrentCall(id)) @@ -1543,7 +1506,7 @@ void ManagerImpl::peerAnsweredCall(const std::string& id) //THREAD=VoIP Call=Outgoing void ManagerImpl::peerRingingCall(const std::string& id) { - DEBUG("Manager: Peer call %s ringing", id.c_str()); + DEBUG("Peer call %s ringing", id.c_str()); if (isCurrentCall(id)) ringback(); @@ -1554,7 +1517,7 @@ void ManagerImpl::peerRingingCall(const std::string& id) //THREAD=VoIP Call=Outgoing/Ingoing void ManagerImpl::peerHungupCall(const std::string& call_id) { - DEBUG("Manager: Peer hungup call %s", call_id.c_str()); + DEBUG("Peer hungup call %s", call_id.c_str()); if (isConferenceParticipant(call_id)) { Conference *conf = getConferenceFromCallID(call_id); @@ -1573,15 +1536,17 @@ void ManagerImpl::peerHungupCall(const std::string& call_id) /* Direct IP to IP call */ if (isIPToIP(call_id)) { Call * call = SIPVoIPLink::instance()->getCall(call_id); - history_->addCall(call, preferences.getHistoryLimit()); + history_.addCall(call, preferences.getHistoryLimit()); SIPVoIPLink::instance()->hangup(call_id); + saveHistory(); } else { const std::string account_id(getAccountFromCall(call_id)); VoIPLink *link = getAccountLink(account_id); Call * call = link->getCall(call_id); - history_->addCall(call, preferences.getHistoryLimit()); + history_.addCall(call, preferences.getHistoryLimit()); link->peerHungup(call_id); + saveHistory(); } /* Broadcast a signal over DBus */ @@ -1592,7 +1557,7 @@ void ManagerImpl::peerHungupCall(const std::string& call_id) removeStream(call_id); if (getCallList().empty()) { - DEBUG("Manager: Stop audio stream, there are no calls remaining"); + DEBUG("Stop audio stream, there are no calls remaining"); ost::MutexLock lock(audioLayerMutex_); audiodriver_->stopStream(); } @@ -1601,7 +1566,7 @@ void ManagerImpl::peerHungupCall(const std::string& call_id) //THREAD=VoIP void ManagerImpl::callBusy(const std::string& id) { - DEBUG("Manager: Call %s busy", id.c_str()); + DEBUG("Call %s busy", id.c_str()); dbus_.getCallManager()->callStateChanged(id, "BUSY"); if (isCurrentCall(id)) { @@ -1624,11 +1589,11 @@ void ManagerImpl::callFailure(const std::string& call_id) } if (isConferenceParticipant(call_id)) { - DEBUG("Manager: Call %s participating in a conference failed", call_id.c_str()); + DEBUG("Call %s participating in a conference failed", call_id.c_str()); Conference *conf = getConferenceFromCallID(call_id); if (conf == NULL) { - ERROR("Manager: Could not retreive conference from call id %s", call_id.c_str()); + ERROR("Could not retreive conference from call id %s", call_id.c_str()); return; } @@ -1648,11 +1613,6 @@ void ManagerImpl::startVoiceMessageNotification(const std::string& accountId, dbus_.getCallManager()->voiceMailNotify(accountId, nb_msg); } -void ManagerImpl::connectionStatusNotification() -{ - dbus_.getConfigurationManager()->accountsChanged(); -} - /** * Multi Thread */ @@ -1665,7 +1625,7 @@ void ManagerImpl::playATone(Tone::TONEID toneId) ost::MutexLock lock(audioLayerMutex_); if (audiodriver_ == NULL) { - ERROR("Manager: Error: Audio layer not initialized"); + ERROR("Audio layer not initialized"); return; } @@ -1673,7 +1633,7 @@ void ManagerImpl::playATone(Tone::TONEID toneId) audiodriver_->startStream(); } - if (telephoneTone_ != 0) { + if (telephoneTone_.get() != 0) { ost::MutexLock lock(toneMutex_); telephoneTone_->setCurrentTone(toneId); } @@ -1689,14 +1649,13 @@ void ManagerImpl::stopTone() ost::MutexLock lock(toneMutex_); - if (telephoneTone_ != NULL) + if (telephoneTone_.get() != NULL) telephoneTone_->setCurrentTone(Tone::TONE_NULL); - if (audiofile_) { + if (audiofile_.get()) { std::string filepath(audiofile_->getFilePath()); dbus_.getCallManager()->recordPlaybackStopped(filepath); - delete audiofile_; - audiofile_ = NULL; + audiofile_.reset(); } } @@ -1740,7 +1699,7 @@ void ManagerImpl::ringtone(const std::string& accountID) Account *account = getAccount(accountID); if (!account) { - WARN("Manager: Warning: invalid account in ringtone"); + WARN("Invalid account in ringtone"); return; } @@ -1763,7 +1722,7 @@ void ManagerImpl::ringtone(const std::string& accountID) ost::MutexLock lock(audioLayerMutex_); if (!audiodriver_) { - ERROR("Manager: Error: no audio layer in ringtone"); + ERROR("no audio layer in ringtone"); return; } @@ -1773,27 +1732,25 @@ void ManagerImpl::ringtone(const std::string& accountID) { ost::MutexLock m(toneMutex_); - if (audiofile_) { + if (audiofile_.get()) { dbus_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath()); - delete audiofile_; - audiofile_ = NULL; + audiofile_.reset(); } try { if (ringchoice.find(".wav") != std::string::npos) - audiofile_ = new WaveFile(ringchoice, samplerate); + audiofile_.reset(new WaveFile(ringchoice, samplerate)); else { sfl::Codec *codec; + if (ringchoice.find(".ul") != std::string::npos or ringchoice.find(".au") != std::string::npos) + codec = audioCodecFactory.getCodec(PAYLOAD_CODEC_ULAW); + else + throw AudioFileException("Couldn't guess an appropriate decoder"); - if (ringchoice.find(".ul") != std::string::npos or ringchoice.find(".au") != std::string::npos) - codec = audioCodecFactory.getCodec(PAYLOAD_CODEC_ULAW); - else - throw AudioFileException("Couldn't guess an appropriate decoder"); - - audiofile_ = new RawFile(ringchoice, static_cast<sfl::AudioCodec *>(codec), samplerate); + audiofile_.reset(new RawFile(ringchoice, static_cast<sfl::AudioCodec *>(codec), samplerate)); } - } catch (AudioFileException &e) { - ERROR("Manager: Exception: %s", e.what()); + } catch (const AudioFileException &e) { + ERROR("Exception: %s", e.what()); } } // leave mutex @@ -1802,10 +1759,9 @@ void ManagerImpl::ringtone(const std::string& accountID) audiodriver_->startStream(); } -AudioLoop* -ManagerImpl::getTelephoneTone() +AudioLoop* ManagerImpl::getTelephoneTone() { - if (telephoneTone_) { + if (telephoneTone_.get()) { ost::MutexLock m(toneMutex_); return telephoneTone_->getCurrentTone(); } else @@ -1816,8 +1772,7 @@ AudioLoop* ManagerImpl::getTelephoneFile() { ost::MutexLock m(toneMutex_); - - return audiofile_; + return audiofile_.get(); } /////////////////////////////////////////////////////////////////////////////// @@ -1826,14 +1781,13 @@ ManagerImpl::getTelephoneFile() /** * Initialization: Main Thread */ -std::string ManagerImpl::getConfigFile() const +std::string ManagerImpl::createConfigFile() const { - std::string configdir = std::string(HOMEDIR) + DIR_SEPARATOR_STR + ".config" - + DIR_SEPARATOR_STR + PACKAGE; + std::string configdir = std::string(HOMEDIR) + DIR_SEPARATOR_STR + + ".config" + DIR_SEPARATOR_STR + PACKAGE; if (XDG_CONFIG_HOME != NULL) { - std::string xdg_env = std::string(XDG_CONFIG_HOME); - + std::string xdg_env(XDG_CONFIG_HOME); if (not xdg_env.empty()) configdir = xdg_env; } @@ -1848,7 +1802,7 @@ std::string ManagerImpl::getConfigFile() const return configdir + DIR_SEPARATOR_STR + PROGNAME + ".yml"; } -std::vector<std::string> ManagerImpl::unserialize(std::string s) +std::vector<std::string> ManagerImpl::split_string(std::string s) { std::vector<std::string> list; std::string temp; @@ -1863,7 +1817,7 @@ std::vector<std::string> ManagerImpl::unserialize(std::string s) return list; } -std::string ManagerImpl::serialize(const std::vector<std::string> &v) +std::string ManagerImpl::join_string(const std::vector<std::string> &v) { std::ostringstream os; std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(os, "/")); @@ -2015,7 +1969,7 @@ int ManagerImpl::isRingtoneEnabled(const std::string& id) Account *account = getAccount(id); if (!account) { - WARN("Manager: Warning: invalid account in ringtone enabled"); + WARN("Invalid account in ringtone enabled"); return 0; } @@ -2027,7 +1981,7 @@ void ManagerImpl::ringtoneEnabled(const std::string& id) Account *account = getAccount(id); if (!account) { - WARN("Manager: Warning: invalid account in ringtone enabled"); + WARN("Invalid account in ringtone enabled"); return; } @@ -2041,7 +1995,7 @@ std::string ManagerImpl::getRecordPath() const void ManagerImpl::setRecordPath(const std::string& recPath) { - DEBUG("Manager: Set record path %s", recPath.c_str()); + DEBUG("Set record path %s", recPath.c_str()); audioPreference.setRecordpath(recPath); } @@ -2061,11 +2015,11 @@ void ManagerImpl::setRecordingCall(const std::string& id) ConferenceMap::const_iterator it(conferenceMap_.find(id)); if (it == conferenceMap_.end()) { - DEBUG("Manager: Set recording for call %s", id.c_str()); + DEBUG("Set recording for call %s", id.c_str()); std::string accountid(getAccountFromCall(id)); rec = getAccountLink(accountid)->getCall(id); } else { - DEBUG("Manager: Set recording for conference %s", id.c_str()); + DEBUG("Set recording for conference %s", id.c_str()); Conference *conf = it->second; if (conf) { @@ -2078,7 +2032,7 @@ void ManagerImpl::setRecordingCall(const std::string& id) } if (rec == NULL) { - ERROR("Manager: Error: Could not find recordable instance %s", id.c_str()); + ERROR("Could not find recordable instance %s", id.c_str()); return; } @@ -2095,14 +2049,14 @@ bool ManagerImpl::isRecording(const std::string& id) bool ManagerImpl::startRecordedFilePlayback(const std::string& filepath) { - DEBUG("Manager: Start recorded file playback %s", filepath.c_str()); + DEBUG("Start recorded file playback %s", filepath.c_str()); int sampleRate; { ost::MutexLock lock(audioLayerMutex_); if (!audiodriver_) { - ERROR("Manager: Error: No audio layer in start recorded file playback"); + ERROR("No audio layer in start recorded file playback"); return false; } @@ -2112,16 +2066,15 @@ bool ManagerImpl::startRecordedFilePlayback(const std::string& filepath) { ost::MutexLock m(toneMutex_); - if (audiofile_) { + if (audiofile_.get()) { dbus_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath()); - delete audiofile_; - audiofile_ = NULL; + audiofile_.reset(); } try { - audiofile_ = new WaveFile(filepath, sampleRate); + audiofile_.reset(new WaveFile(filepath, sampleRate)); } catch (const AudioFileException &e) { - ERROR("Manager: Exception: %s", e.what()); + ERROR("Exception: %s", e.what()); } } // release toneMutex @@ -2134,7 +2087,7 @@ bool ManagerImpl::startRecordedFilePlayback(const std::string& filepath) void ManagerImpl::stopRecordedFilePlayback(const std::string& filepath) { - DEBUG("Manager: Stop recorded file playback %s", filepath.c_str()); + DEBUG("Stop recorded file playback %s", filepath.c_str()); { ost::MutexLock lock(audioLayerMutex_); @@ -2143,14 +2096,13 @@ void ManagerImpl::stopRecordedFilePlayback(const std::string& filepath) { ost::MutexLock m(toneMutex_); - delete audiofile_; - audiofile_ = NULL; + audiofile_.reset(); } } void ManagerImpl::setHistoryLimit(int days) { - DEBUG("Manager: Set history limit"); + DEBUG("Set history limit"); preferences.setHistoryLimit(days); saveConfig(); } @@ -2167,7 +2119,7 @@ int32_t ManagerImpl::getMailNotify() const void ManagerImpl::setMailNotify() { - DEBUG("Manager: Set mail notify"); + DEBUG("Set mail notify"); preferences.getNotifyMails() ? preferences.setNotifyMails(true) : preferences.setNotifyMails(false); saveConfig(); } @@ -2181,7 +2133,7 @@ void ManagerImpl::setAudioManager(const std::string &api) return; if (api == audioPreference.getAudioApi()) { - DEBUG("Manager: Audio manager chosen already in use. No changes made. "); + DEBUG("Audio manager chosen already in use. No changes made. "); return; } } @@ -2204,7 +2156,7 @@ int ManagerImpl::getAudioDeviceIndex(const std::string &name) ost::MutexLock lock(audioLayerMutex_); if (audiodriver_ == NULL) { - ERROR("Manager: Error: Audio layer not initialized"); + ERROR("Audio layer not initialized"); return soundCardIndex; } @@ -2288,7 +2240,7 @@ void ManagerImpl::audioSamplingRateChanged(int samplerate) ost::MutexLock lock(audioLayerMutex_); if (!audiodriver_) { - DEBUG("Manager: No Audio driver initialized"); + DEBUG("No Audio driver initialized"); return; } @@ -2296,10 +2248,10 @@ void ManagerImpl::audioSamplingRateChanged(int samplerate) int currentSamplerate = mainBuffer_.getInternalSamplingRate(); if (currentSamplerate >= samplerate) { - DEBUG("Manager: No need to update audio layer sampling rate"); + DEBUG("No need to update audio layer sampling rate"); return; } else - DEBUG("Manager: Audio sampling rate changed: %d -> %d", currentSamplerate, samplerate); + DEBUG("Audio sampling rate changed: %d -> %d", currentSamplerate, samplerate); bool wasActive = audiodriver_->isStarted(); @@ -2310,64 +2262,16 @@ void ManagerImpl::audioSamplingRateChanged(int samplerate) unsigned int sampleRate = audiodriver_->getSampleRate(); - delete telephoneTone_; - telephoneTone_ = new TelephoneTone(preferences.getZoneToneChoice(), sampleRate); - - delete dtmfKey_; - dtmfKey_ = new DTMF(sampleRate); + telephoneTone_.reset(new TelephoneTone(preferences.getZoneToneChoice(), sampleRate)); + dtmfKey_.reset(new DTMF(sampleRate)); if (wasActive) audiodriver_->startStream(); } -/** - * Init the volume for speakers/micro from 0 to 100 value - * Initialization: Main Thread - */ -void ManagerImpl::initVolume() -{ - setSpkrVolume(audioPreference.getVolumespkr()); - setMicVolume(audioPreference.getVolumemic()); -} - -void ManagerImpl::setSpkrVolume(unsigned short spkr_vol) -{ - speakerVolume_ = spkr_vol; -} - -void ManagerImpl::setMicVolume(unsigned short mic_vol) -{ - micVolume_ = mic_vol; -} - -int ManagerImpl::getLocalIp2IpPort() const -{ - return preferences.getPortNum(); -} - -//THREAD=Main -bool ManagerImpl::getConfig(const std::string& section, - const std::string& name, TokenList& arg) const -{ - return config_.getConfigTreeItemToken(section, name, arg); -} - -//THREAD=Main -int ManagerImpl::getConfigInt(const std::string& section, - const std::string& name) const -{ - return config_.getConfigTreeItemIntValue(section, name); -} - -bool ManagerImpl::getConfigBool(const std::string& section, - const std::string& name) const -{ - return config_.getConfigTreeItemValue(section, name) == Conf::TRUE_STR; -} - //THREAD=Main std::string ManagerImpl::getConfigString(const std::string& section, - const std::string& name) const + const std::string& name) const { return config_.getConfigTreeItemValue(section, name); } @@ -2390,7 +2294,7 @@ void ManagerImpl::setConfig(const std::string& section, void ManagerImpl::setAccountsOrder(const std::string& order) { - DEBUG("Manager: Set accounts order : %s", order.c_str()); + DEBUG("Set accounts order : %s", order.c_str()); // Set the new config preferences.setAccountOrder(order); @@ -2406,18 +2310,18 @@ std::vector<std::string> ManagerImpl::getAccountList() const // The IP2IP profile is always available, and first in the list - AccountMap::const_iterator ip2ip_iter = accountMap_.find(IP2IP_PROFILE); + AccountMap::const_iterator ip2ip_iter = accountMap_.find(SIPAccount::IP2IP_PROFILE); vector<string> v; if (ip2ip_iter->second) v.push_back(ip2ip_iter->second->getAccountID()); else - ERROR("Manager: could not find IP2IP profile in getAccount list"); + ERROR("could not find IP2IP profile in getAccount list"); // If no order has been set, load the default one ie according to the creation date. if (account_order.empty()) { for (AccountMap::const_iterator iter = accountMap_.begin(); iter != accountMap_.end(); ++iter) { - if (iter->first == IP2IP_PROFILE || iter->first.empty()) + if (iter->first == SIPAccount::IP2IP_PROFILE || iter->first.empty()) continue; if (iter->second) @@ -2426,7 +2330,7 @@ std::vector<std::string> ManagerImpl::getAccountList() const } else { for (vector<string>::const_iterator iter = account_order.begin(); iter != account_order.end(); ++iter) { - if (*iter == IP2IP_PROFILE or iter->empty()) + if (*iter == SIPAccount::IP2IP_PROFILE or iter->empty()) continue; AccountMap::const_iterator account_iter = accountMap_.find(*iter); @@ -2446,12 +2350,12 @@ std::map<std::string, std::string> ManagerImpl::getAccountDetails( static const SIPAccount DEFAULT_ACCOUNT("default"); if (accountID.empty()) { - DEBUG("Manager: Returning default account settings"); + DEBUG("Returning default account settings"); return DEFAULT_ACCOUNT.getAccountDetails(); } AccountMap::const_iterator iter = accountMap_.find(accountID); - Account * account = 0; + Account * account = NULL; if (iter != accountMap_.end()) account = iter->second; @@ -2459,7 +2363,7 @@ std::map<std::string, std::string> ManagerImpl::getAccountDetails( if (account) return account->getAccountDetails(); else { - DEBUG("Manager: Get account details on a non-existing accountID %s. Returning default", accountID.c_str()); + DEBUG("Get account details on a non-existing accountID %s. Returning default", accountID.c_str()); return DEFAULT_ACCOUNT.getAccountDetails(); } } @@ -2470,12 +2374,12 @@ std::map<std::string, std::string> ManagerImpl::getAccountDetails( void ManagerImpl::setAccountDetails(const std::string& accountID, const std::map<std::string, std::string>& details) { - DEBUG("Manager: Set account details for %s", accountID.c_str()); + DEBUG("Set account details for %s", accountID.c_str()); Account* account = getAccount(accountID); if (account == NULL) { - ERROR("Manager: Error: Could not find account %s", accountID.c_str()); + ERROR("Could not find account %s", accountID.c_str()); return; } @@ -2493,7 +2397,8 @@ void ManagerImpl::setAccountDetails(const std::string& accountID, dbus_.getConfigurationManager()->accountsChanged(); } -std::string ManagerImpl::addAccount(const std::map<std::string, std::string>& details) +std::string +ManagerImpl::addAccount(const std::map<std::string, std::string>& details) { /** @todo Deal with both the accountMap_ and the Configuration */ std::stringstream accountID; @@ -2504,7 +2409,7 @@ std::string ManagerImpl::addAccount(const std::map<std::string, std::string>& de // Get the type std::string accountType((*details.find(CONFIG_ACCOUNT_TYPE)).second); - DEBUG("Manager: Adding account %s", newAccountID.c_str()); + DEBUG("Adding account %s", newAccountID.c_str()); /** @todo Verify the uniqueness, in case a program adds accounts, two in a row. */ @@ -2539,7 +2444,7 @@ std::string ManagerImpl::addAccount(const std::map<std::string, std::string>& de preferences.setAccountOrder(accountList); } - DEBUG("AccountMap: %s", accountList.c_str()); + DEBUG("Getting accounts: %s", accountList.c_str()); newAccount->registerVoIPLink(); @@ -2570,18 +2475,12 @@ void ManagerImpl::removeAccount(const std::string& accountID) } // ACCOUNT handling -bool ManagerImpl::associateCallToAccount(const std::string& callID, +void ManagerImpl::associateCallToAccount(const std::string& callID, const std::string& accountID) { - if (getAccountFromCall(callID).empty() and accountExists(accountID)) { - // account id exist in AccountMap - ost::MutexLock m(callAccountMapMutex_); - callAccountMap_[callID] = accountID; - DEBUG("Manager: Associate Call %s with Account %s", callID.data(), accountID.data()); - return true; - } - - return false; + ost::MutexLock m(callAccountMapMutex_); + callAccountMap_[callID] = accountID; + DEBUG("Associate Call %s with Account %s", callID.data(), accountID.data()); } std::string ManagerImpl::getAccountFromCall(const std::string& callID) @@ -2632,101 +2531,134 @@ std::string ManagerImpl::getNewCallID() std::vector<std::string> ManagerImpl::loadAccountOrder() const { - return unserialize(preferences.getAccountOrder()); + return split_string(preferences.getAccountOrder()); } -void ManagerImpl::loadAccountMap(Conf::YamlParser *parser) +void ManagerImpl::loadDefaultAccountMap() { // build a default IP2IP account with default parameters - Account *ip2ip = new SIPAccount(IP2IP_PROFILE); - accountMap_[IP2IP_PROFILE] = ip2ip; - - // If configuration file parsed, load saved preferences - if (parser) { - Conf::Sequence *seq = parser->getAccountSequence()->getSequence(); + accountMap_[SIPAccount::IP2IP_PROFILE] = new SIPAccount(SIPAccount::IP2IP_PROFILE); + SIPVoIPLink::instance()->sipTransport.createDefaultSipUdpTransport(); + accountMap_[SIPAccount::IP2IP_PROFILE]->registerVoIPLink(); +} - for (Conf::Sequence::const_iterator iter = seq->begin(); iter != seq->end(); ++iter) { - Conf::MappingNode *map = (Conf::MappingNode *)(*iter); - std::string accountid; - map->getValue("id", &accountid); +namespace { + bool isIP2IP(const Conf::YamlNode *node) + { + std::string id; + const Conf::MappingNode *m = dynamic_cast<const Conf::MappingNode *>(node); + if (!m) + return false; + m->getValue("id", &id); + return id == "IP2IP"; + } - if (accountid == "IP2IP") { - ip2ip->unserialize(map); - break; - } + void loadAccount(const Conf::YamlNode *item, AccountMap &accountMap) + { + const Conf::MappingNode *node = dynamic_cast<const Conf::MappingNode *>(item); + if (!node) { + ERROR("Could not load account"); + return; } - } - // Initialize default UDP transport according to - // IP to IP settings (most likely using port 5060) - SIPVoIPLink::instance()->createDefaultSipUdpTransport(); + std::string accountType; + node->getValue("type", &accountType); - // Force IP2IP settings to be loaded to be loaded - // No registration in the sense of the REGISTER method is performed. - ip2ip->registerVoIPLink(); + std::string accountid; + node->getValue("id", &accountid); - if (!parser) - return; + std::string accountAlias; + node->getValue("alias", &accountAlias); - // build preferences - preferences.unserialize(parser->getPreferenceNode()); - voipPreferences.unserialize(parser->getVoipPreferenceNode()); - addressbookPreference.unserialize(parser->getAddressbookNode()); - hookPreference.unserialize(parser->getHookNode()); - audioPreference.unserialize(parser->getAudioNode()); - shortcutPreferences.unserialize(parser->getShortcutNode()); + if (!accountid.empty() and !accountAlias.empty() and accountid != SIPAccount::IP2IP_PROFILE) { + Account *a; +#if HAVE_IAX + if (accountType == "IAX") + a = new IAXAccount(accountid); + else // assume SIP +#endif + a = new SIPAccount(accountid); - Conf::Sequence *seq = parser->getAccountSequence()->getSequence(); + accountMap[accountid] = a; + a->unserialize(*node); + } + } - // Each element in sequence is a new account to create - for (Conf::Sequence::const_iterator iter = seq->begin(); iter != seq->end(); ++iter) { - Conf::MappingNode *map = (Conf::MappingNode *)(*iter); + void unregisterAccount(std::pair<const std::string, Account*> &item) + { + item.second->unregisterVoIPLink(); + } - std::string accountType; - map->getValue("type", &accountType); + void unloadAccount(std::pair<const std::string, Account*> &item) + { + // avoid deleting IP2IP account twice + if (not item.first.empty()) { + delete item.second; + item.second = 0; + } + } - std::string accountid; - map->getValue("id", &accountid); +} // end anonymous namespace - std::string accountAlias; - map->getValue("alias", &accountAlias); +void ManagerImpl::loadAccountMap(Conf::YamlParser &parser) +{ + using namespace Conf; + // build a default IP2IP account with default parameters + accountMap_[SIPAccount::IP2IP_PROFILE] = new SIPAccount(SIPAccount::IP2IP_PROFILE); - if (accountid.empty() or accountAlias.empty() or accountid == IP2IP_PROFILE) - continue; + // load saved preferences for IP2IP account from configuration file + Sequence *seq = parser.getAccountSequence()->getSequence(); + Sequence::const_iterator ip2ip = std::find_if(seq->begin(), seq->end(), isIP2IP); + if (ip2ip != seq->end()) { + MappingNode *node = dynamic_cast<MappingNode*>(*ip2ip); + if (node) + accountMap_[SIPAccount::IP2IP_PROFILE]->unserialize(*node); + } - Account *a; + // Initialize default UDP transport according to + // IP to IP settings (most likely using port 5060) + SIPVoIPLink::instance()->sipTransport.createDefaultSipUdpTransport(); -#if HAVE_IAX - if (accountType == "IAX") - a = new IAXAccount(accountid); - else // assume SIP -#endif - a = new SIPAccount(accountid); + // Force IP2IP settings to be loaded to be loaded + // No registration in the sense of the REGISTER method is performed. + accountMap_[SIPAccount::IP2IP_PROFILE]->registerVoIPLink(); - accountMap_[accountid] = a; + // build preferences + preferences.unserialize(*parser.getPreferenceNode()); + voipPreferences.unserialize(*parser.getVoipPreferenceNode()); + addressbookPreference.unserialize(*parser.getAddressbookNode()); + hookPreference.unserialize(*parser.getHookNode()); + audioPreference.unserialize(*parser.getAudioNode()); + shortcutPreferences.unserialize(*parser.getShortcutNode()); - a->unserialize(map); - } + using namespace std::tr1; // for std::tr1::bind and std::tr1::ref + using namespace std::tr1::placeholders; + // Each valid account element in sequence is a new account to load + std::for_each(seq->begin(), seq->end(), bind(loadAccount, _1, ref(accountMap_))); } -void ManagerImpl::unloadAccountMap() +void ManagerImpl::unregisterAllAccounts() { - for (AccountMap::iterator iter = accountMap_.begin(); iter != accountMap_.end(); ++iter) { - // Avoid removing the IP2IP account twice - if (not iter->first.empty()) { - delete iter->second; - iter->second = 0; - } - } + std::for_each(accountMap_.begin(), accountMap_.end(), unregisterAccount); +} +void ManagerImpl::unloadAccountMap() +{ + std::for_each(accountMap_.begin(), accountMap_.end(), unloadAccount); accountMap_.clear(); } -bool ManagerImpl::accountExists(const std::string& accountID) +bool ManagerImpl::accountExists(const std::string &accountID) { return accountMap_.find(accountID) != accountMap_.end(); } +SIPAccount* +ManagerImpl::getIP2IPAccount() +{ + return static_cast<SIPAccount*>(accountMap_[SIPAccount::IP2IP_PROFILE]); +} + Account* ManagerImpl::getAccount(const std::string& accountID) { @@ -2734,19 +2666,19 @@ ManagerImpl::getAccount(const std::string& accountID) if (iter != accountMap_.end()) return iter->second; - return getAccount(IP2IP_PROFILE); + return accountMap_[SIPAccount::IP2IP_PROFILE]; } std::string ManagerImpl::getAccountIdFromNameAndServer(const std::string& userName, const std::string& server) const { - DEBUG("Manager : username = %s, server = %s", userName.c_str(), server.c_str()); + DEBUG("username = %s, server = %s", userName.c_str(), server.c_str()); // Try to find the account id from username and server name by full match for (AccountMap::const_iterator iter = accountMap_.begin(); iter != accountMap_.end(); ++iter) { SIPAccount *account = dynamic_cast<SIPAccount *>(iter->second); if (account and account->isEnabled() and account->fullMatch(userName, server)) { - DEBUG("Manager: Matching account id in request is a fullmatch %s@%s", userName.c_str(), server.c_str()); + DEBUG("Matching account id in request is a fullmatch %s@%s", userName.c_str(), server.c_str()); return iter->first; } } @@ -2756,7 +2688,7 @@ std::string ManagerImpl::getAccountIdFromNameAndServer(const std::string& userNa SIPAccount *account = dynamic_cast<SIPAccount *>(iter->second); if (account and account->isEnabled() and account->hostnameMatch(server)) { - DEBUG("Manager: Matching account id in request with hostname %s", server.c_str()); + DEBUG("Matching account id in request with hostname %s", server.c_str()); return iter->first; } } @@ -2766,13 +2698,12 @@ std::string ManagerImpl::getAccountIdFromNameAndServer(const std::string& userNa SIPAccount *account = dynamic_cast<SIPAccount *>(iter->second); if (account and account->isEnabled() and account->userMatch(userName)) { - DEBUG("Manager: Matching account id in request with username %s", userName.c_str()); + DEBUG("Matching account id in request with username %s", userName.c_str()); return iter->first; } } - DEBUG("Manager: Username %s or server %s doesn't match any account, using IP2IP", userName.c_str(), server.c_str()); - + DEBUG("Username %s or server %s doesn't match any account, using IP2IP", userName.c_str(), server.c_str()); return ""; } @@ -2802,37 +2733,13 @@ void ManagerImpl::setAddressbookSettings(const std::map<std::string, int32_t>& s void ManagerImpl::setAddressbookList(const std::vector<std::string>& list) { - addressbookPreference.setList(ManagerImpl::serialize(list)); + addressbookPreference.setList(ManagerImpl::join_string(list)); saveConfig(); } std::vector<std::string> ManagerImpl::getAddressbookList() const { - return unserialize(addressbookPreference.getList()); -} - -std::map<std::string, std::string> ManagerImpl::getHookSettings() const -{ - std::map<std::string, std::string> settings; - - settings["URLHOOK_IAX2_ENABLED"] = hookPreference.getIax2Enabled() ? "true" : "false"; - settings["PHONE_NUMBER_HOOK_ADD_PREFIX"] = hookPreference.getNumberAddPrefix(); - settings["PHONE_NUMBER_HOOK_ENABLED"] = hookPreference.getNumberEnabled() ? "true" : "false"; - settings["URLHOOK_SIP_ENABLED"] = hookPreference.getSipEnabled() ? "true" : "false"; - settings["URLHOOK_COMMAND"] = hookPreference.getUrlCommand(); - settings["URLHOOK_SIP_FIELD"] = hookPreference.getUrlSipField(); - - return settings; -} - -void ManagerImpl::setHookSettings(const std::map<std::string, std::string>& settings) -{ - hookPreference.setIax2Enabled(settings.find("URLHOOK_IAX2_ENABLED")->second == "true"); - hookPreference.setNumberAddPrefix(settings.find("PHONE_NUMBER_HOOK_ADD_PREFIX")->second); - hookPreference.setNumberEnabled(settings.find("PHONE_NUMBER_HOOK_ENABLED")->second == "true"); - hookPreference.setSipEnabled(settings.find("URLHOOK_SIP_ENABLED")->second == "true"); - hookPreference.setUrlCommand(settings.find("URLHOOK_COMMAND")->second); - hookPreference.setUrlSipField(settings.find("URLHOOK_SIP_FIELD")->second); + return split_string(addressbookPreference.getList()); } void ManagerImpl::setIPToIPForCall(const std::string& callID, bool IPToIP) @@ -2847,7 +2754,7 @@ bool ManagerImpl::isIPToIP(const std::string& callID) const return iter != IPToIPMap_.end() and iter->second; } -std::map<std::string, std::string> ManagerImpl::getCallDetails(const std::string& callID) +std::map<std::string, std::string> ManagerImpl::getCallDetails(const std::string &callID) { // We need here to retrieve the call information attached to the call ID // To achieve that, we need to get the voip link attached to the call @@ -2876,8 +2783,9 @@ std::map<std::string, std::string> ManagerImpl::getCallDetails(const std::string call_details["DISPLAY_NAME"] = call->getDisplayName(); call_details["CALL_STATE"] = call->getStateStr(); call_details["CALL_TYPE"] = type.str(); + call_details["CONF_ID"] = call->getConfId(); } else { - ERROR("Manager: Error: getCallDetails()"); + ERROR("Call is NULL"); call_details["ACCOUNTID"] = ""; call_details["PEER_NUMBER"] = "Unknown"; call_details["PEER_NAME"] = "Unknown"; @@ -2891,7 +2799,7 @@ std::map<std::string, std::string> ManagerImpl::getCallDetails(const std::string std::vector<std::map<std::string, std::string> > ManagerImpl::getHistory() const { - return history_->getSerialized(); + return history_.getSerialized(); } namespace { @@ -2940,18 +2848,34 @@ std::vector<std::string> ManagerImpl::getParticipantList(const std::string& conf const ParticipantSet participants(iter_conf->second->getParticipantList()); std::copy(participants.begin(), participants.end(), std::back_inserter(v));; } else - WARN("Manager: Warning: Did not find conference %s", confID.c_str()); + WARN("Did not find conference %s", confID.c_str()); return v; } +std::string ManagerImpl::getConferenceId(const std::string& callID) +{ + std::string account_id = getAccountFromCall(callID); + Call *call = getAccountLink(account_id)->getCall(callID); + if(call == NULL) { + ERROR("Get conference id"); + return ""; + } + + std::string confID = call->getConfId(); + + return confID; +} + void ManagerImpl::saveHistory() { - if (!history_->save()) - ERROR("Manager: could not save history!"); + if (!history_.save()) + ERROR("Could not save history!"); + else + dbus_.getConfigurationManager()->historyChanged(); } void ManagerImpl::clearHistory() { - history_->clear(); + history_.clear(); } diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index 2c9dc2ebf372b05fee0d59124b4058d25b796a7e..e762892a6acb8b57650162156ab89064e0a0c1ff 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -32,17 +32,18 @@ * as that of the covered work. */ -#ifndef __SFL_MANAGER_H__ -#define __SFL_MANAGER_H__ +#ifndef MANAGER_IMPL_H_ +#define MANAGER_IMPL_H_ #include <string> #include <vector> #include <set> #include <map> -#include <cc++/thread.h> +#include <tr1/memory> +#include "cc_thread.h" #include "dbus/dbusmanager.h" -#include "config/config.h" +#include "config/sfl_config.h" #include "call.h" #include "conference.h" @@ -52,15 +53,12 @@ #include "audio/mainbuffer.h" #include "preferences.h" +#include "history/history.h" #include "noncopyable.h" -namespace sfl { -class InstantMessaging; -} - namespace Conf { -class YamlParser; -class YamlEmitter; + class YamlParser; + class YamlEmitter; } class DTMF; @@ -75,6 +73,7 @@ class DNSService; #endif class Account; +class SIPAccount; /** Define a type for a AccountMap container */ typedef std::map<std::string, Account*> AccountMap; @@ -94,8 +93,6 @@ static const char * const default_conf = "conf"; class ManagerImpl { public: ManagerImpl(); - ~ManagerImpl(); - /** * General preferences configuration @@ -131,7 +128,7 @@ class ManagerImpl { * Initialisation of thread (sound) and map. * Init a new VoIPLink, audio codec and audio driver */ - void init(std::string config_file=""); + void init(const std::string &config_file); /** * Terminate all thread (sound, link) and unload AccountMap @@ -356,7 +353,7 @@ class ManagerImpl { * @param call A call pointer * @param accountId an account id */ - void incomingCall(Call* call, const std::string& accountId); + void incomingCall(Call &call, const std::string& accountId); /** * Notify the user that the recipient of the call has answered and the put the @@ -401,11 +398,6 @@ class ManagerImpl { */ void startVoiceMessageNotification(const std::string& accountId, int nb_msg); - /** - * Notify the client through DBus that registration state has been updated - */ - void connectionStatusNotification(); - /** * ConfigurationManager - Send registration request * @param accountId The account to register/unregister @@ -466,6 +458,8 @@ class ManagerImpl { */ std::vector<std::string> getParticipantList(const std::string& confID) const; + std::string getConferenceId(const std::string& callID); + /** * Save the details of an existing account, given the account ID * This will load the configuration map with the given data. @@ -577,9 +571,9 @@ class ManagerImpl { * Required format: payloads separated with one slash. * @return std::string The serializabled string */ - static std::string serialize(const std::vector<std::string> &v); + static std::string join_string(const std::vector<std::string> &v); - static std::vector<std::string> unserialize(std::string v); + static std::vector<std::string> split_string(std::string v); /** * Ringtone option. @@ -693,17 +687,6 @@ class ManagerImpl { */ std::vector <std::string> getAddressbookList() const; - /** - * Hook configuration - */ - std::map<std::string, std::string> getHookSettings() const; - - /** - * Hook configuration - */ - void setHookSettings(const std::map<std::string, std::string>& settings); - - /** * Get the audio manager * @return int The audio manager @@ -737,16 +720,6 @@ class ManagerImpl { */ std::vector<std::string> getActiveCodecList() const; - /** - * Retrieve in the configuration tree the value of a parameter in a specific section - * @param section The section to look in - * @param name The name of the parameter you want to get - * @param arg Undocumented - * @return bool true on success - * false otherwise - */ - bool getConfig(const std::string& section, const std::string& name, TokenList& arg) const; - /** * Change a specific value in the configuration tree. * This value will then be saved in the user config file sflphonedrc @@ -769,26 +742,6 @@ class ManagerImpl { */ void setConfig(const std::string& section, const std::string& name, int value); - /** - * Get a int from the configuration tree - * Throw an Conf::ConfigTreeItemException if not found - * @param section The section name to look in - * @param name The parameter name - * @return int The int value - */ - - int getConfigInt(const std::string& section, const std::string& name) const; - - /** - * Get a bool from the configuration tree - * Throw an Conf::ConfigTreeItemException if not found - * @param section The section name to look in - * @param name The parameter name - * @return bool The bool value - */ - - bool getConfigBool(const std::string& section, const std::string& name) const; - /** * Get a string from the configuration tree * Throw an Conf::ConfigTreeItemException if not found @@ -849,42 +802,6 @@ class ManagerImpl { */ bool incomingCallWaiting() const; - /* - * Inline functions to manage speaker volume control - * Read by main thread and AudioLayer thread - * Write by main thread only - * @return unsigned short The volume value - */ - unsigned short getSpkrVolume() const { - return speakerVolume_; - } - - /* - * Inline functions to manage speaker volume control - * Read by main thread and AudioLayer thread - * Write by main thread only - * @param spkr_vol The volume value - */ - void setSpkrVolume(unsigned short spkr_vol); - - /* - * Inline functions to manage mic volume control - * Read by main thread and AudioLayer thread - * Write by main thread only - * @return unsigned short The volume value - */ - unsigned short getMicVolume() const { - return micVolume_; - } - - /* - * Inline functions to manage mic volume control - * Read by main thread and AudioLayer thread - * Write by main thread only - * @param mic_vol The volume value - */ - void setMicVolume(unsigned short mic_vol); - /** * Return a new random callid that is not present in the list * @return std::string A brand new callid @@ -941,19 +858,13 @@ class ManagerImpl { /** * Create config directory in home user and return configuration file path */ - std::string getConfigFile() const; - + std::string createConfigFile() const; /* * Initialize zeroconf module and scanning */ void initZeroconf(); - /* - * Init the volume for speakers/micro from 0 to 100 value - */ - void initVolume(); - /** * Switch of current call id * @param id The new callid @@ -981,19 +892,18 @@ class ManagerImpl { AudioLayer* audiodriver_; // Main thread - - DTMF* dtmfKey_; + std::tr1::shared_ptr<DTMF> dtmfKey_; ///////////////////// // Protected by Mutex ///////////////////// ost::Mutex toneMutex_; - TelephoneTone* telephoneTone_; - AudioFile *audiofile_; + std::tr1::shared_ptr<TelephoneTone> telephoneTone_; + std::tr1::shared_ptr<AudioFile> audiofile_; // To handle volume control - short speakerVolume_; - short micVolume_; + // short speakerVolume_; + // short micVolume_; // End of sound variable /** @@ -1028,13 +938,6 @@ class ManagerImpl { */ void removeWaitingCall(const std::string& id); - /** - * Tell if a call is waiting and should be remove - * @param id std::string to test - * @return bool True if the call is waiting - */ - bool isWaitingCall(const std::string& id) const; - /** Remove a CallID/std::string association * Protected by mutex * @param callID the CallID to remove @@ -1060,7 +963,6 @@ class ManagerImpl { std::map<std::string, bool> IPToIPMap_; - void setIPToIPForCall(const std::string& callID, bool IPToIP); bool isIPToIP(const std::string& callID) const; @@ -1069,9 +971,18 @@ class ManagerImpl { AccountMap accountMap_; /** - * Load the account from configuration + * Unregister all account in accountMap_ */ - void loadAccountMap(Conf::YamlParser *parser); + void unregisterAllAccounts(); + + /** + * Load the account map from configuration + */ + void loadAccountMap(Conf::YamlParser &parser); + /** + * Load default account map (no configuration) + */ + void loadDefaultAccountMap(); /** * Unload the account (delete them) @@ -1089,13 +1000,15 @@ class ManagerImpl { public: + void setIPToIPForCall(const std::string& callID, bool IPToIP); + /** Associate a new std::string to a std::string * Protected by mutex * @param callID the new CallID not in the list yet * @param accountID the known accountID present in accountMap * @return bool True if the new association is create */ - bool associateCallToAccount(const std::string& callID, const std::string& accountID); + void associateCallToAccount(const std::string& callID, const std::string& accountID); /** * Test if call is a valid call, i.e. have been created and stored in @@ -1112,13 +1025,6 @@ class ManagerImpl { return &mainBuffer_; } - /** - * Return a pointer to the instance of InstantMessaging - */ - sfl::InstantMessaging *getInstantMessageModule() { - return imModule_; - } - /** * Tell if there is a current call processed * @return bool True if there is a current call @@ -1150,6 +1056,7 @@ class ManagerImpl { * @return Account* The account pointer or 0 */ Account* getAccount(const std::string& accountID); + SIPAccount* getIP2IPAccount(); /** Return the std::string from a CallID * Protected by mutex @@ -1167,8 +1074,6 @@ class ManagerImpl { std::string getAccountIdFromNameAndServer(const std::string& userName, const std::string& server) const; - int getLocalIp2IpPort() const; - std::string getStunServer() const; void setStunServer(const std::string &server); @@ -1191,13 +1096,6 @@ class ManagerImpl { * To handle the persistent history * TODO: move this to ConfigurationManager */ - History *history_; - - /** - * Instant messaging module, resposible to initiate, format, parse, - * send, and receive instant messages. - */ - sfl::InstantMessaging *imModule_; + History history_; }; - -#endif // __MANAGER_H__ +#endif // MANAGER_IMPL_H_ diff --git a/daemon/src/preferences.cpp b/daemon/src/preferences.cpp index 98f36f2a2a5dd9e3476b49634af9fbf3958f941a..18e803ed90538543c1e839e0c7586f2e0b0785a7 100644 --- a/daemon/src/preferences.cpp +++ b/daemon/src/preferences.cpp @@ -29,15 +29,83 @@ */ #include "preferences.h" +#include "logger.h" #include "audio/alsa/alsalayer.h" #include "audio/pulseaudio/pulselayer.h" +#include "config/yamlemitter.h" +#include "config/yamlnode.h" +#include "hooks/urlhook.h" +#include "sip/sip_utils.h" #include <sstream> #include "global.h" -#include <cassert> const char * const Preferences::DFT_ZONE = "North America"; +const char * const Preferences::REGISTRATION_EXPIRE_KEY = "registrationexpire"; namespace { +// general preferences +static const char * const ORDER_KEY = "order"; +static const char * const AUDIO_API_KEY = "audioApi"; +static const char * const HISTORY_LIMIT_KEY = "historyLimit"; +static const char * const HISTORY_MAX_CALLS_KEY = "historyMaxCalls"; +static const char * const NOTIFY_MAILS_KEY = "notifyMails"; +static const char * const ZONE_TONE_CHOICE_KEY = "zoneToneChoice"; +static const char * const PORT_NUM_KEY = "portNum"; +static const char * const SEARCH_BAR_DISPLAY_KEY = "searchBarDisplay"; +static const char * const ZEROCONF_ENABLE_KEY = "zeroConfenable"; +static const char * const MD5_HASH_KEY = "md5Hash"; + +// voip preferences +static const char * const PLAY_DTMF_KEY = "playDtmf"; +static const char * const PLAY_TONES_KEY = "playTones"; +static const char * const PULSE_LENGTH_KEY = "pulseLength"; +static const char * const SYMMETRIC_RTP_KEY = "symmetric"; +static const char * const ZID_FILE_KEY = "zidFile"; + +// addressbook preferences +static const char * const PHOTO_KEY = "photo"; +static const char * const ENABLED_KEY = "enabled"; +static const char * const LIST_KEY = "list"; +static const char * const MAX_RESULTS_KEY = "maxResults"; +static const char * const BUSINESS_KEY = "business"; +static const char * const HOME_KEY = "home"; +static const char * const MOBILE_KEY = "mobile"; + +// hooks preferences +static const char * const IAX2_ENABLED_KEY = "iax2Enabled"; +static const char * const NUMBER_ADD_PREFIX_KEY = "numberAddPrefix"; +static const char * const NUMBER_ENABLED_KEY = "numberEnabled"; +static const char * const SIP_ENABLED_KEY = "sipEnabled"; +static const char * const URL_COMMAND_KEY = "urlCommand"; +static const char * const URL_SIP_FIELD_KEY = "urlSipField"; + +// audio preferences +static const char * const ALSAMAP_KEY = "alsa"; +static const char * const PULSEMAP_KEY = "pulse"; +static const char * const CARDIN_KEY = "cardIn"; +static const char * const CARDOUT_KEY = "cardOut"; +static const char * const CARDRING_KEY = "cardRing"; +static const char * const PLUGIN_KEY = "plugin"; +static const char * const SMPLRATE_KEY = "smplRate"; +static const char * const DEVICE_PLAYBACK_KEY = "devicePlayback"; +static const char * const DEVICE_RECORD_KEY = "deviceRecord"; +static const char * const DEVICE_RINGTONE_KEY = "deviceRingtone"; +static const char * const RECORDPATH_KEY = "recordPath"; +static const char * const ALWAYS_RECORDING_KEY = "alwaysRecording"; +static const char * const VOLUMEMIC_KEY = "volumeMic"; +static const char * const VOLUMESPKR_KEY = "volumeSpkr"; +static const char * const NOISE_REDUCE_KEY = "noiseReduce"; +static const char * const ECHO_CANCEL_KEY = "echoCancel"; +static const char * const ECHO_TAIL_KEY = "echoTailLength"; +static const char * const ECHO_DELAY_KEY = "echoDelayLength"; + +// shortcut preferences +static const char * const HANGUP_SHORT_KEY = "hangUp"; +static const char * const PICKUP_SHORT_KEY = "pickUp"; +static const char * const POPUP_SHORT_KEY = "popupWindow"; +static const char * const TOGGLE_HOLD_SHORT_KEY = "toggleHold"; +static const char * const TOGGLE_PICKUP_HANGUP_SHORT_KEY = "togglePickupHangup"; + static const char * const DFT_PULSE_LENGTH_STR ="250"; /** Default DTMF lenght */ static const char * const ZRTP_ZIDFILE = "zidFile"; /** The filename used for storing ZIDs */ static const char * const ALSA_DFT_CARD = "0"; /** Default sound card index */ @@ -45,7 +113,8 @@ static const char * const DFT_VOL_SPKR_STR = "100"; /** Default speaker volu static const char * const DFT_VOL_MICRO_STR = "100"; /** Default mic volume */ } // end anonymous namespace -Preferences::Preferences() : accountOrder_("") +Preferences::Preferences() : + accountOrder_("") , historyLimit_(30) , historyMaxCalls_(20) , notifyMails_(false) @@ -57,7 +126,7 @@ Preferences::Preferences() : accountOrder_("") , md5Hash_(false) {} -void Preferences::serialize(Conf::YamlEmitter *emiter) +void Preferences::serialize(Conf::YamlEmitter &emiter) { Conf::MappingNode preferencemap(NULL); @@ -80,47 +149,43 @@ void Preferences::serialize(Conf::YamlEmitter *emiter) Conf::ScalarNode zeroConfenable(zeroConfenable_); Conf::ScalarNode md5Hash(md5Hash_); - preferencemap.setKeyValue(orderKey, &order); - preferencemap.setKeyValue(historyLimitKey, &historyLimit); - preferencemap.setKeyValue(historyMaxCallsKey, &historyMaxCalls); - preferencemap.setKeyValue(notifyMailsKey, ¬ifyMails); - preferencemap.setKeyValue(zoneToneChoiceKey, &zoneToneChoice); - preferencemap.setKeyValue(registrationExpireKey, ®istrationExpire); - preferencemap.setKeyValue(portNumKey, &portNum); - preferencemap.setKeyValue(searchBarDisplayKey, &searchBarDisplay); - preferencemap.setKeyValue(zeroConfenableKey, &zeroConfenable); - preferencemap.setKeyValue(md5HashKey, &md5Hash); - - emiter->serializePreference(&preferencemap); + preferencemap.setKeyValue(ORDER_KEY, &order); + preferencemap.setKeyValue(HISTORY_LIMIT_KEY, &historyLimit); + preferencemap.setKeyValue(HISTORY_MAX_CALLS_KEY, &historyMaxCalls); + preferencemap.setKeyValue(NOTIFY_MAILS_KEY, ¬ifyMails); + preferencemap.setKeyValue(ZONE_TONE_CHOICE_KEY, &zoneToneChoice); + preferencemap.setKeyValue(REGISTRATION_EXPIRE_KEY, ®istrationExpire); + preferencemap.setKeyValue(PORT_NUM_KEY, &portNum); + preferencemap.setKeyValue(SEARCH_BAR_DISPLAY_KEY, &searchBarDisplay); + preferencemap.setKeyValue(ZEROCONF_ENABLE_KEY, &zeroConfenable); + preferencemap.setKeyValue(MD5_HASH_KEY, &md5Hash); + + emiter.serializePreference(&preferencemap, "preferences"); } -void Preferences::unserialize(Conf::MappingNode *map) +void Preferences::unserialize(const Conf::MappingNode &map) { - if (map == NULL) { - ERROR("Preference: Error: Preference map is NULL"); - return; - } - - map->getValue(orderKey, &accountOrder_); - map->getValue(historyLimitKey, &historyLimit_); - map->getValue(historyMaxCallsKey, &historyMaxCalls_); - map->getValue(notifyMailsKey, ¬ifyMails_); - map->getValue(zoneToneChoiceKey, &zoneToneChoice_); - map->getValue(registrationExpireKey, ®istrationExpire_); - map->getValue(portNumKey, &portNum_); - map->getValue(searchBarDisplayKey, &searchBarDisplay_); - map->getValue(zeroConfenableKey, &zeroConfenable_); - map->getValue(md5HashKey, &md5Hash_); + map.getValue(ORDER_KEY, &accountOrder_); + map.getValue(HISTORY_LIMIT_KEY, &historyLimit_); + map.getValue(HISTORY_MAX_CALLS_KEY, &historyMaxCalls_); + map.getValue(NOTIFY_MAILS_KEY, ¬ifyMails_); + map.getValue(ZONE_TONE_CHOICE_KEY, &zoneToneChoice_); + map.getValue(REGISTRATION_EXPIRE_KEY, ®istrationExpire_); + map.getValue(PORT_NUM_KEY, &portNum_); + map.getValue(SEARCH_BAR_DISPLAY_KEY, &searchBarDisplay_); + map.getValue(ZEROCONF_ENABLE_KEY, &zeroConfenable_); + map.getValue(MD5_HASH_KEY, &md5Hash_); } -VoipPreference::VoipPreference() : playDtmf_(true) +VoipPreference::VoipPreference() : + playDtmf_(true) , playTones_(true) , pulseLength_(atoi(DFT_PULSE_LENGTH_STR)) , symmetricRtp_(true) , zidFile_(ZRTP_ZIDFILE) {} -void VoipPreference::serialize(Conf::YamlEmitter *emitter) +void VoipPreference::serialize(Conf::YamlEmitter &emitter) { Conf::MappingNode preferencemap(NULL); @@ -132,27 +197,22 @@ void VoipPreference::serialize(Conf::YamlEmitter *emitter) Conf::ScalarNode symmetricRtp(symmetricRtp_); Conf::ScalarNode zidFile(zidFile_.c_str()); - preferencemap.setKeyValue(playDtmfKey, &playDtmf); - preferencemap.setKeyValue(playTonesKey, &playTones); - preferencemap.setKeyValue(pulseLengthKey, &pulseLength); - preferencemap.setKeyValue(symmetricRtpKey, &symmetricRtp); - preferencemap.setKeyValue(zidFileKey, &zidFile); + preferencemap.setKeyValue(PLAY_DTMF_KEY, &playDtmf); + preferencemap.setKeyValue(PLAY_TONES_KEY, &playTones); + preferencemap.setKeyValue(PULSE_LENGTH_KEY, &pulseLength); + preferencemap.setKeyValue(SYMMETRIC_RTP_KEY, &symmetricRtp); + preferencemap.setKeyValue(ZID_FILE_KEY, &zidFile); - emitter->serializeVoipPreference(&preferencemap); + emitter.serializePreference(&preferencemap, "voipPreferences"); } -void VoipPreference::unserialize(Conf::MappingNode *map) +void VoipPreference::unserialize(const Conf::MappingNode &map) { - if (!map) { - ERROR("VoipPreference: Error: Preference map is NULL"); - return; - } - - map->getValue(playDtmfKey, &playDtmf_); - map->getValue(playTonesKey, &playTones_); - map->getValue(pulseLengthKey, &pulseLength_); - map->getValue(symmetricRtpKey, &symmetricRtp_); - map->getValue(zidFileKey, &zidFile_); + map.getValue(PLAY_DTMF_KEY, &playDtmf_); + map.getValue(PLAY_TONES_KEY, &playTones_); + map.getValue(PULSE_LENGTH_KEY, &pulseLength_); + map.getValue(SYMMETRIC_RTP_KEY, &symmetricRtp_); + map.getValue(ZID_FILE_KEY, &zidFile_); } AddressbookPreference::AddressbookPreference() : photo_(true) @@ -164,7 +224,7 @@ AddressbookPreference::AddressbookPreference() : photo_(true) , mobile_(true) {} -void AddressbookPreference::serialize(Conf::YamlEmitter *emitter) +void AddressbookPreference::serialize(Conf::YamlEmitter &emitter) { Conf::MappingNode preferencemap(NULL); @@ -178,35 +238,30 @@ void AddressbookPreference::serialize(Conf::YamlEmitter *emitter) Conf::ScalarNode home(home_); Conf::ScalarNode mobile(mobile_); - preferencemap.setKeyValue(photoKey, &photo); - preferencemap.setKeyValue(enabledKey, &enabled); - preferencemap.setKeyValue(listKey, &list); - preferencemap.setKeyValue(maxResultsKey, &maxResults); - preferencemap.setKeyValue(businessKey, &business); - preferencemap.setKeyValue(homeKey, &home); - preferencemap.setKeyValue(mobileKey, &mobile); - - emitter->serializeAddressbookPreference(&preferencemap); + preferencemap.setKeyValue(PHOTO_KEY, &photo); + preferencemap.setKeyValue(ENABLED_KEY, &enabled); + preferencemap.setKeyValue(LIST_KEY, &list); + preferencemap.setKeyValue(MAX_RESULTS_KEY, &maxResults); + preferencemap.setKeyValue(BUSINESS_KEY, &business); + preferencemap.setKeyValue(HOME_KEY, &home); + preferencemap.setKeyValue(MOBILE_KEY, &mobile); + emitter.serializePreference(&preferencemap, "addressbook"); } -void AddressbookPreference::unserialize(Conf::MappingNode *map) +void AddressbookPreference::unserialize(const Conf::MappingNode &map) { - if (!map) { - ERROR("Addressbook: Error: Preference map is NULL"); - return; - } - - map->getValue(photoKey, &photo_); - map->getValue(enabledKey, &enabled_); - map->getValue(listKey, &list_); - map->getValue(maxResultsKey, &maxResults_); - map->getValue(businessKey, &business_); - map->getValue(homeKey, &home_); - map->getValue(mobileKey, &mobile_); + map.getValue(PHOTO_KEY, &photo_); + map.getValue(ENABLED_KEY, &enabled_); + map.getValue(LIST_KEY, &list_); + map.getValue(MAX_RESULTS_KEY, &maxResults_); + map.getValue(BUSINESS_KEY, &business_); + map.getValue(HOME_KEY, &home_); + map.getValue(MOBILE_KEY, &mobile_); } -HookPreference::HookPreference() : iax2Enabled_(false) +HookPreference::HookPreference() : + iax2Enabled_(false) , numberAddPrefix_("") , numberEnabled_(false) , sipEnabled_(false) @@ -214,7 +269,29 @@ HookPreference::HookPreference() : iax2Enabled_(false) , urlSipField_("X-sflphone-url") {} -void HookPreference::serialize(Conf::YamlEmitter *emitter) +HookPreference::HookPreference(const std::map<std::string, std::string> &settings) : + iax2Enabled_(settings.find("URLHOOK_IAX2_ENABLED")->second == "true") + , numberAddPrefix_(settings.find("PHONE_NUMBER_HOOK_ADD_PREFIX")->second) + , numberEnabled_(settings.find("PHONE_NUMBER_HOOK_ENABLED")->second == "true") + , sipEnabled_(settings.find("URLHOOK_SIP_ENABLED")->second == "true") + , urlCommand_(settings.find("URLHOOK_COMMAND")->second) + , urlSipField_(settings.find("URLHOOK_SIP_FIELD")->second) +{} + +std::map<std::string, std::string> HookPreference::toMap() const +{ + std::map<std::string, std::string> settings; + settings["URLHOOK_IAX2_ENABLED"] = iax2Enabled_ ? "true" : "false"; + settings["PHONE_NUMBER_HOOK_ADD_PREFIX"] = numberAddPrefix_; + settings["PHONE_NUMBER_HOOK_ENABLED"] = numberEnabled_ ? "true" : "false"; + settings["URLHOOK_SIP_ENABLED"] = sipEnabled_ ? "true" : "false"; + settings["URLHOOK_COMMAND"] = urlCommand_; + settings["URLHOOK_SIP_FIELD"] = urlSipField_; + + return settings; +} + +void HookPreference::serialize(Conf::YamlEmitter &emitter) { Conf::MappingNode preferencemap(NULL); @@ -225,45 +302,48 @@ void HookPreference::serialize(Conf::YamlEmitter *emitter) Conf::ScalarNode urlCommand(urlCommand_); Conf::ScalarNode urlSipField(urlSipField_); - preferencemap.setKeyValue(iax2EnabledKey, &iax2Enabled); - preferencemap.setKeyValue(numberAddPrefixKey, &numberAddPrefix); - preferencemap.setKeyValue(numberEnabledKey, &numberEnabled); - preferencemap.setKeyValue(sipEnabledKey, &sipEnabled); - preferencemap.setKeyValue(urlCommandKey, &urlCommand); - preferencemap.setKeyValue(urlSipFieldKey, &urlSipField); + preferencemap.setKeyValue(IAX2_ENABLED_KEY, &iax2Enabled); + preferencemap.setKeyValue(NUMBER_ADD_PREFIX_KEY, &numberAddPrefix); + preferencemap.setKeyValue(NUMBER_ENABLED_KEY, &numberEnabled); + preferencemap.setKeyValue(SIP_ENABLED_KEY, &sipEnabled); + preferencemap.setKeyValue(URL_COMMAND_KEY, &urlCommand); + preferencemap.setKeyValue(URL_SIP_FIELD_KEY, &urlSipField); - emitter->serializeHooksPreference(&preferencemap); + emitter.serializePreference(&preferencemap, "hooks"); } -void HookPreference::unserialize(Conf::MappingNode *map) +void HookPreference::unserialize(const Conf::MappingNode &map) { - if (!map) { - ERROR("Hook: Error: Preference map is NULL"); - return; - } + map.getValue(IAX2_ENABLED_KEY, &iax2Enabled_); + map.getValue(NUMBER_ADD_PREFIX_KEY, &numberAddPrefix_); + map.getValue(NUMBER_ENABLED_KEY, &numberEnabled_); + map.getValue(SIP_ENABLED_KEY, &sipEnabled_); + map.getValue(URL_COMMAND_KEY, &urlCommand_); + map.getValue(URL_SIP_FIELD_KEY, &urlSipField_); +} - map->getValue(iax2EnabledKey, &iax2Enabled_); - map->getValue(numberAddPrefixKey, &numberAddPrefix_); - map->getValue(numberEnabledKey, &numberEnabled_); - map->getValue(sipEnabledKey, &sipEnabled_); - map->getValue(urlCommandKey, &urlCommand_); - map->getValue(urlSipFieldKey, &urlSipField_); +void HookPreference::runHook(pjsip_msg *msg) +{ + if (sipEnabled_) { + const std::string header(sip_utils::fetchHeaderValue(msg, urlSipField_)); + UrlHook::runAction(urlCommand_, header); + } } AudioPreference::AudioPreference() : audioApi_(PULSEAUDIO_API_STR) - , cardin_(atoi(ALSA_DFT_CARD)) // ALSA_DFT_CARD - , cardout_(atoi(ALSA_DFT_CARD)) // ALSA_DFT_CARD - , cardring_(atoi(ALSA_DFT_CARD)) // ALSA_DFT_CARD - , plugin_("default") // PCM_DEFAULT - , smplrate_(44100) // DFT_SAMPLE_RATE + , cardin_(atoi(ALSA_DFT_CARD)) + , cardout_(atoi(ALSA_DFT_CARD)) + , cardring_(atoi(ALSA_DFT_CARD)) + , plugin_("default") + , smplrate_(44100) , devicePlayback_("") , deviceRecord_("") , deviceRingtone_("") - , recordpath_("") // DFT_RECORD_PATH + , recordpath_("") , alwaysRecording_(false) - , volumemic_(atoi(DFT_VOL_SPKR_STR)) // DFT_VOL_SPKR_STR - , volumespkr_(atoi(DFT_VOL_MICRO_STR)) // DFT_VOL_MICRO_STR + , volumemic_(atoi(DFT_VOL_SPKR_STR)) + , volumespkr_(atoi(DFT_VOL_MICRO_STR)) , noisereduce_(true) , echocancel_(false) , echoCancelTailLength_(100) @@ -303,7 +383,7 @@ AudioLayer* AudioPreference::switchAndCreateAudioLayer() return createAudioLayer(); } -void AudioPreference::serialize(Conf::YamlEmitter *emitter) +void AudioPreference::serialize(Conf::YamlEmitter &emitter) { Conf::MappingNode preferencemap(NULL); Conf::MappingNode alsapreferencemap(NULL); @@ -343,68 +423,64 @@ void AudioPreference::serialize(Conf::YamlEmitter *emitter) Conf::ScalarNode noise(noisereduce_); Conf::ScalarNode echo(echocancel_); std::stringstream tailstr; - DEBUG("************************************************** serialize echotail %d", echoCancelTailLength_); tailstr << echoCancelTailLength_; Conf::ScalarNode echotail(tailstr.str()); std::stringstream delaystr; - DEBUG("************************************************** serialize echodelay %d", echoCancelTailLength_); delaystr << echoCancelDelay_; Conf::ScalarNode echodelay(delaystr.str()); - preferencemap.setKeyValue(audioApiKey, &audioapi); - preferencemap.setKeyValue(recordpathKey, &recordpath); - preferencemap.setKeyValue(alwaysRecordingKey, &alwaysRecording); - preferencemap.setKeyValue(volumemicKey, &volumemic); - preferencemap.setKeyValue(volumespkrKey, &volumespkr); - - preferencemap.setKeyValue(alsamapKey, &alsapreferencemap); - alsapreferencemap.setKeyValue(cardinKey, &cardin); - alsapreferencemap.setKeyValue(cardoutKey, &cardout); - alsapreferencemap.setKeyValue(cardringKey, &cardring); - alsapreferencemap.setKeyValue(pluginKey, &plugin); - alsapreferencemap.setKeyValue(smplrateKey, &smplrate); - - preferencemap.setKeyValue(pulsemapKey, &pulsepreferencemap); - pulsepreferencemap.setKeyValue(devicePlaybackKey, &devicePlayback); - pulsepreferencemap.setKeyValue(deviceRecordKey, &deviceRecord); - pulsepreferencemap.setKeyValue(deviceRingtoneKey, &deviceRingtone); - - preferencemap.setKeyValue(noiseReduceKey, &noise); - preferencemap.setKeyValue(echoCancelKey, &echo); - preferencemap.setKeyValue(echoTailKey, &echotail); - preferencemap.setKeyValue(echoDelayKey, &echodelay); - - emitter->serializeAudioPreference(&preferencemap); + preferencemap.setKeyValue(AUDIO_API_KEY, &audioapi); + preferencemap.setKeyValue(RECORDPATH_KEY, &recordpath); + preferencemap.setKeyValue(ALWAYS_RECORDING_KEY, &alwaysRecording); + preferencemap.setKeyValue(VOLUMEMIC_KEY, &volumemic); + preferencemap.setKeyValue(VOLUMESPKR_KEY, &volumespkr); + + preferencemap.setKeyValue(ALSAMAP_KEY, &alsapreferencemap); + alsapreferencemap.setKeyValue(CARDIN_KEY, &cardin); + alsapreferencemap.setKeyValue(CARDOUT_KEY, &cardout); + alsapreferencemap.setKeyValue(CARDRING_KEY, &cardring); + alsapreferencemap.setKeyValue(PLUGIN_KEY, &plugin); + alsapreferencemap.setKeyValue(SMPLRATE_KEY, &smplrate); + + preferencemap.setKeyValue(PULSEMAP_KEY, &pulsepreferencemap); + pulsepreferencemap.setKeyValue(DEVICE_PLAYBACK_KEY, &devicePlayback); + pulsepreferencemap.setKeyValue(DEVICE_RECORD_KEY, &deviceRecord); + pulsepreferencemap.setKeyValue(DEVICE_RINGTONE_KEY, &deviceRingtone); + + preferencemap.setKeyValue(NOISE_REDUCE_KEY, &noise); + preferencemap.setKeyValue(ECHO_CANCEL_KEY, &echo); + preferencemap.setKeyValue(ECHO_TAIL_KEY, &echotail); + preferencemap.setKeyValue(ECHO_DELAY_KEY, &echodelay); + + emitter.serializePreference(&preferencemap, "audio"); } -void AudioPreference::unserialize(Conf::MappingNode *map) +void AudioPreference::unserialize(const Conf::MappingNode &map) { - assert(map); - - map->getValue(audioApiKey, &audioApi_); - map->getValue(recordpathKey, &recordpath_); - map->getValue(alwaysRecordingKey, &alwaysRecording_); - map->getValue(volumemicKey, &volumemic_); - map->getValue(volumespkrKey, &volumespkr_); - map->getValue(noiseReduceKey, &noisereduce_); - map->getValue(echoCancelKey, &echocancel_); + map.getValue(AUDIO_API_KEY, &audioApi_); + map.getValue(RECORDPATH_KEY, &recordpath_); + map.getValue(ALWAYS_RECORDING_KEY, &alwaysRecording_); + map.getValue(VOLUMEMIC_KEY, &volumemic_); + map.getValue(VOLUMESPKR_KEY, &volumespkr_); + map.getValue(NOISE_REDUCE_KEY, &noisereduce_); + map.getValue(ECHO_CANCEL_KEY, &echocancel_); - Conf::MappingNode *alsamap =(Conf::MappingNode *)(map->getValue("alsa")); + Conf::MappingNode *alsamap =(Conf::MappingNode *) map.getValue("alsa"); if (alsamap) { - alsamap->getValue(cardinKey, &cardin_); - alsamap->getValue(cardoutKey, &cardout_); - alsamap->getValue(cardringKey, &cardring_); - alsamap->getValue(smplrateKey, &smplrate_); - alsamap->getValue(pluginKey, &plugin_); + alsamap->getValue(CARDIN_KEY, &cardin_); + alsamap->getValue(CARDOUT_KEY, &cardout_); + alsamap->getValue(CARDRING_KEY, &cardring_); + alsamap->getValue(SMPLRATE_KEY, &smplrate_); + alsamap->getValue(PLUGIN_KEY, &plugin_); } - Conf::MappingNode *pulsemap =(Conf::MappingNode *)(map->getValue("pulse")); + Conf::MappingNode *pulsemap =(Conf::MappingNode *)(map.getValue("pulse")); if (pulsemap) { - pulsemap->getValue(devicePlaybackKey, &devicePlayback_); - pulsemap->getValue(deviceRecordKey, &deviceRecord_); - pulsemap->getValue(deviceRingtoneKey, &deviceRingtone_); + pulsemap->getValue(DEVICE_PLAYBACK_KEY, &devicePlayback_); + pulsemap->getValue(DEVICE_RECORD_KEY, &deviceRecord_); + pulsemap->getValue(DEVICE_RINGTONE_KEY, &deviceRingtone_); } } @@ -415,11 +491,11 @@ std::map<std::string, std::string> ShortcutPreferences::getShortcuts() const { std::map<std::string, std::string> shortcutsMap; - shortcutsMap[hangupShortKey] = hangup_; - shortcutsMap[pickupShortKey] = pickup_; - shortcutsMap[popupShortKey] = popup_; - shortcutsMap[toggleHoldShortKey] = toggleHold_; - shortcutsMap[togglePickupHangupShortKey] = togglePickupHangup_; + shortcutsMap[HANGUP_SHORT_KEY] = hangup_; + shortcutsMap[PICKUP_SHORT_KEY] = pickup_; + shortcutsMap[POPUP_SHORT_KEY] = popup_; + shortcutsMap[TOGGLE_HOLD_SHORT_KEY] = toggleHold_; + shortcutsMap[TOGGLE_PICKUP_HANGUP_SHORT_KEY] = togglePickupHangup_; return shortcutsMap; } @@ -427,15 +503,15 @@ std::map<std::string, std::string> ShortcutPreferences::getShortcuts() const void ShortcutPreferences::setShortcuts(std::map<std::string, std::string> map) { - hangup_ = map[hangupShortKey]; - pickup_ = map[pickupShortKey]; - popup_ = map[popupShortKey]; - toggleHold_ = map[toggleHoldShortKey]; - togglePickupHangup_ = map[togglePickupHangupShortKey]; + hangup_ = map[HANGUP_SHORT_KEY]; + pickup_ = map[PICKUP_SHORT_KEY]; + popup_ = map[POPUP_SHORT_KEY]; + toggleHold_ = map[TOGGLE_HOLD_SHORT_KEY]; + togglePickupHangup_ = map[TOGGLE_PICKUP_HANGUP_SHORT_KEY]; } -void ShortcutPreferences::serialize(Conf::YamlEmitter *emitter) +void ShortcutPreferences::serialize(Conf::YamlEmitter &emitter) { Conf::MappingNode preferencemap(NULL); @@ -445,26 +521,21 @@ void ShortcutPreferences::serialize(Conf::YamlEmitter *emitter) Conf::ScalarNode toggleHold(toggleHold_); Conf::ScalarNode togglePickupHangup(togglePickupHangup_); - preferencemap.setKeyValue(hangupShortKey, &hangup); - preferencemap.setKeyValue(pickupShortKey, &pickup); - preferencemap.setKeyValue(popupShortKey, &popup); - preferencemap.setKeyValue(toggleHoldShortKey, &toggleHold); - preferencemap.setKeyValue(togglePickupHangupShortKey, &togglePickupHangup); + preferencemap.setKeyValue(HANGUP_SHORT_KEY, &hangup); + preferencemap.setKeyValue(PICKUP_SHORT_KEY, &pickup); + preferencemap.setKeyValue(POPUP_SHORT_KEY, &popup); + preferencemap.setKeyValue(TOGGLE_HOLD_SHORT_KEY, &toggleHold); + preferencemap.setKeyValue(TOGGLE_PICKUP_HANGUP_SHORT_KEY, &togglePickupHangup); - emitter->serializeShortcutPreference(&preferencemap); + emitter.serializePreference(&preferencemap, "shortcuts"); } -void ShortcutPreferences::unserialize(Conf::MappingNode *map) +void ShortcutPreferences::unserialize(const Conf::MappingNode &map) { - if (map == NULL) { - ERROR("ShortcutPreference: Error: Preference map is NULL"); - return; - } - - map->getValue(hangupShortKey, &hangup_); - map->getValue(pickupShortKey, &pickup_); - map->getValue(popupShortKey, &popup_); - map->getValue(toggleHoldShortKey, &toggleHold_); - map->getValue(togglePickupHangupShortKey, &togglePickupHangup_); + map.getValue(HANGUP_SHORT_KEY, &hangup_); + map.getValue(PICKUP_SHORT_KEY, &pickup_); + map.getValue(POPUP_SHORT_KEY, &popup_); + map.getValue(TOGGLE_HOLD_SHORT_KEY, &toggleHold_); + map.getValue(TOGGLE_PICKUP_HANGUP_SHORT_KEY, &togglePickupHangup_); } diff --git a/daemon/src/preferences.h b/daemon/src/preferences.h index b056527825de51bd6728ec758bfc04173cdfe4c1..2dc73f4187f43ef7b5a03b50836e0356f9b9b168 100644 --- a/daemon/src/preferences.h +++ b/daemon/src/preferences.h @@ -32,82 +32,20 @@ #define __PREFERENCE_H__ #include "config/serializable.h" - -// general preferences -static const char * const orderKey = "order"; -static const char * const audioApiKey = "audioApi"; -static const char * const historyLimitKey = "historyLimit"; -static const char * const historyMaxCallsKey = "historyMaxCalls"; -static const char * const notifyMailsKey = "notifyMails"; -static const char * const zoneToneChoiceKey = "zoneToneChoice"; -static const char * const registrationExpireKey = "registrationExpire"; -static const char * const portNumKey = "portNum"; -static const char * const searchBarDisplayKey = "searchBarDisplay"; -static const char * const zeroConfenableKey = "zeroConfenable"; -static const char * const md5HashKey = "md5Hash"; - -// voip preferences -static const char * const playDtmfKey = "playDtmf"; -static const char * const playTonesKey = "playTones"; -static const char * const pulseLengthKey = "pulseLength"; -static const char * const symmetricRtpKey = "symmetric"; -static const char * const zidFileKey = "zidFile"; - -// addressbook preferences -static const char * const photoKey = "photo"; -static const char * const enabledKey = "enabled"; -static const char * const listKey = "list"; -static const char * const maxResultsKey = "maxResults"; -static const char * const businessKey = "business"; -static const char * const homeKey = "home"; -static const char * const mobileKey = "mobile"; - -// hooks preferences -static const char * const iax2EnabledKey = "iax2Enabled"; -static const char * const numberAddPrefixKey = "numberAddPrefix"; -static const char * const numberEnabledKey = "numberEnabled"; -static const char * const sipEnabledKey = "sipEnabled"; -static const char * const urlCommandKey = "urlCommand"; -static const char * const urlSipFieldKey = "urlSipField"; - -// audio preferences -static const char * const alsamapKey = "alsa"; -static const char * const pulsemapKey = "pulse"; -static const char * const cardinKey = "cardIn"; -static const char * const cardoutKey = "cardOut"; -static const char * const cardringKey = "cardRing"; -static const char * const pluginKey = "plugin"; -static const char * const smplrateKey = "smplRate"; -static const char * const devicePlaybackKey = "devicePlayback"; -static const char * const deviceRecordKey = "deviceRecord"; -static const char * const deviceRingtoneKey = "deviceRingtone"; -static const char * const recordpathKey = "recordPath"; -static const char * const alwaysRecordingKey = "alwaysRecording"; -static const char * const volumemicKey = "volumeMic"; -static const char * const volumespkrKey = "volumeSpkr"; -static const char * const noiseReduceKey = "noiseReduce"; -static const char * const echoCancelKey = "echoCancel"; -static const char * const echoTailKey = "echoTailLength"; -static const char * const echoDelayKey = "echoDelayLength"; - -// shortcut preferences -static const char * const hangupShortKey = "hangUp"; -static const char * const pickupShortKey = "pickUp"; -static const char * const popupShortKey = "popupWindow"; -static const char * const toggleHoldShortKey = "toggleHold"; -static const char * const togglePickupHangupShortKey = "togglePickupHangup"; +#include <string> +#include <map> class AudioLayer; class Preferences : public Serializable { public: static const char * const DFT_ZONE; + static const char * const REGISTRATION_EXPIRE_KEY; Preferences(); - virtual void serialize(Conf::YamlEmitter *emitter); - - virtual void unserialize(Conf::MappingNode *map); + virtual void serialize(Conf::YamlEmitter &emitter); + virtual void unserialize(const Conf::MappingNode &map); std::string getAccountOrder() const { return accountOrder_; @@ -204,9 +142,8 @@ class VoipPreference : public Serializable { public: VoipPreference(); - virtual void serialize(Conf::YamlEmitter *emitter); - - virtual void unserialize(Conf::MappingNode *map); + virtual void serialize(Conf::YamlEmitter &emitter); + virtual void unserialize(const Conf::MappingNode &map); bool getPlayDtmf() const { return playDtmf_; @@ -259,9 +196,8 @@ class AddressbookPreference : public Serializable { public: AddressbookPreference(); - virtual void serialize(Conf::YamlEmitter *emitter); - - virtual void unserialize(Conf::MappingNode *map); + virtual void serialize(Conf::YamlEmitter &emitter); + virtual void unserialize(const Conf::MappingNode &map); bool getPhoto() const { return photo_; @@ -326,63 +262,28 @@ class AddressbookPreference : public Serializable { bool business_; bool home_; bool mobile_; - }; +class pjsip_msg; + class HookPreference : public Serializable { public: HookPreference(); + HookPreference(const std::map<std::string, std::string> &settings); - virtual void serialize(Conf::YamlEmitter *emitter); - - virtual void unserialize(Conf::MappingNode *map); - - bool getIax2Enabled() const { - return iax2Enabled_; - } - - void setIax2Enabled(bool i) { - iax2Enabled_ = i; - } + virtual void serialize(Conf::YamlEmitter &emitter); + virtual void unserialize(const Conf::MappingNode &map); std::string getNumberAddPrefix() const { - return numberAddPrefix_; - } - - void setNumberAddPrefix(const std::string &n) { - numberAddPrefix_ = n; - } - - bool getNumberEnabled() const { - return numberEnabled_; - } - - void setNumberEnabled(bool n) { - numberEnabled_ = n; - } - - bool getSipEnabled() const { - return sipEnabled_; - } - - void setSipEnabled(bool s) { - sipEnabled_ = s; + if (numberEnabled_) + return numberAddPrefix_; + else + return ""; } - std::string getUrlCommand() const { - return urlCommand_; - } - void setUrlCommand(const std::string &u) { - urlCommand_ = u; - } - - std::string getUrlSipField() const { - return urlSipField_; - } - void setUrlSipField(const std::string &u) { - urlSipField_ = u; - } + std::map<std::string, std::string> toMap() const; + void runHook(pjsip_msg *msg); private: bool iax2Enabled_; @@ -391,7 +292,6 @@ class HookPreference : public Serializable { bool sipEnabled_; std::string urlCommand_; std::string urlSipField_; - }; class AudioPreference : public Serializable { @@ -408,9 +308,8 @@ class AudioPreference : public Serializable { audioApi_ = api; } - virtual void serialize(Conf::YamlEmitter *emitter); - - virtual void unserialize(Conf::MappingNode *map); + virtual void serialize(Conf::YamlEmitter &emitter); + virtual void unserialize(const Conf::MappingNode &map); // alsa preference int getCardin() const { @@ -567,8 +466,8 @@ class AudioPreference : public Serializable { class ShortcutPreferences : public Serializable { public: ShortcutPreferences(); - virtual void serialize(Conf::YamlEmitter *emitter); - virtual void unserialize(Conf::MappingNode *map); + virtual void serialize(Conf::YamlEmitter &emitter); + virtual void unserialize(const Conf::MappingNode &map); void setShortcuts(std::map<std::string, std::string> shortcuts); std::map<std::string, std::string> getShortcuts() const; diff --git a/daemon/src/sfl_types.h b/daemon/src/sfl_types.h new file mode 100644 index 0000000000000000000000000000000000000000..382eb1c84cd87bf7b286b01a2ad6bf89b150ea21 --- /dev/null +++ b/daemon/src/sfl_types.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef SFL_TYPES_H_ +#define SFL_TYPES_H_ + +#include <cstddef> // for size_t + +typedef short SFLDataFormat; +typedef signed short SINT16; +typedef signed int SINT32; + +static const size_t SIZEBUF = 400000; /** About 12 sec of buffering at 8000 Hz*/ + +#endif // SFL_TYPES_H_ diff --git a/daemon/src/sip/Makefile.am b/daemon/src/sip/Makefile.am index 539a041feb29a3b10efcf1f47980c79c501b4482..6ad33a74a4e1ad6832b1162ec9658c64f09a4328 100644 --- a/daemon/src/sip/Makefile.am +++ b/daemon/src/sip/Makefile.am @@ -9,12 +9,16 @@ libsiplink_la_SOURCES = \ sipaccount.cpp \ sipcall.cpp \ sipvoiplink.cpp \ + siptransport.cpp \ pattern.h \ sdes_negotiator.h \ sdp.h \ sipaccount.h \ sipcall.h \ - sipvoiplink.h + sipvoiplink.h \ + siptransport.h \ + sip_utils.cpp \ + sip_utils.h libsiplink_la_CXXFLAGS = \ @PCRE_LIBS@ diff --git a/daemon/src/sip/pattern.cpp b/daemon/src/sip/pattern.cpp index d1b139cc269f204ba49b9f7c005159030eb19985..33717457cf7fd6a5f486b3ee94b003d2af91a453 100644 --- a/daemon/src/sip/pattern.cpp +++ b/daemon/src/sip/pattern.cpp @@ -37,8 +37,7 @@ Pattern::Pattern(const std::string& pattern, const std::string& options) : pattern_(pattern), subject_(), re_(NULL), - ovector_(NULL), - ovectorSize_(0), + ovector_(), count_(0), options_(0), optionsDescription_(options) @@ -74,8 +73,6 @@ Pattern::~Pattern() { if (re_ != NULL) pcre_free(re_); - - delete[] ovector_; } void Pattern::compile() @@ -100,14 +97,10 @@ void Pattern::compile() // Allocate an appropriate amount // of memory for the output vector. int captureCount; - pcre_fullinfo(re_, NULL, PCRE_INFO_CAPTURECOUNT, &captureCount); - delete[] ovector_; - - ovector_ = new int[(captureCount + 1) * 3]; - - ovectorSize_ = (captureCount + 1) * 3; + ovector_.clear(); + ovector_.resize((captureCount + 1) * 3); } unsigned int Pattern::getCaptureGroupCount() @@ -121,11 +114,7 @@ std::vector<std::string> Pattern::groups() { const char ** stringList; - pcre_get_substring_list(subject_.c_str(), - ovector_, - count_, - &stringList); - + pcre_get_substring_list(subject_.c_str(), &ovector_[0], count_, &stringList); std::vector<std::string> matchedSubstrings; for (int i = 1; stringList[i] != NULL; i++) @@ -140,7 +129,7 @@ std::string Pattern::group(int groupNumber) { const char * stringPtr; - int rc = pcre_get_substring(subject_.substr(offset_[0]).c_str(), ovector_, + int rc = pcre_get_substring(subject_.substr(offset_[0]).c_str(), &ovector_[0], count_, groupNumber, &stringPtr); if (rc < 0) { @@ -167,7 +156,7 @@ std::string Pattern::group(const std::string& groupName) { const char * stringPtr = NULL; int rc = pcre_get_named_substring(re_, subject_.substr(offset_[0]).c_str(), - ovector_, count_, groupName.c_str(), + &ovector_[0], count_, groupName.c_str(), &stringPtr); if (rc < 0) { @@ -240,8 +229,8 @@ bool Pattern::matches(const std::string& subject) { // Try to find a match for this pattern int rc = pcre_exec(re_, NULL, subject.substr(offset_[1]).c_str(), - subject.length() - offset_[1], 0, options_, ovector_, - ovectorSize_); + subject.length() - offset_[1], 0, options_, &ovector_[0], + ovector_.size()); // Matching failed. if (rc < 0) { diff --git a/daemon/src/sip/pattern.h b/daemon/src/sip/pattern.h index a33ad4eaa90c81d4c5f4a4a898847fda79034243..428093468fd2fe97a340b72322688d64c09cabf0 100644 --- a/daemon/src/sip/pattern.h +++ b/daemon/src/sip/pattern.h @@ -311,10 +311,7 @@ class Pattern { pcre * re_; // The internal output vector used by PCRE. - int * ovector_; - - // The size of the ovector_ - int ovectorSize_; + std::vector<int> ovector_; // Current offset in the ovector_; int offset_[2]; diff --git a/daemon/src/sip/sdes_negotiator.cpp b/daemon/src/sip/sdes_negotiator.cpp index 1d0d808e13dda73498234d8de8e3ae975ac543af..8bf4cc12db3a1905f37f7771f02343dc1a4bd7ca 100644 --- a/daemon/src/sip/sdes_negotiator.cpp +++ b/daemon/src/sip/sdes_negotiator.cpp @@ -32,6 +32,7 @@ #include "pattern.h" #include <cstdio> +#include <tr1/memory> #include <iostream> #include <sstream> #include <algorithm> @@ -60,30 +61,27 @@ std::vector<CryptoAttribute *> SdesNegotiator::parse() // syntax : //a=crypto:tag 1*WSP crypto-suite 1*WSP key-params *(1*WSP session-param) - Pattern - * generalSyntaxPattern, - * tagPattern, - * cryptoSuitePattern, - * keyParamsPattern; + std::tr1::shared_ptr<Pattern> generalSyntaxPattern, tagPattern, cryptoSuitePattern, + keyParamsPattern; try { // used to match white space (which are used as separator) - generalSyntaxPattern = new Pattern("[\x20\x09]+", "g"); + generalSyntaxPattern.reset(new Pattern("[\x20\x09]+", "g")); - tagPattern = new Pattern("^a=crypto:(?P<tag>[0-9]{1,9})"); + tagPattern.reset(new Pattern("^a=crypto:(?P<tag>[0-9]{1,9})")); - cryptoSuitePattern = new Pattern( + cryptoSuitePattern.reset(new Pattern( "(?P<cryptoSuite>AES_CM_128_HMAC_SHA1_80|" \ "AES_CM_128_HMAC_SHA1_32|" \ "F8_128_HMAC_SHA1_80|" \ - "[A-Za-z0-9_]+)"); // srtp-crypto-suite-ext + "[A-Za-z0-9_]+)")); // srtp-crypto-suite-ext - keyParamsPattern = new Pattern( + keyParamsPattern.reset(new Pattern( "(?P<srtpKeyMethod>inline|[A-Za-z0-9_]+)\\:" \ "(?P<srtpKeyInfo>[A-Za-z0-9\x2B\x2F\x3D]+)" \ "(\\|2\\^(?P<lifetime>[0-9]+)\\|" \ "(?P<mkiValue>[0-9]+)\\:" \ - "(?P<mkiLength>[0-9]{1,3})\\;?)?", "g"); + "(?P<mkiLength>[0-9]{1,3})\\;?)?", "g")); } catch (const CompileError& exception) { throw ParseError("A compile exception occured on a pattern."); @@ -93,7 +91,6 @@ std::vector<CryptoAttribute *> SdesNegotiator::parse() // Take each line from the vector // and parse its content - std::vector<CryptoAttribute *> cryptoAttributeVector; for (std::vector<std::string>::iterator iter = remoteAttribute_.begin(); @@ -176,11 +173,10 @@ std::vector<CryptoAttribute *> SdesNegotiator::parse() bool SdesNegotiator::negotiate() { - - std::vector<CryptoAttribute *> cryptoAttributeVector = parse(); + std::vector<CryptoAttribute *> cryptoAttributeVector(parse()); std::vector<CryptoAttribute *>::iterator iter_offer = cryptoAttributeVector.begin(); - std::vector<CryptoSuiteDefinition>::iterator iter_local = localCapabilities_.begin(); + std::vector<CryptoSuiteDefinition>::const_iterator iter_local = localCapabilities_.begin(); bool negotiationSuccess = false; @@ -196,13 +192,14 @@ bool SdesNegotiator::negotiate() cryptoSuite_ = (*iter_offer)->getCryptoSuite(); srtpKeyMethod_ = (*iter_offer)->getSrtpKeyMethod(); srtpKeyInfo_ = (*iter_offer)->getSrtpKeyInfo(); - authTagLength_ = cryptoSuite_.substr(cryptoSuite_.size()-2, 2); + authTagLength_ = cryptoSuite_.substr(cryptoSuite_.size() - 2, 2); } - iter_local++; + ++iter_local; } - delete(*iter_offer); - iter_offer++; + delete *iter_offer; + *iter_offer = 0; + ++iter_offer; } } catch (const ParseError& exception) { diff --git a/daemon/src/sip/sdes_negotiator.h b/daemon/src/sip/sdes_negotiator.h index 7fb4213555d670af6bd32f68073584107a886c09..c6d575da1d224ded4fe91c0735b2b84081f6eba1 100644 --- a/daemon/src/sip/sdes_negotiator.h +++ b/daemon/src/sip/sdes_negotiator.h @@ -62,7 +62,7 @@ enum KeyMethod { }; struct CryptoSuiteDefinition { - char * name; + const char *name; int masterKeyLength; int masterSaltLength; int srtpLifetime; @@ -80,10 +80,10 @@ struct CryptoSuiteDefinition { * List of accepted Crypto-Suites * as defined in RFC4568 (6.2) */ -const CryptoSuiteDefinition CryptoSuites[3] = { - { (char*) "AES_CM_128_HMAC_SHA1_80", 128, 112, 48, 31, AESCounterMode, 128, HMACSHA1, 80, 80, 160, 160 }, - { (char*) "AES_CM_128_HMAC_SHA1_32", 128, 112, 48, 31, AESCounterMode, 128, HMACSHA1, 32, 80, 160, 160 }, - { (char*) "F8_128_HMAC_SHA1_80", 128, 112, 48, 31, AESF8Mode, 128, HMACSHA1, 80, 80, 160, 160 } +static const CryptoSuiteDefinition CryptoSuites[] = { + { "AES_CM_128_HMAC_SHA1_80", 128, 112, 48, 31, AESCounterMode, 128, HMACSHA1, 80, 80, 160, 160 }, + { "AES_CM_128_HMAC_SHA1_32", 128, 112, 48, 31, AESCounterMode, 128, HMACSHA1, 32, 80, 160, 160 }, + { "F8_128_HMAC_SHA1_80", 128, 112, 48, 31, AESF8Mode, 128, HMACSHA1, 80, 80, 160, 160 } }; diff --git a/daemon/src/sip/sdp.cpp b/daemon/src/sip/sdp.cpp index 2034f39c71f43d8e527d620fe98d13246531fe04..cc895e3afff4d2e49d0671260e439c2378e43f6c 100644 --- a/daemon/src/sip/sdp.cpp +++ b/daemon/src/sip/sdp.cpp @@ -31,7 +31,7 @@ */ #include "sdp.h" -#include "global.h" +#include "logger.h" #include "manager.h" #include <cassert> @@ -92,7 +92,7 @@ void Sdp::setActiveRemoteSdpSession(const pjmedia_sdp_session *sdp) activeRemoteSession_ = (pjmedia_sdp_session*) sdp; if (!sdp) { - ERROR("Sdp: Error: Remote sdp is NULL while parsing telephone event attribute"); + ERROR("Remote sdp is NULL while parsing telephone event attribute"); return; } @@ -111,7 +111,7 @@ void Sdp::setActiveRemoteSdpSession(const pjmedia_sdp_session *sdp) return; } - ERROR("Sdp: Error: Could not found dtmf event from remote sdp"); + ERROR("Could not found dtmf event from remote sdp"); } std::string Sdp::getCodecName() @@ -207,7 +207,7 @@ void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med) void Sdp::setLocalMediaCapabilities(const CodecOrder &selectedCodecs) { - if (selectedCodecs.size() == 0) + if (selectedCodecs.empty()) WARN("No selected codec while building local SDP offer"); codec_list_.clear(); @@ -227,7 +227,7 @@ namespace { { char buffer[2048]; size_t size = pjmedia_sdp_print(session, buffer, sizeof(buffer)); - std::string sessionStr(buffer, size); + std::string sessionStr(buffer, std::min(size, sizeof(buffer))); DEBUG("%s", sessionStr.c_str()); } } @@ -237,6 +237,11 @@ int Sdp::createLocalSession(const CodecOrder &selectedCodecs) setLocalMediaCapabilities(selectedCodecs); localSession_ = PJ_POOL_ZALLOC_T(memPool_, pjmedia_sdp_session); + if (!localSession_) { + ERROR("Could not create local SDP session"); + return !PJ_SUCCESS; + } + localSession_->conn = PJ_POOL_ZALLOC_T(memPool_, pjmedia_sdp_conn); /* Initialize the fields of the struct */ @@ -270,7 +275,7 @@ int Sdp::createLocalSession(const CodecOrder &selectedCodecs) if (!srtpCrypto_.empty()) addSdesAttribute(srtpCrypto_); - DEBUG("SDP: Local SDP Session:"); + DEBUG("Local SDP Session:"); printSession(localSession_); return pjmedia_sdp_validate(localSession_); @@ -279,60 +284,59 @@ int Sdp::createLocalSession(const CodecOrder &selectedCodecs) void Sdp::createOffer(const CodecOrder &selectedCodecs) { if (createLocalSession(selectedCodecs) != PJ_SUCCESS) - ERROR("SDP: Error: Failed to create initial offer"); + ERROR("Failed to create initial offer"); else if (pjmedia_sdp_neg_create_w_local_offer(memPool_, localSession_, &negotiator_) != PJ_SUCCESS) - ERROR("SDP: Error: Failed to create an initial SDP negotiator"); + ERROR("Failed to create an initial SDP negotiator"); } void Sdp::receiveOffer(const pjmedia_sdp_session* remote, const CodecOrder &selectedCodecs) { - assert(remote); + if (!remote) { + ERROR("Remote session is NULL"); + return; + } - DEBUG("SDP: Remote SDP Session:"); + DEBUG("Remote SDP Session:"); printSession(remote); if (localSession_ == NULL && createLocalSession(selectedCodecs) != PJ_SUCCESS) { - ERROR("SDP: Failed to create initial offer"); + ERROR("Failed to create initial offer"); return; } remoteSession_ = pjmedia_sdp_session_clone(memPool_, remote); - pj_status_t status = pjmedia_sdp_neg_create_w_remote_offer(memPool_, localSession_, - remoteSession_, &negotiator_); - - assert(status == PJ_SUCCESS); -} - -void Sdp::receivingAnswerAfterInitialOffer(const pjmedia_sdp_session* remote) -{ - assert(pjmedia_sdp_neg_get_state(negotiator_) == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER); - assert(pjmedia_sdp_neg_set_remote_answer(memPool_, negotiator_, remote) == PJ_SUCCESS); - assert(pjmedia_sdp_neg_get_state(negotiator_) == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO); + if (pjmedia_sdp_neg_create_w_remote_offer(memPool_, localSession_, + remoteSession_, &negotiator_) != PJ_SUCCESS) { + ERROR("Could not create negotiator with remote offer"); + negotiator_ = NULL; + } } - void Sdp::startNegotiation() { + if (negotiator_ == NULL) { + ERROR("Can't start negotiation with invalid negotiator"); + return; + } + const pjmedia_sdp_session *active_local; const pjmedia_sdp_session *active_remote; - assert(negotiator_); - if (pjmedia_sdp_neg_get_state(negotiator_) != PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) - WARN("SDP: Warning: negotiator not in right state for negotiation"); + WARN("Negotiator not in right state for negotiation"); if (pjmedia_sdp_neg_negotiate(memPool_, negotiator_, 0) != PJ_SUCCESS) return; if (pjmedia_sdp_neg_get_active_local(negotiator_, &active_local) != PJ_SUCCESS) - ERROR("SDP: Could not retrieve local active session"); + ERROR("Could not retrieve local active session"); else setActiveLocalSdpSession(active_local); if (pjmedia_sdp_neg_get_active_remote(negotiator_, &active_remote) != PJ_SUCCESS) - ERROR("SDP: Could not retrieve remote active session"); + ERROR("Could not retrieve remote active session"); else setActiveRemoteSdpSession(active_remote); } @@ -368,18 +372,20 @@ Sdp::~Sdp() void Sdp::addAttributeToLocalAudioMedia(const char *attr) { - pjmedia_sdp_media_add_attr(localSession_->media[0], pjmedia_sdp_attr_create(memPool_, attr, NULL)); + if (localSession_) + pjmedia_sdp_media_add_attr(localSession_->media[0], pjmedia_sdp_attr_create(memPool_, attr, NULL)); } void Sdp::removeAttributeFromLocalAudioMedia(const char *attr) { - pjmedia_sdp_media_remove_all_attr(localSession_->media[0], attr); + if (localSession_) + pjmedia_sdp_media_remove_all_attr(localSession_->media[0], attr); } void Sdp::setMediaTransportInfoFromRemoteSdp() { if (!activeRemoteSession_) { - ERROR("Sdp: Error: Remote sdp is NULL while parsing media"); + ERROR("Remote sdp is NULL while parsing media"); return; } @@ -390,13 +396,11 @@ void Sdp::setMediaTransportInfoFromRemoteSdp() return; } - ERROR("SDP: No remote sdp media found in the remote offer"); + ERROR("No remote sdp media found in the remote offer"); } void Sdp::getRemoteSdpCryptoFromOffer(const pjmedia_sdp_session* remote_sdp, CryptoOffer& crypto_offer) { - CryptoOffer remoteOffer; - for (unsigned i = 0; i < remote_sdp->media_count; ++i) { pjmedia_sdp_media *media = remote_sdp->media[i]; diff --git a/daemon/src/sip/sdp.h b/daemon/src/sip/sdp.h index 7c467fc5faf588e9d551052529226f4a8dcd09f7..28ffec8e4db3944fb0b658bf42cbc7c149ca3b24 100644 --- a/daemon/src/sip/sdp.h +++ b/daemon/src/sip/sdp.h @@ -252,7 +252,7 @@ class Sdp { * Set the SRTP master_key * @param mk The Master Key of a srtp session. */ - void setLocalSdpCrypto(const std::vector<std::string> lc) { + void setLocalSdpCrypto(const std::vector<std::string> &lc) { srtpCrypto_ = lc; } @@ -274,10 +274,9 @@ class Sdp { std::string getCodecName(); - void receivingAnswerAfterInitialOffer(const pjmedia_sdp_session* remote); - private: NON_COPYABLE(Sdp); + friend class SDPTest; /** * The pool to allocate memory, ownership to SipCall diff --git a/daemon/src/sip/sip_utils.cpp b/daemon/src/sip/sip_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdcd57542a5971163f42355df615fb8172d75810 --- /dev/null +++ b/daemon/src/sip/sip_utils.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include <pjsip.h> +#include <pjlib.h> +#include <pjsip_ua.h> +#include <pjlib-util.h> +#include <pjnath.h> +#include <pjnath/stun_config.h> +#include <pj/string.h> +#include <pjsip/sip_msg.h> +#include <pjsip/sip_types.h> +#include <pjsip/sip_uri.h> +#include <pj/list.h> +#include "sip_utils.h" + +std::string +sip_utils::fetchHeaderValue(pjsip_msg *msg, const std::string &field) +{ + pj_str_t name = pj_str((char*) field.c_str()); + pjsip_generic_string_hdr *hdr = static_cast<pjsip_generic_string_hdr*>(pjsip_msg_find_hdr_by_name(msg, &name, NULL)); + + if (!hdr) + return ""; + + std::string value(hdr->hvalue.ptr, hdr->hvalue.slen); + + size_t pos = value.find("\n"); + + if (pos != std::string::npos) + return value.substr(0, pos); + else + return ""; +} + +pjsip_route_hdr * +sip_utils::createRouteSet(const std::string &route, pj_pool_t *hdr_pool) +{ + int port = 0; + std::string host; + + size_t found = route.find(":"); + + if (found != std::string::npos) { + host = route.substr(0, found); + port = atoi(route.substr(found + 1, route.length()).c_str()); + } else + host = route; + + pjsip_route_hdr *route_set = pjsip_route_hdr_create(hdr_pool); + pjsip_route_hdr *routing = pjsip_route_hdr_create(hdr_pool); + pjsip_sip_uri *url = pjsip_sip_uri_create(hdr_pool, 0); + url->lr_param = 1; + routing->name_addr.uri = (pjsip_uri*) url; + pj_strdup2(hdr_pool, &url->host, host.c_str()); + url->port = port; + + pj_list_push_back(route_set, pjsip_hdr_clone(hdr_pool, routing)); + + return route_set; +} + + +std::string +sip_utils::parseDisplayName(const char * buffer) +{ + const char* from_header = strstr(buffer, "From: "); + + if (!from_header) + return ""; + + std::string temp(from_header); + size_t begin_displayName = temp.find("\"") + 1; + size_t end_displayName = temp.rfind("\""); + std::string displayName(temp.substr(begin_displayName, end_displayName - begin_displayName)); + + static const size_t MAX_DISPLAY_NAME_SIZE = 25; + if (displayName.size() > MAX_DISPLAY_NAME_SIZE) + return ""; + + return displayName; +} + +void +sip_utils::stripSipUriPrefix(std::string& sipUri) +{ + // Remove sip: prefix + static const char SIP_PREFIX[] = "sip:"; + size_t found = sipUri.find(SIP_PREFIX); + + if (found != std::string::npos) + sipUri.erase(found, found + (sizeof SIP_PREFIX) - 1); + + found = sipUri.find("@"); + + if (found != std::string::npos) + sipUri.erase(found); +} diff --git a/daemon/src/sip/sip_utils.h b/daemon/src/sip/sip_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..4d430af97c99fd307eb7e67483cedba6ee128ef9 --- /dev/null +++ b/daemon/src/sip/sip_utils.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef SIP_UTILS_H_ +#define SIP_UTILS_H_ + +#include <string> + +#include <pjsip/sip_msg.h> + +class pjsip_msg; + +namespace sip_utils { + /** + * Helper function to parser header from incoming sip messages + * @return Header from SIP message + */ + std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field); + + pjsip_route_hdr *createRouteSet(const std::string &route, pj_pool_t *hdr_pool); + + void stripSipUriPrefix(std::string& sipUri); + + std::string parseDisplayName(const char * buffer); +} + +#endif // SIP_UTILS_H_ diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index bd57505637c48fc32e8bcd72bbac48e64266e28e..d89a1698fd034e673cb8566e2a492cc56ad1798b 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -30,19 +30,27 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "sipaccount.h" #include "sipvoiplink.h" +#include "config/yamlnode.h" +#include "config/yamlemitter.h" +#include "logger.h" #include "manager.h" -#include "config.h" #include <pwd.h> #include <sstream> -#include <cassert> +#include <stdlib.h> +const char * const SIPAccount::IP2IP_PROFILE = "IP2IP"; const char * const SIPAccount::OVERRTP_STR = "overrtp"; const char * const SIPAccount::SIPINFO_STR = "sipinfo"; namespace { - const int MIN_REGISTRATION_TIME = 600; + const int MIN_REGISTRATION_TIME = 60; + const int DEFAULT_REGISTRATION_TIME = 3600; } SIPAccount::SIPAccount(const std::string& accountID) @@ -60,15 +68,14 @@ SIPAccount::SIPAccount(const std::string& accountID) , serviceRoute_() , tlsListenerPort_(DEFAULT_SIP_TLS_PORT) , transportType_(PJSIP_TRANSPORT_UNSPECIFIED) - , cred_(NULL) + , cred_() , tlsSetting_() , contactHeader_() , contactUpdateEnabled_(false) , stunServerName_() - , stunPort_(0) + , stunPort_(PJ_STUN_PORT) , dtmfType_(OVERRTP_STR) , tlsEnable_("false") - , tlsPort_(DEFAULT_SIP_TLS_PORT) , tlsCaListFile_() , tlsCertificateFile_() , tlsPrivateKeyFile_() @@ -91,16 +98,15 @@ SIPAccount::SIPAccount(const std::string& accountID) , zrtpHelloHash_(true) , zrtpNotSuppWarning_(true) , registrationStateDetailed_() + , keepAliveEnabled_(false) , keepAliveTimer_() + , keepAliveTimerActive_(false) , link_(SIPVoIPLink::instance()) + , receivedParameter_() + , rPort_(-1) {} -SIPAccount::~SIPAccount() -{ - delete [] cred_; -} - -void SIPAccount::serialize(Conf::YamlEmitter *emitter) +void SIPAccount::serialize(Conf::YamlEmitter &emitter) { using namespace Conf; MappingNode accountmap(NULL); @@ -116,13 +122,14 @@ void SIPAccount::serialize(Conf::YamlEmitter *emitter) ScalarNode type(Account::type_); std::stringstream registrationExpireStr; registrationExpireStr << registrationExpire_; - ScalarNode expire(registrationExpireStr); + ScalarNode expire(registrationExpireStr.str()); ScalarNode interface(interface_); std::stringstream portstr; portstr << localPort_; ScalarNode port(portstr.str()); ScalarNode serviceRoute(serviceRoute_); ScalarNode contactUpdateEnabled(contactUpdateEnabled_); + ScalarNode keepAliveEnabled(keepAliveEnabled_); ScalarNode mailbox(mailBox_); ScalarNode publishAddr(publishedIpAddress_); @@ -152,7 +159,7 @@ void SIPAccount::serialize(Conf::YamlEmitter *emitter) ScalarNode notSuppWarning(zrtpNotSuppWarning_); portstr.str(""); - portstr << tlsPort_; + portstr << tlsListenerPort_; ScalarNode tlsport(portstr.str()); ScalarNode certificate(tlsCertificateFile_); ScalarNode calist(tlsCaListFile_); @@ -167,161 +174,156 @@ void SIPAccount::serialize(Conf::YamlEmitter *emitter) ScalarNode verifyclient(tlsVerifyServer_); ScalarNode verifyserver(tlsVerifyClient_); - accountmap.setKeyValue(aliasKey, &alias); - accountmap.setKeyValue(typeKey, &type); - accountmap.setKeyValue(idKey, &id); - accountmap.setKeyValue(usernameKey, &username); - accountmap.setKeyValue(hostnameKey, &hostname); - accountmap.setKeyValue(accountEnableKey, &enable); - accountmap.setKeyValue(mailboxKey, &mailbox); - accountmap.setKeyValue(registrationExpireKey, &expire); - accountmap.setKeyValue(interfaceKey, &interface); - accountmap.setKeyValue(portKey, &port); - accountmap.setKeyValue(stunServerKey, &stunServer); - accountmap.setKeyValue(stunEnabledKey, &stunEnabled); - accountmap.setKeyValue(publishAddrKey, &publishAddr); - accountmap.setKeyValue(publishPortKey, &publishPort); - accountmap.setKeyValue(sameasLocalKey, &sameasLocal); - accountmap.setKeyValue(serviceRouteKey, &serviceRoute); - accountmap.setKeyValue(updateContactHeaderKey, &contactUpdateEnabled); - accountmap.setKeyValue(dtmfTypeKey, &dtmfType); - accountmap.setKeyValue(displayNameKey, &displayName); - accountmap.setKeyValue(codecsKey, &codecs); - accountmap.setKeyValue(ringtonePathKey, &ringtonePath); - accountmap.setKeyValue(ringtoneEnabledKey, &ringtoneEnabled); - - accountmap.setKeyValue(srtpKey, &srtpmap); - srtpmap.setKeyValue(srtpEnableKey, &srtpenabled); - srtpmap.setKeyValue(keyExchangeKey, &keyExchange); - srtpmap.setKeyValue(rtpFallbackKey, &rtpFallback); - - accountmap.setKeyValue(zrtpKey, &zrtpmap); - zrtpmap.setKeyValue(displaySasKey, &displaySas); - zrtpmap.setKeyValue(displaySasOnceKey, &displaySasOnce); - zrtpmap.setKeyValue(helloHashEnabledKey, &helloHashEnabled); - zrtpmap.setKeyValue(notSuppWarningKey, ¬SuppWarning); + accountmap.setKeyValue(ALIAS_KEY, &alias); + accountmap.setKeyValue(TYPE_KEY, &type); + accountmap.setKeyValue(ID_KEY, &id); + accountmap.setKeyValue(USERNAME_KEY, &username); + accountmap.setKeyValue(HOSTNAME_KEY, &hostname); + accountmap.setKeyValue(ACCOUNT_ENABLE_KEY, &enable); + accountmap.setKeyValue(MAILBOX_KEY, &mailbox); + accountmap.setKeyValue(Preferences::REGISTRATION_EXPIRE_KEY, &expire); + accountmap.setKeyValue(INTERFACE_KEY, &interface); + accountmap.setKeyValue(PORT_KEY, &port); + accountmap.setKeyValue(STUN_SERVER_KEY, &stunServer); + accountmap.setKeyValue(STUN_ENABLED_KEY, &stunEnabled); + accountmap.setKeyValue(PUBLISH_ADDR_KEY, &publishAddr); + accountmap.setKeyValue(PUBLISH_PORT_KEY, &publishPort); + accountmap.setKeyValue(SAME_AS_LOCAL_KEY, &sameasLocal); + accountmap.setKeyValue(SERVICE_ROUTE_KEY, &serviceRoute); + accountmap.setKeyValue(UPDATE_CONTACT_HEADER_KEY, &contactUpdateEnabled); + accountmap.setKeyValue(DTMF_TYPE_KEY, &dtmfType); + accountmap.setKeyValue(DISPLAY_NAME_KEY, &displayName); + accountmap.setKeyValue(CODECS_KEY, &codecs); + accountmap.setKeyValue(RINGTONE_PATH_KEY, &ringtonePath); + accountmap.setKeyValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled); + accountmap.setKeyValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled); + + accountmap.setKeyValue(SRTP_KEY, &srtpmap); + srtpmap.setKeyValue(SRTP_ENABLE_KEY, &srtpenabled); + srtpmap.setKeyValue(KEY_EXCHANGE_KEY, &keyExchange); + srtpmap.setKeyValue(RTP_FALLBACK_KEY, &rtpFallback); + + accountmap.setKeyValue(ZRTP_KEY, &zrtpmap); + zrtpmap.setKeyValue(DISPLAY_SAS_KEY, &displaySas); + zrtpmap.setKeyValue(DISPLAY_SAS_ONCE_KEY, &displaySasOnce); + zrtpmap.setKeyValue(HELLO_HASH_ENABLED_KEY, &helloHashEnabled); + zrtpmap.setKeyValue(NOT_SUPP_WARNING_KEY, ¬SuppWarning); SequenceNode credentialseq(NULL); - accountmap.setKeyValue(credKey, &credentialseq); + accountmap.setKeyValue(CRED_KEY, &credentialseq); std::vector<std::map<std::string, std::string> >::const_iterator it; for (it = credentials_.begin(); it != credentials_.end(); ++it) { std::map<std::string, std::string> cred = *it; MappingNode *map = new MappingNode(NULL); - map->setKeyValue(USERNAME, new ScalarNode(cred[USERNAME])); - map->setKeyValue(PASSWORD, new ScalarNode(cred[PASSWORD])); - map->setKeyValue(REALM, new ScalarNode(cred[REALM])); + map->setKeyValue(CONFIG_ACCOUNT_USERNAME, new ScalarNode(cred[CONFIG_ACCOUNT_USERNAME])); + map->setKeyValue(CONFIG_ACCOUNT_PASSWORD, new ScalarNode(cred[CONFIG_ACCOUNT_PASSWORD])); + map->setKeyValue(CONFIG_ACCOUNT_REALM, new ScalarNode(cred[CONFIG_ACCOUNT_REALM])); credentialseq.addNode(map); } - accountmap.setKeyValue(tlsKey, &tlsmap); - tlsmap.setKeyValue(tlsPortKey, &tlsport); - tlsmap.setKeyValue(certificateKey, &certificate); - tlsmap.setKeyValue(calistKey, &calist); - tlsmap.setKeyValue(ciphersKey, &ciphers); - tlsmap.setKeyValue(tlsEnableKey, &tlsenabled); - tlsmap.setKeyValue(methodKey, &tlsmethod); - tlsmap.setKeyValue(timeoutKey, &timeout); - tlsmap.setKeyValue(tlsPasswordKey, &tlspassword); - tlsmap.setKeyValue(privateKeyKey, &privatekey); - tlsmap.setKeyValue(requireCertifKey, &requirecertif); - tlsmap.setKeyValue(serverKey, &server); - tlsmap.setKeyValue(verifyClientKey, &verifyclient); - tlsmap.setKeyValue(verifyServerKey, &verifyserver); + accountmap.setKeyValue(TLS_KEY, &tlsmap); + tlsmap.setKeyValue(TLS_PORT_KEY, &tlsport); + tlsmap.setKeyValue(CERTIFICATE_KEY, &certificate); + tlsmap.setKeyValue(CALIST_KEY, &calist); + tlsmap.setKeyValue(CIPHERS_KEY, &ciphers); + tlsmap.setKeyValue(TLS_ENABLE_KEY, &tlsenabled); + tlsmap.setKeyValue(METHOD_KEY, &tlsmethod); + tlsmap.setKeyValue(TIMEOUT_KEY, &timeout); + tlsmap.setKeyValue(TLS_PASSWORD_KEY, &tlspassword); + tlsmap.setKeyValue(PRIVATE_KEY_KEY, &privatekey); + tlsmap.setKeyValue(REQUIRE_CERTIF_KEY, &requirecertif); + tlsmap.setKeyValue(SERVER_KEY, &server); + tlsmap.setKeyValue(VERIFY_CLIENT_KEY, &verifyclient); + tlsmap.setKeyValue(VERIFY_SERVER_KEY, &verifyserver); try { - emitter->serializeAccount(&accountmap); + emitter.serializeAccount(&accountmap); } catch (const YamlEmitterException &e) { - ERROR("ConfigTree: %s", e.what()); + ERROR("%s", e.what()); } Sequence *seq = credentialseq.getSequence(); Sequence::iterator seqit; for (seqit = seq->begin(); seqit != seq->end(); ++seqit) { - MappingNode *node = (MappingNode*)*seqit; - delete node->getValue(USERNAME); - delete node->getValue(PASSWORD); - delete node->getValue(REALM); + MappingNode *node = static_cast<MappingNode*>(*seqit); + delete node->getValue(CONFIG_ACCOUNT_USERNAME); + delete node->getValue(CONFIG_ACCOUNT_PASSWORD); + delete node->getValue(CONFIG_ACCOUNT_REALM); delete node; } - - } -void SIPAccount::unserialize(Conf::MappingNode *map) +void SIPAccount::unserialize(const Conf::MappingNode &map) { using namespace Conf; - MappingNode *srtpMap; - MappingNode *tlsMap; - MappingNode *zrtpMap; - - assert(map); - - map->getValue(aliasKey, &alias_); - map->getValue(typeKey, &type_); - map->getValue(usernameKey, &username_); - map->getValue(hostnameKey, &hostname_); - map->getValue(accountEnableKey, &enabled_); - map->getValue(mailboxKey, &mailBox_); - map->getValue(codecsKey, &codecStr_); + + map.getValue(ALIAS_KEY, &alias_); + map.getValue(TYPE_KEY, &type_); + map.getValue(USERNAME_KEY, &username_); + map.getValue(HOSTNAME_KEY, &hostname_); + map.getValue(ACCOUNT_ENABLE_KEY, &enabled_); + map.getValue(MAILBOX_KEY, &mailBox_); + map.getValue(CODECS_KEY, &codecStr_); // Update codec list which one is used for SDP offer - setActiveCodecs(ManagerImpl::unserialize(codecStr_)); - - map->getValue(ringtonePathKey, &ringtonePath_); - map->getValue(ringtoneEnabledKey, &ringtoneEnabled_); - map->getValue(registrationExpireKey, ®istrationExpire_); - map->getValue(interfaceKey, &interface_); - int port; - map->getValue(portKey, &port); + setActiveCodecs(ManagerImpl::split_string(codecStr_)); + + map.getValue(RINGTONE_PATH_KEY, &ringtonePath_); + map.getValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled_); + map.getValue(Preferences::REGISTRATION_EXPIRE_KEY, ®istrationExpire_); + map.getValue(INTERFACE_KEY, &interface_); + int port = DEFAULT_SIP_PORT; + map.getValue(PORT_KEY, &port); localPort_ = port; - map->getValue(publishAddrKey, &publishedIpAddress_); - map->getValue(publishPortKey, &port); + map.getValue(PUBLISH_ADDR_KEY, &publishedIpAddress_); + map.getValue(PUBLISH_PORT_KEY, &port); publishedPort_ = port; - map->getValue(sameasLocalKey, &publishedSameasLocal_); + map.getValue(SAME_AS_LOCAL_KEY, &publishedSameasLocal_); + map.getValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled_); std::string dtmfType; - map->getValue(dtmfTypeKey, &dtmfType); + map.getValue(DTMF_TYPE_KEY, &dtmfType); dtmfType_ = dtmfType; - map->getValue(serviceRouteKey, &serviceRoute_); - map->getValue(updateContactHeaderKey, &contactUpdateEnabled_); + map.getValue(SERVICE_ROUTE_KEY, &serviceRoute_); + map.getValue(UPDATE_CONTACT_HEADER_KEY, &contactUpdateEnabled_); // stun enabled - map->getValue(stunEnabledKey, &stunEnabled_); - map->getValue(stunServerKey, &stunServer_); + map.getValue(STUN_ENABLED_KEY, &stunEnabled_); + map.getValue(STUN_SERVER_KEY, &stunServer_); // Init stun server name with default server name stunServerName_ = pj_str((char*) stunServer_.data()); - map->getValue(displayNameKey, &displayName_); + map.getValue(DISPLAY_NAME_KEY, &displayName_); std::vector<std::map<std::string, std::string> > creds; - YamlNode *credNode = map->getValue(credKey); + YamlNode *credNode = map.getValue(CRED_KEY); /* We check if the credential key is a sequence * because it was a mapping in a previous version of * the configuration file. */ if (credNode && credNode->getType() == SEQUENCE) { - SequenceNode *credSeq = (SequenceNode *) credNode; + SequenceNode *credSeq = static_cast<SequenceNode *>(credNode); Sequence::iterator it; Sequence *seq = credSeq->getSequence(); for (it = seq->begin(); it != seq->end(); ++it) { - MappingNode *cred = (MappingNode *)(*it); + MappingNode *cred = static_cast<MappingNode *>(*it); std::string user; std::string pass; std::string realm; - cred->getValue(USERNAME, &user); - cred->getValue(PASSWORD, &pass); - cred->getValue(REALM, &realm); + cred->getValue(CONFIG_ACCOUNT_USERNAME, &user); + cred->getValue(CONFIG_ACCOUNT_PASSWORD, &pass); + cred->getValue(CONFIG_ACCOUNT_REALM, &realm); std::map<std::string, std::string> credentialMap; - credentialMap[USERNAME] = user; - credentialMap[PASSWORD] = pass; - credentialMap[REALM] = realm; + credentialMap[CONFIG_ACCOUNT_USERNAME] = user; + credentialMap[CONFIG_ACCOUNT_PASSWORD] = pass; + credentialMap[CONFIG_ACCOUNT_REALM] = realm; creds.push_back(credentialMap); } } @@ -330,54 +332,56 @@ void SIPAccount::unserialize(Conf::MappingNode *map) // migration from old file format std::map<std::string, std::string> credmap; std::string password; - map->getValue(passwordKey, &password); + map.getValue(PASSWORD_KEY, &password); - credmap[USERNAME] = username_; - credmap[PASSWORD] = password; - credmap[REALM] = "*"; + credmap[CONFIG_ACCOUNT_USERNAME] = username_; + credmap[CONFIG_ACCOUNT_PASSWORD] = password; + credmap[CONFIG_ACCOUNT_REALM] = "*"; creds.push_back(credmap); } setCredentials(creds); // get srtp submap - srtpMap = (MappingNode *)(map->getValue(srtpKey)); + MappingNode *srtpMap = static_cast<MappingNode *>(map.getValue(SRTP_KEY)); if (srtpMap) { - srtpMap->getValue(srtpEnableKey, &srtpEnabled_); - srtpMap->getValue(keyExchangeKey, &srtpKeyExchange_); - srtpMap->getValue(rtpFallbackKey, &srtpFallback_); + srtpMap->getValue(SRTP_ENABLE_KEY, &srtpEnabled_); + srtpMap->getValue(KEY_EXCHANGE_KEY, &srtpKeyExchange_); + srtpMap->getValue(RTP_FALLBACK_KEY, &srtpFallback_); } // get zrtp submap - zrtpMap = (MappingNode *)(map->getValue(zrtpKey)); + MappingNode *zrtpMap = static_cast<MappingNode *>(map.getValue(ZRTP_KEY)); if (zrtpMap) { - zrtpMap->getValue(displaySasKey, &zrtpDisplaySas_); - zrtpMap->getValue(displaySasOnceKey, &zrtpDisplaySasOnce_); - zrtpMap->getValue(helloHashEnabledKey, &zrtpHelloHash_); - zrtpMap->getValue(notSuppWarningKey, &zrtpNotSuppWarning_); + zrtpMap->getValue(DISPLAY_SAS_KEY, &zrtpDisplaySas_); + zrtpMap->getValue(DISPLAY_SAS_ONCE_KEY, &zrtpDisplaySasOnce_); + zrtpMap->getValue(HELLO_HASH_ENABLED_KEY, &zrtpHelloHash_); + zrtpMap->getValue(NOT_SUPP_WARNING_KEY, &zrtpNotSuppWarning_); } // get tls submap - tlsMap = (MappingNode *)(map->getValue(tlsKey)); + MappingNode *tlsMap = static_cast<MappingNode *>(map.getValue(TLS_KEY)); if (tlsMap) { - tlsMap->getValue(tlsEnableKey, &tlsEnable_); - tlsMap->getValue(tlsPortKey, &tlsPort_); - tlsMap->getValue(certificateKey, &tlsCertificateFile_); - tlsMap->getValue(calistKey, &tlsCaListFile_); - tlsMap->getValue(ciphersKey, &tlsCiphers_); - tlsMap->getValue(methodKey, &tlsMethod_); - tlsMap->getValue(tlsPasswordKey, &tlsPassword_); - tlsMap->getValue(privateKeyKey, &tlsPrivateKeyFile_); - tlsMap->getValue(requireCertifKey, &tlsRequireClientCertificate_); - tlsMap->getValue(serverKey, &tlsServerName_); - tlsMap->getValue(verifyClientKey, &tlsVerifyServer_); - tlsMap->getValue(verifyServerKey, &tlsVerifyClient_); + tlsMap->getValue(TLS_ENABLE_KEY, &tlsEnable_); + std::string tlsPort; + tlsMap->getValue(TLS_PORT_KEY, &tlsPort); + tlsListenerPort_ = atoi(tlsPort.c_str()); + tlsMap->getValue(CERTIFICATE_KEY, &tlsCertificateFile_); + tlsMap->getValue(CALIST_KEY, &tlsCaListFile_); + tlsMap->getValue(CIPHERS_KEY, &tlsCiphers_); + tlsMap->getValue(METHOD_KEY, &tlsMethod_); + tlsMap->getValue(TLS_PASSWORD_KEY, &tlsPassword_); + tlsMap->getValue(PRIVATE_KEY_KEY, &tlsPrivateKeyFile_); + tlsMap->getValue(REQUIRE_CERTIF_KEY, &tlsRequireClientCertificate_); + tlsMap->getValue(SERVER_KEY, &tlsServerName_); + tlsMap->getValue(VERIFY_CLIENT_KEY, &tlsVerifyServer_); + tlsMap->getValue(VERIFY_SERVER_KEY, &tlsVerifyClient_); // FIXME - tlsMap->getValue(timeoutKey, &tlsNegotiationTimeoutSec_); - tlsMap->getValue(timeoutKey, &tlsNegotiationTimeoutMsec_); + tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutSec_); + tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutMsec_); } } @@ -387,8 +391,8 @@ void SIPAccount::setAccountDetails(std::map<std::string, std::string> details) // Account setting common to SIP and IAX alias_ = details[CONFIG_ACCOUNT_ALIAS]; type_ = details[CONFIG_ACCOUNT_TYPE]; - username_ = details[USERNAME]; - hostname_ = details[HOSTNAME]; + username_ = details[CONFIG_ACCOUNT_USERNAME]; + hostname_ = details[CONFIG_ACCOUNT_HOSTNAME]; enabled_ = details[CONFIG_ACCOUNT_ENABLE] == "true"; ringtonePath_ = details[CONFIG_RINGTONE_PATH]; ringtoneEnabled_ = details[CONFIG_RINGTONE_ENABLED] == "true"; @@ -397,54 +401,58 @@ void SIPAccount::setAccountDetails(std::map<std::string, std::string> details) // SIP specific account settings // general sip settings - displayName_ = details[DISPLAY_NAME]; - serviceRoute_ = details[ROUTESET]; - interface_ = details[LOCAL_INTERFACE]; - publishedSameasLocal_ = details[PUBLISHED_SAMEAS_LOCAL] == "true"; - publishedIpAddress_ = details[PUBLISHED_ADDRESS]; - localPort_ = atoi(details[LOCAL_PORT].c_str()); - publishedPort_ = atoi(details[PUBLISHED_PORT].c_str()); - stunServer_ = details[STUN_SERVER]; - stunEnabled_ = details[STUN_ENABLE] == "true"; - dtmfType_ = details[ACCOUNT_DTMF_TYPE]; + displayName_ = details[CONFIG_DISPLAY_NAME]; + serviceRoute_ = details[CONFIG_ACCOUNT_ROUTESET]; + interface_ = details[CONFIG_LOCAL_INTERFACE]; + publishedSameasLocal_ = details[CONFIG_PUBLISHED_SAMEAS_LOCAL] == "true"; + publishedIpAddress_ = details[CONFIG_PUBLISHED_ADDRESS]; + localPort_ = atoi(details[CONFIG_LOCAL_PORT].c_str()); + publishedPort_ = atoi(details[CONFIG_PUBLISHED_PORT].c_str()); + if (stunServer_ != details[CONFIG_STUN_SERVER]) { + link_->sipTransport.destroyStunResolver(stunServer_); + // pj_stun_sock_destroy(pj_stun_sock *stun_sock); + } + stunServer_ = details[CONFIG_STUN_SERVER]; + stunEnabled_ = details[CONFIG_STUN_ENABLE] == "true"; + dtmfType_ = details[CONFIG_ACCOUNT_DTMF_TYPE]; registrationExpire_ = atoi(details[CONFIG_ACCOUNT_REGISTRATION_EXPIRE].c_str()); + if(registrationExpire_ < MIN_REGISTRATION_TIME) + registrationExpire_ = MIN_REGISTRATION_TIME; - userAgent_ = details[USERAGENT]; + userAgent_ = details[CONFIG_ACCOUNT_USERAGENT]; + keepAliveEnabled_ = details[CONFIG_KEEP_ALIVE_ENABLED] == "true"; // srtp settings - srtpEnabled_ = details[SRTP_ENABLE] == "true"; - srtpFallback_ = details[SRTP_RTP_FALLBACK] == "true"; - zrtpDisplaySas_ = details[ZRTP_DISPLAY_SAS] == "true"; - zrtpDisplaySasOnce_ = details[ZRTP_DISPLAY_SAS_ONCE] == "true"; - zrtpNotSuppWarning_ = details[ZRTP_NOT_SUPP_WARNING] == "true"; - zrtpHelloHash_ = details[ZRTP_HELLO_HASH] == "true"; - srtpKeyExchange_ = details[SRTP_KEY_EXCHANGE]; + srtpEnabled_ = details[CONFIG_SRTP_ENABLE] == "true"; + srtpFallback_ = details[CONFIG_SRTP_RTP_FALLBACK] == "true"; + zrtpDisplaySas_ = details[CONFIG_ZRTP_DISPLAY_SAS] == "true"; + zrtpDisplaySasOnce_ = details[CONFIG_ZRTP_DISPLAY_SAS_ONCE] == "true"; + zrtpNotSuppWarning_ = details[CONFIG_ZRTP_NOT_SUPP_WARNING] == "true"; + zrtpHelloHash_ = details[CONFIG_ZRTP_HELLO_HASH] == "true"; + srtpKeyExchange_ = details[CONFIG_SRTP_KEY_EXCHANGE]; // TLS settings - // The TLS listener is unique and globally defined through IP2IP_PROFILE - if (accountID_ == IP2IP_PROFILE) - tlsListenerPort_ = atoi(details[TLS_LISTENER_PORT].c_str()); - - tlsEnable_ = details[TLS_ENABLE]; - tlsCaListFile_ = details[TLS_CA_LIST_FILE]; - tlsCertificateFile_ = details[TLS_CERTIFICATE_FILE]; - tlsPrivateKeyFile_ = details[TLS_PRIVATE_KEY_FILE]; - tlsPassword_ = details[TLS_PASSWORD]; - tlsMethod_ = details[TLS_METHOD]; - tlsCiphers_ = details[TLS_CIPHERS]; - tlsServerName_ = details[TLS_SERVER_NAME]; - tlsVerifyServer_ = details[TLS_VERIFY_SERVER] == "true"; - tlsVerifyClient_ = details[TLS_VERIFY_CLIENT] == "true"; - tlsRequireClientCertificate_ = details[TLS_REQUIRE_CLIENT_CERTIFICATE] == "true"; - tlsNegotiationTimeoutSec_ = details[TLS_NEGOTIATION_TIMEOUT_SEC]; - tlsNegotiationTimeoutMsec_ = details[TLS_NEGOTIATION_TIMEOUT_MSEC]; + tlsListenerPort_ = atoi(details[CONFIG_TLS_LISTENER_PORT].c_str()); + tlsEnable_ = details[CONFIG_TLS_ENABLE]; + tlsCaListFile_ = details[CONFIG_TLS_CA_LIST_FILE]; + tlsCertificateFile_ = details[CONFIG_TLS_CERTIFICATE_FILE]; + tlsPrivateKeyFile_ = details[CONFIG_TLS_PRIVATE_KEY_FILE]; + tlsPassword_ = details[CONFIG_TLS_PASSWORD]; + tlsMethod_ = details[CONFIG_TLS_METHOD]; + tlsCiphers_ = details[CONFIG_TLS_CIPHERS]; + tlsServerName_ = details[CONFIG_TLS_SERVER_NAME]; + tlsVerifyServer_ = details[CONFIG_TLS_VERIFY_SERVER] == "true"; + tlsVerifyClient_ = details[CONFIG_TLS_VERIFY_CLIENT] == "true"; + tlsRequireClientCertificate_ = details[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] == "true"; + tlsNegotiationTimeoutSec_ = details[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC]; + tlsNegotiationTimeoutMsec_ = details[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC]; if (credentials_.empty()) { // credentials not set, construct 1 entry std::vector<std::map<std::string, std::string> > v; std::map<std::string, std::string> map; - map[USERNAME] = username_; - map[PASSWORD] = details[PASSWORD]; - map[REALM] = "*"; + map[CONFIG_ACCOUNT_USERNAME] = username_; + map[CONFIG_ACCOUNT_PASSWORD] = details[CONFIG_ACCOUNT_PASSWORD]; + map[CONFIG_ACCOUNT_REALM] = "*"; v.push_back(map); setCredentials(v); } @@ -454,14 +462,14 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const { std::map<std::string, std::string> a; - a[ACCOUNT_ID] = accountID_; + a[CONFIG_ACCOUNT_ID] = accountID_; // The IP profile does not allow to set an alias - a[CONFIG_ACCOUNT_ALIAS] = (accountID_ == IP2IP_PROFILE) ? IP2IP_PROFILE : alias_; + a[CONFIG_ACCOUNT_ALIAS] = isIP2IP() ? IP2IP_PROFILE : alias_; a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? "true" : "false"; a[CONFIG_ACCOUNT_TYPE] = type_; - a[HOSTNAME] = hostname_; - a[USERNAME] = username_; + a[CONFIG_ACCOUNT_HOSTNAME] = hostname_; + a[CONFIG_ACCOUNT_USERNAME] = username_; a[CONFIG_RINGTONE_PATH] = ringtonePath_; a[CONFIG_RINGTONE_ENABLED] = ringtoneEnabled_ ? "true" : "false"; @@ -471,7 +479,7 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const std::string registrationStateCode; std::string registrationStateDescription; - if (accountID_ == IP2IP_PROFILE) + if (isIP2IP()) registrationStateDescription = "Direct IP call"; else { state = registrationState_; @@ -482,57 +490,58 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const registrationStateDescription = registrationStateDetailed_.second; } - a[REGISTRATION_STATUS] = (accountID_ == IP2IP_PROFILE) ? "READY": mapStateNumberToString(state); - a[REGISTRATION_STATE_CODE] = registrationStateCode; - a[REGISTRATION_STATE_DESCRIPTION] = registrationStateDescription; + a[CONFIG_ACCOUNT_REGISTRATION_STATUS] = isIP2IP() ? "READY": mapStateNumberToString(state); + a[CONFIG_ACCOUNT_REGISTRATION_STATE_CODE] = registrationStateCode; + a[CONFIG_ACCOUNT_REGISTRATION_STATE_DESC] = registrationStateDescription; // Add sip specific details - a[ROUTESET] = serviceRoute_; - a[USERAGENT] = userAgent_; + a[CONFIG_ACCOUNT_ROUTESET] = serviceRoute_; + a[CONFIG_ACCOUNT_USERAGENT] = userAgent_; std::stringstream registrationExpireStr; registrationExpireStr << registrationExpire_; a[CONFIG_ACCOUNT_REGISTRATION_EXPIRE] = registrationExpireStr.str(); - a[LOCAL_INTERFACE] = interface_; - a[PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? "true" : "false"; - a[PUBLISHED_ADDRESS] = publishedIpAddress_; + a[CONFIG_LOCAL_INTERFACE] = interface_; + a[CONFIG_PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? "true" : "false"; + a[CONFIG_PUBLISHED_ADDRESS] = publishedIpAddress_; std::stringstream localport; localport << localPort_; - a[LOCAL_PORT] = localport.str(); + a[CONFIG_LOCAL_PORT] = localport.str(); std::stringstream publishedport; publishedport << publishedPort_; - a[PUBLISHED_PORT] = publishedport.str(); - a[STUN_ENABLE] = stunEnabled_ ? "true" : "false"; - a[STUN_SERVER] = stunServer_; - a[ACCOUNT_DTMF_TYPE] = dtmfType_; + a[CONFIG_PUBLISHED_PORT] = publishedport.str(); + a[CONFIG_STUN_ENABLE] = stunEnabled_ ? "true" : "false"; + a[CONFIG_STUN_SERVER] = stunServer_; + a[CONFIG_ACCOUNT_DTMF_TYPE] = dtmfType_; + a[CONFIG_KEEP_ALIVE_ENABLED] = keepAliveEnabled_ ? "true" : "false"; - a[SRTP_KEY_EXCHANGE] = srtpKeyExchange_; - a[SRTP_ENABLE] = srtpEnabled_ ? "true" : "false"; - a[SRTP_RTP_FALLBACK] = srtpFallback_ ? "true" : "false"; + a[CONFIG_SRTP_KEY_EXCHANGE] = srtpKeyExchange_; + a[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? "true" : "false"; + a[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? "true" : "false"; - a[ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? "true" : "false"; - a[ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? "true" : "false"; - a[ZRTP_HELLO_HASH] = zrtpHelloHash_ ? "true" : "false"; - a[ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? "true" : "false"; + a[CONFIG_ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? "true" : "false"; + a[CONFIG_ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? "true" : "false"; + a[CONFIG_ZRTP_HELLO_HASH] = zrtpHelloHash_ ? "true" : "false"; + a[CONFIG_ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? "true" : "false"; // TLS listener is unique and parameters are modified through IP2IP_PROFILE std::stringstream tlslistenerport; tlslistenerport << tlsListenerPort_; - a[TLS_LISTENER_PORT] = tlslistenerport.str(); - a[TLS_ENABLE] = tlsEnable_; - a[TLS_CA_LIST_FILE] = tlsCaListFile_; - a[TLS_CERTIFICATE_FILE] = tlsCertificateFile_; - a[TLS_PRIVATE_KEY_FILE] = tlsPrivateKeyFile_; - a[TLS_PASSWORD] = tlsPassword_; - a[TLS_METHOD] = tlsMethod_; - a[TLS_CIPHERS] = tlsCiphers_; - a[TLS_SERVER_NAME] = tlsServerName_; - a[TLS_VERIFY_SERVER] = tlsVerifyServer_ ? "true" : "false"; - a[TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? "true" : "false"; - a[TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? "true" : "false"; - a[TLS_NEGOTIATION_TIMEOUT_SEC] = tlsNegotiationTimeoutSec_; - a[TLS_NEGOTIATION_TIMEOUT_MSEC] = tlsNegotiationTimeoutMsec_; + a[CONFIG_TLS_LISTENER_PORT] = tlslistenerport.str(); + a[CONFIG_TLS_ENABLE] = tlsEnable_; + a[CONFIG_TLS_CA_LIST_FILE] = tlsCaListFile_; + a[CONFIG_TLS_CERTIFICATE_FILE] = tlsCertificateFile_; + a[CONFIG_TLS_PRIVATE_KEY_FILE] = tlsPrivateKeyFile_; + a[CONFIG_TLS_PASSWORD] = tlsPassword_; + a[CONFIG_TLS_METHOD] = tlsMethod_; + a[CONFIG_TLS_CIPHERS] = tlsCiphers_; + a[CONFIG_TLS_SERVER_NAME] = tlsServerName_; + a[CONFIG_TLS_VERIFY_SERVER] = tlsVerifyServer_ ? "true" : "false"; + a[CONFIG_TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? "true" : "false"; + a[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? "true" : "false"; + a[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC] = tlsNegotiationTimeoutSec_; + a[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC] = tlsNegotiationTimeoutMsec_; return a; } @@ -544,7 +553,7 @@ void SIPAccount::registerVoIPLink() // Init TLS settings if the user wants to use TLS if (tlsEnable_ == "true") { - DEBUG("SIPAccount: TLS is enabled for account %s", accountID_.c_str()); + DEBUG("TLS is enabled for account %s", accountID_.c_str()); transportType_ = PJSIP_TRANSPORT_TLS; initTlsConfiguration(); } @@ -559,25 +568,25 @@ void SIPAccount::registerVoIPLink() // In our definition of the ip2ip profile (aka Direct IP Calls), // no registration should be performed - if (accountID_ == IP2IP_PROFILE) + if (isIP2IP()) return; try { link_->sendRegister(this); } catch (const VoipLinkException &e) { - ERROR("SIPAccount: %s", e.what()); + ERROR("%s", e.what()); } } void SIPAccount::unregisterVoIPLink() { - if (accountID_ == IP2IP_PROFILE) + if (isIP2IP()) return; try { link_->sendUnregister(this); } catch (const VoipLinkException &e) { - ERROR("SIPAccount: %s", e.what()); + ERROR("%s", e.what()); } } @@ -586,23 +595,45 @@ void SIPAccount::startKeepAliveTimer() { if (isTlsEnabled()) return; + if (isIP2IP()) + return; + + if(keepAliveTimerActive_) + return; + + DEBUG("Start keep alive timer for account %s", getAccountID().c_str()); + + // make sure here we have an entirely new timer + memset(&keepAliveTimer_, 0, sizeof(pj_timer_entry)); + pj_time_val keepAliveDelay_; keepAliveTimer_.cb = &SIPAccount::keepAliveRegistrationCb; keepAliveTimer_.user_data = this; + keepAliveTimer_.id = rand(); // expiration may be undetermined during the first registration request - if (registrationExpire_ == 0) - keepAliveDelay_.sec = 60; - else - keepAliveDelay_.sec = registrationExpire_; + if (registrationExpire_ == 0) { + DEBUG("Registration Expire: 0, taking 60 instead"); + keepAliveDelay_.sec = 3600; + } + else { + DEBUG("Registration Expire: %d", registrationExpire_); + keepAliveDelay_.sec = registrationExpire_ + MIN_REGISTRATION_TIME; + } keepAliveDelay_.msec = 0; + keepAliveTimerActive_ = true; + link_->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_); } void SIPAccount::stopKeepAliveTimer() { - link_->cancelKeepAliveTimer(keepAliveTimer_); + DEBUG("Stop keep alive timer %d for account %s", keepAliveTimer_.id, getAccountID().c_str()); + + keepAliveTimerActive_ = false; + + link_->cancelKeepAliveTimer(keepAliveTimer_); } pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum(const std::string& method) @@ -625,8 +656,6 @@ pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum(const std::string& method) void SIPAccount::initTlsConfiguration() { // TLS listener is unique and should be only modified through IP2IP_PROFILE - tlsListenerPort_ = tlsPort_; - pjsip_tls_setting_default(&tlsSetting_); pj_cstr(&tlsSetting_.ca_list_file, tlsCaListFile_.c_str()); @@ -670,7 +699,7 @@ void SIPAccount::initStunConfiguration() void SIPAccount::loadConfig() { if (registrationExpire_ == 0) - registrationExpire_ = MIN_REGISTRATION_TIME; /** Default expire value for registration */ + registrationExpire_ = DEFAULT_REGISTRATION_TIME; /** Default expire value for registration */ if (tlsEnable_ == "true") { initTlsConfiguration(); @@ -786,53 +815,75 @@ void SIPAccount::setContactHeader(std::string address, std::string port) std::string SIPAccount::getContactHeader() const { - std::string scheme; - std::string transport; + if (transport_ == NULL) + ERROR("Transport not created yet"); + + // The transport type must be specified, in our case START_OTHER refers to stun transport + pjsip_transport_type_e transportType = transportType_; + if (transportType == PJSIP_TRANSPORT_START_OTHER) + transportType = PJSIP_TRANSPORT_UDP; // Use the CONTACT header provided by the registrar if any - if(!contactHeader_.empty()) + if (!contactHeader_.empty()) return contactHeader_; // Else we determine this infor based on transport information std::string address, port; - link_->findLocalAddressFromTransport(transport_, transportType_, address, port); + std::ostringstream portstr; + + link_->sipTransport.findLocalAddressFromTransport(transport_, transportType, address, port); + + if (!receivedParameter_.empty()) + address = receivedParameter_; + + if (rPort_ != -1) { + portstr << rPort_; + port = portstr.str(); + } // UDP does not require the transport specification + std::string scheme; + std::string transport; if (transportType_ == PJSIP_TRANSPORT_TLS) { scheme = "sips:"; - transport = ";transport=" + std::string(pjsip_transport_get_type_name(transportType_)); + transport = ";transport=" + std::string(pjsip_transport_get_type_name(transportType)); } else scheme = "sip:"; return displayName_ + (displayName_.empty() ? "" : " ") + "<" + - scheme + username_ + (username_.empty() ? "":"@") + + scheme + username_ + (username_.empty() ? "" : "@") + address + ":" + port + transport + ">"; } void SIPAccount::keepAliveRegistrationCb(UNUSED pj_timer_heap_t *th, pj_timer_entry *te) { - SIPAccount *sipAccount = reinterpret_cast<SIPAccount *>(te->user_data); + SIPAccount *sipAccount = static_cast<SIPAccount *>(te->user_data); + + ERROR("Keep alive registration callback for account %s", sipAccount->getAccountID().c_str()); - if (sipAccount->isTlsEnabled()) - return; + if (sipAccount == NULL) { + ERROR("SIP account is NULL while registering a new keep alive timer"); + return; + } - if(sipAccount->isRegistered()) { + // IP2IP default does not require keep-alive + if (sipAccount->isIP2IP()) + return; - // send a new register request - sipAccount->registerVoIPLink(); + // TLS is connection oriented and does not require keep-alive + if (sipAccount->isTlsEnabled()) + return; - // make sure the current timer is deactivated - sipAccount->stopKeepAliveTimer(); + sipAccount->stopKeepAliveTimer(); - // register a new timer - sipAccount->startKeepAliveTimer(); - } + if (sipAccount->isRegistered()) + sipAccount->registerVoIPLink(); } namespace { -std::string computeMd5HashFromCredential( - const std::string& username, const std::string& password, - const std::string& realm) +std::string computeMd5HashFromCredential(const std::string& username, + const std::string& password, + const std::string& realm) { #define MD5_APPEND(pms,buf,len) pj_md5_update(pms, (const pj_uint8_t*)buf, len) @@ -845,6 +896,7 @@ std::string computeMd5HashFromCredential( MD5_APPEND(&pms, realm.data(), realm.length()); MD5_APPEND(&pms, ":", 1); MD5_APPEND(&pms, password.data(), password.length()); +#undef MD5_APPEND unsigned char digest[16]; pj_md5_final(&pms, digest); @@ -856,29 +908,31 @@ std::string computeMd5HashFromCredential( return std::string(hash, 32); } - - } // anon namespace void SIPAccount::setCredentials(const std::vector<std::map<std::string, std::string> >& creds) { + // we can not authenticate without credentials + if (creds.empty()) { + ERROR("Cannot authenticate with empty credentials list"); + return; + } + using std::vector; using std::string; using std::map; bool md5HashingEnabled = Manager::instance().preferences.getMd5Hash(); - assert(creds.size() > 0); // we can not authenticate without credentials - credentials_ = creds; /* md5 hashing */ for (vector<map<string, string> >::iterator it = credentials_.begin(); it != credentials_.end(); ++it) { - map<string, string>::const_iterator val = (*it).find(USERNAME); + map<string, string>::const_iterator val = (*it).find(CONFIG_ACCOUNT_USERNAME); const std::string username = val != (*it).end() ? val->second : ""; - val = (*it).find(REALM); + val = (*it).find(CONFIG_ACCOUNT_REALM); const std::string realm(val != (*it).end() ? val->second : ""); - val = (*it).find(PASSWORD); + val = (*it).find(CONFIG_ACCOUNT_PASSWORD); const std::string password(val != (*it).end() ? val->second : ""); if (md5HashingEnabled) { @@ -892,32 +946,30 @@ void SIPAccount::setCredentials(const std::vector<std::map<std::string, std::str // re-hash a hashed password. if (password.length() != 32) - (*it)[PASSWORD] = computeMd5HashFromCredential(username, password, realm); + (*it)[CONFIG_ACCOUNT_PASSWORD] = computeMd5HashFromCredential(username, password, realm); } } // Create the credential array - delete[] cred_; - cred_ = new pjsip_cred_info[credentials_.size()]; + cred_.resize(credentials_.size()); size_t i = 0; - for (vector<map<string, string > >::const_iterator iter = credentials_.begin(); iter != credentials_.end(); ++iter) { - map<string, string>::const_iterator val = (*iter).find(PASSWORD); + map<string, string>::const_iterator val = (*iter).find(CONFIG_ACCOUNT_PASSWORD); const std::string password = val != (*iter).end() ? val->second : ""; int dataType = (md5HashingEnabled and password.length() == 32) ? PJSIP_CRED_DATA_DIGEST : PJSIP_CRED_DATA_PLAIN_PASSWD; - val = (*iter).find(USERNAME); + val = (*iter).find(CONFIG_ACCOUNT_USERNAME); if (val != (*iter).end()) cred_[i].username = pj_str((char*) val->second.c_str()); cred_[i].data = pj_str((char*) password.c_str()); - val = (*iter).find(REALM); + val = (*iter).find(CONFIG_ACCOUNT_REALM); if (val != (*iter).end()) cred_[i].realm = pj_str((char*) val->second.c_str()); @@ -928,7 +980,8 @@ void SIPAccount::setCredentials(const std::vector<std::map<std::string, std::str } } -const std::vector<std::map<std::string, std::string> > &SIPAccount::getCredentials() +const std::vector<std::map<std::string, std::string> > & +SIPAccount::getCredentials() const { return credentials_; } @@ -945,23 +998,22 @@ std::string SIPAccount::getUserAgentName() const std::map<std::string, std::string> SIPAccount::getIp2IpDetails() const { - assert(accountID_ == IP2IP_PROFILE); + assert(isIP2IP()); std::map<std::string, std::string> ip2ipAccountDetails; - ip2ipAccountDetails[ACCOUNT_ID] = IP2IP_PROFILE; - ip2ipAccountDetails[SRTP_KEY_EXCHANGE] = srtpKeyExchange_; - ip2ipAccountDetails[SRTP_ENABLE] = srtpEnabled_ ? "true" : "false"; - ip2ipAccountDetails[SRTP_RTP_FALLBACK] = srtpFallback_ ? "true" : "false"; - ip2ipAccountDetails[ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? "true" : "false"; - ip2ipAccountDetails[ZRTP_HELLO_HASH] = zrtpHelloHash_ ? "true" : "false"; - ip2ipAccountDetails[ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? "true" : "false"; - ip2ipAccountDetails[ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? "true" : "false"; - ip2ipAccountDetails[LOCAL_INTERFACE] = interface_; + ip2ipAccountDetails[CONFIG_ACCOUNT_ID] = IP2IP_PROFILE; + ip2ipAccountDetails[CONFIG_SRTP_KEY_EXCHANGE] = srtpKeyExchange_; + ip2ipAccountDetails[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? "true" : "false"; + ip2ipAccountDetails[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? "true" : "false"; + ip2ipAccountDetails[CONFIG_ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? "true" : "false"; + ip2ipAccountDetails[CONFIG_ZRTP_HELLO_HASH] = zrtpHelloHash_ ? "true" : "false"; + ip2ipAccountDetails[CONFIG_ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? "true" : "false"; + ip2ipAccountDetails[CONFIG_ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? "true" : "false"; + ip2ipAccountDetails[CONFIG_LOCAL_INTERFACE] = interface_; std::stringstream portstr; portstr << localPort_; - ip2ipAccountDetails[LOCAL_PORT] = portstr.str(); + ip2ipAccountDetails[CONFIG_LOCAL_PORT] = portstr.str(); - std::map<std::string, std::string> tlsSettings; - tlsSettings = getTlsSettings(); + std::map<std::string, std::string> tlsSettings(getTlsSettings()); std::copy(tlsSettings.begin(), tlsSettings.end(), std::inserter( ip2ipAccountDetails, ip2ipAccountDetails.end())); @@ -970,25 +1022,25 @@ std::map<std::string, std::string> SIPAccount::getIp2IpDetails() const std::map<std::string, std::string> SIPAccount::getTlsSettings() const { + assert(isIP2IP()); std::map<std::string, std::string> tlsSettings; - assert(accountID_ == IP2IP_PROFILE); std::stringstream portstr; portstr << tlsListenerPort_; - tlsSettings[TLS_LISTENER_PORT] = portstr.str(); - tlsSettings[TLS_ENABLE] = tlsEnable_; - tlsSettings[TLS_CA_LIST_FILE] = tlsCaListFile_; - tlsSettings[TLS_CERTIFICATE_FILE] = tlsCertificateFile_; - tlsSettings[TLS_PRIVATE_KEY_FILE] = tlsPrivateKeyFile_; - tlsSettings[TLS_PASSWORD] = tlsPassword_; - tlsSettings[TLS_METHOD] = tlsMethod_; - tlsSettings[TLS_CIPHERS] = tlsCiphers_; - tlsSettings[TLS_SERVER_NAME] = tlsServerName_; - tlsSettings[TLS_VERIFY_SERVER] = tlsVerifyServer_ ? "true" : "false"; - tlsSettings[TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? "true" : "false"; - tlsSettings[TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? "true" : "false"; - tlsSettings[TLS_NEGOTIATION_TIMEOUT_SEC] = tlsNegotiationTimeoutSec_; - tlsSettings[TLS_NEGOTIATION_TIMEOUT_MSEC] = tlsNegotiationTimeoutMsec_; + tlsSettings[CONFIG_TLS_LISTENER_PORT] = portstr.str(); + tlsSettings[CONFIG_TLS_ENABLE] = tlsEnable_; + tlsSettings[CONFIG_TLS_CA_LIST_FILE] = tlsCaListFile_; + tlsSettings[CONFIG_TLS_CERTIFICATE_FILE] = tlsCertificateFile_; + tlsSettings[CONFIG_TLS_PRIVATE_KEY_FILE] = tlsPrivateKeyFile_; + tlsSettings[CONFIG_TLS_PASSWORD] = tlsPassword_; + tlsSettings[CONFIG_TLS_METHOD] = tlsMethod_; + tlsSettings[CONFIG_TLS_CIPHERS] = tlsCiphers_; + tlsSettings[CONFIG_TLS_SERVER_NAME] = tlsServerName_; + tlsSettings[CONFIG_TLS_VERIFY_SERVER] = tlsVerifyServer_ ? "true" : "false"; + tlsSettings[CONFIG_TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? "true" : "false"; + tlsSettings[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? "true" : "false"; + tlsSettings[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC] = tlsNegotiationTimeoutSec_; + tlsSettings[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC] = tlsNegotiationTimeoutMsec_; return tlsSettings; } @@ -1021,23 +1073,28 @@ void set_opt(const std::map<std::string, std::string> &details, const char *key, void SIPAccount::setTlsSettings(const std::map<std::string, std::string>& details) { - assert(accountID_ == IP2IP_PROFILE); - set_opt(details, TLS_LISTENER_PORT, tlsListenerPort_); - set_opt(details, TLS_ENABLE, tlsEnable_); - set_opt(details, TLS_CA_LIST_FILE, tlsCaListFile_); - set_opt(details, TLS_CERTIFICATE_FILE, tlsCertificateFile_); - set_opt(details, TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile_); - set_opt(details, TLS_PASSWORD, tlsPassword_); - set_opt(details, TLS_METHOD, tlsMethod_); - set_opt(details, TLS_CIPHERS, tlsCiphers_); - set_opt(details, TLS_SERVER_NAME, tlsServerName_); - set_opt(details, TLS_VERIFY_CLIENT, tlsVerifyClient_); - set_opt(details, TLS_REQUIRE_CLIENT_CERTIFICATE, tlsRequireClientCertificate_); - set_opt(details, TLS_NEGOTIATION_TIMEOUT_SEC, tlsNegotiationTimeoutSec_); - set_opt(details, TLS_NEGOTIATION_TIMEOUT_MSEC, tlsNegotiationTimeoutMsec_); + assert(isIP2IP()); + set_opt(details, CONFIG_TLS_LISTENER_PORT, tlsListenerPort_); + set_opt(details, CONFIG_TLS_ENABLE, tlsEnable_); + set_opt(details, CONFIG_TLS_CA_LIST_FILE, tlsCaListFile_); + set_opt(details, CONFIG_TLS_CERTIFICATE_FILE, tlsCertificateFile_); + set_opt(details, CONFIG_TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile_); + set_opt(details, CONFIG_TLS_PASSWORD, tlsPassword_); + set_opt(details, CONFIG_TLS_METHOD, tlsMethod_); + set_opt(details, CONFIG_TLS_CIPHERS, tlsCiphers_); + set_opt(details, CONFIG_TLS_SERVER_NAME, tlsServerName_); + set_opt(details, CONFIG_TLS_VERIFY_CLIENT, tlsVerifyClient_); + set_opt(details, CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE, tlsRequireClientCertificate_); + set_opt(details, CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC, tlsNegotiationTimeoutSec_); + set_opt(details, CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC, tlsNegotiationTimeoutMsec_); } VoIPLink* SIPAccount::getVoIPLink() { return link_; } + +bool SIPAccount::isIP2IP() const +{ + return accountID_ == IP2IP_PROFILE; +} diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h index 94986a5ae8bd8da62c4b9136a0a214a6405fc6fd..94cf4470ff1b3b5ab90c109d580548594614d64a 100644 --- a/daemon/src/sip/sipaccount.h +++ b/daemon/src/sip/sipaccount.h @@ -47,48 +47,48 @@ namespace Conf { class YamlEmitter; class MappingNode; // SIP specific configuration keys - const char *const interfaceKey = "interface"; - const char *const portKey = "port"; - const char *const publishAddrKey = "publishAddr"; - const char *const publishPortKey = "publishPort"; - const char *const sameasLocalKey = "sameasLocal"; - const char *const dtmfTypeKey = "dtmfType"; - const char *const serviceRouteKey = "serviceRoute"; - const char *const updateContactHeaderKey = "updateContact"; + const char *const INTERFACE_KEY = "interface"; + const char *const PORT_KEY = "port"; + const char *const PUBLISH_ADDR_KEY = "publishAddr"; + const char *const PUBLISH_PORT_KEY = "publishPort"; + const char *const SAME_AS_LOCAL_KEY = "sameasLocal"; + const char *const DTMF_TYPE_KEY = "dtmfType"; + const char *const SERVICE_ROUTE_KEY = "serviceRoute"; + const char *const UPDATE_CONTACT_HEADER_KEY = "updateContact"; + const char *const KEEP_ALIVE_ENABLED = "keepAlive"; // TODO: write an object to store credential which implement serializable - const char *const srtpKey = "srtp"; - const char *const srtpEnableKey = "enable"; - const char *const keyExchangeKey = "keyExchange"; - const char *const rtpFallbackKey = "rtpFallback"; + const char *const SRTP_KEY = "srtp"; + const char *const SRTP_ENABLE_KEY = "enable"; + const char *const KEY_EXCHANGE_KEY = "keyExchange"; + const char *const RTP_FALLBACK_KEY = "rtpFallback"; // TODO: wirte an object to store zrtp params wich implement serializable - const char *const zrtpKey = "zrtp"; - const char *const displaySasKey = "displaySas"; - const char *const displaySasOnceKey = "displaySasOnce"; - const char *const helloHashEnabledKey = "helloHashEnabled"; - const char *const notSuppWarningKey = "notSuppWarning"; + const char *const ZRTP_KEY = "zrtp"; + const char *const DISPLAY_SAS_KEY = "displaySas"; + const char *const DISPLAY_SAS_ONCE_KEY = "displaySasOnce"; + const char *const HELLO_HASH_ENABLED_KEY = "helloHashEnabled"; + const char *const NOT_SUPP_WARNING_KEY = "notSuppWarning"; // TODO: write an object to store tls params which implement serializable - const char *const tlsKey = "tls"; - const char *const tlsPortKey = "tlsPort"; - const char *const certificateKey = "certificate"; - const char *const calistKey = "calist"; - const char *const ciphersKey = "ciphers"; - const char *const tlsEnableKey = "enable"; - const char *const methodKey = "method"; - const char *const timeoutKey = "timeout"; - const char *const tlsPasswordKey = "password"; - const char *const privateKeyKey = "privateKey"; - const char *const requireCertifKey = "requireCertif"; - const char *const serverKey = "server"; - const char *const verifyClientKey = "verifyClient"; - const char *const verifyServerKey = "verifyServer"; - - const char *const stunEnabledKey = "stunEnabled"; - const char *const stunServerKey = "stunServer"; - - const char *const credKey = "credential"; + const char *const TLS_KEY = "tls"; + const char *const TLS_PORT_KEY = "tlsPort"; + const char *const CERTIFICATE_KEY = "certificate"; + const char *const CALIST_KEY = "calist"; + const char *const CIPHERS_KEY = "ciphers"; + const char *const TLS_ENABLE_KEY = "enable"; + const char *const METHOD_KEY = "method"; + const char *const TIMEOUT_KEY = "timeout"; + const char *const TLS_PASSWORD_KEY = "password"; + const char *const PRIVATE_KEY_KEY = "privateKey"; + const char *const REQUIRE_CERTIF_KEY = "requireCertif"; + const char *const SERVER_KEY = "server"; + const char *const VERIFY_CLIENT_KEY = "verifyClient"; + const char *const VERIFY_SERVER_KEY = "verifyServer"; + + const char *const STUN_ENABLED_KEY = "stunEnabled"; + const char *const STUN_SERVER_KEY = "stunServer"; + const char *const CRED_KEY = "credential"; } class SIPVoIPLink; @@ -100,6 +100,7 @@ class SIPVoIPLink; class SIPAccount : public Account { public: + static const char * const IP2IP_PROFILE; static const char * const OVERRTP_STR; static const char * const SIPINFO_STR; @@ -109,11 +110,6 @@ class SIPAccount : public Account { */ SIPAccount(const std::string& accountID); - /** - * Virtual destructor - */ - virtual ~SIPAccount(); - virtual VoIPLink* getVoIPLink(); std::string getUserAgentName() const; @@ -121,17 +117,22 @@ class SIPAccount : public Account { registrationStateDetailed_ = details; } + /** + * Returns true if this is the IP2IP account + */ + bool isIP2IP() const; + /** * Serialize internal state of this account for configuration * @param YamlEmitter the configuration engine which generate the configuration file */ - virtual void serialize(Conf::YamlEmitter *emitter); + virtual void serialize(Conf::YamlEmitter &emitter); /** * Populate the internal state for this account based on info stored in the configuration file * @param The configuration node for this account */ - virtual void unserialize(Conf::MappingNode *map); + virtual void unserialize(const Conf::MappingNode &map); /** * Set the internal state for this account, mainly used to manage account details from the client application. @@ -190,8 +191,8 @@ class SIPAccount : public Account { void stopKeepAliveTimer(); - pjsip_cred_info *getCredInfo() const { - return cred_; + const pjsip_cred_info* getCredInfo() const { + return &(*cred_.begin()); } /** @@ -205,7 +206,9 @@ class SIPAccount : public Account { } void setCredentials(const std::vector<std::map<std::string, std::string> >& details); - const std::vector<std::map<std::string, std::string> > &getCredentials(); + + const std::vector<std::map<std::string, std::string> > & + getCredentials() const; /** * A client sendings a REGISTER request MAY suggest an expiration @@ -467,7 +470,7 @@ class SIPAccount : public Account { * @param The public IPV4 address in the standard dot notation. * @return void */ - void setPublishedAddress(const std::string& publishedIpAddress) { + void setPublishedAddress(const std::string &publishedIpAddress) { publishedIpAddress_ = publishedIpAddress; } @@ -495,32 +498,60 @@ class SIPAccount : public Account { return zrtpHelloHash_; } + void setReceivedParameter(const std::string &received) { + receivedParameter_ = received; + } + + std::string getReceivedParameter() const { + return receivedParameter_; + } + + int getRPort() const { + if (rPort_ == -1) + return localPort_; + else + return rPort_; + } + + void setRPort(int rPort) { rPort_ = rPort; } + /** * Timer used to periodically send re-register request based * on the "Expire" sip header (or the "expire" Contact parameter) */ static void keepAliveRegistrationCb(pj_timer_heap_t *th, pj_timer_entry *te); + bool isKeepAliveEnabled() const { + return keepAliveEnabled_; + } + + /** + * Pointer to the transport used by this acccount + */ pjsip_transport* transport_; + private: NON_COPYABLE(SIPAccount); + /** + * Map of credential for this account + */ std::vector< std::map<std::string, std::string > > credentials_; - /* Maps a string description of the SSL method + /** + * Maps a string description of the SSL method * to the corresponding enum value in pjsip_ssl_method. * @param method The string representation * @return pjsip_ssl_method The corresponding value in the enum */ static pjsip_ssl_method sslMethodStringToPjEnum(const std::string& method); - /* + /** * Initializes tls settings from configuration file. - * */ void initTlsConfiguration(); - /* + /** * Initializes STUN config from the config file */ void initStunConfiguration(); @@ -543,21 +574,41 @@ class SIPAccount : public Account { */ bool bRegister_; - // Network settings + /** + * Network settings + */ int registrationExpire_; - // interface name on which this account is bound + /** + * interface name on which this account is bound + */ std::string interface_; - // Flag which determine if localIpAddress_ or publishedIpAddress_ is used in - // sip headers + /** + * Flag which determine if localIpAddress_ or publishedIpAddress_ is used in + * sip headers + */ bool publishedSameasLocal_; + /** + * Published IP address, ued only if defined by the user in account + * configuration + */ std::string publishedIpAddress_; + /** + * Local port to whih this account is bound + */ pj_uint16_t localPort_; + + /** + * Published port, used only if defined by the user + */ pj_uint16_t publishedPort_; + /** + * Optional list of SIP service this + */ std::string serviceRoute_; /** @@ -576,7 +627,7 @@ class SIPAccount : public Account { /** * Credential information stored for further registration. */ - pjsip_cred_info *cred_; + std::vector<pjsip_cred_info> cred_; /** * The TLS settings, used only if tls is chosen as a sip transport. @@ -616,11 +667,6 @@ class SIPAccount : public Account { */ std::string tlsEnable_; - /** - * Specify the TLS port - */ - int tlsPort_; - /** * Certificate autority file */ @@ -689,17 +735,37 @@ class SIPAccount : public Account { */ std::pair<int, std::string> registrationStateDetailed_; + /** + * Determine if the keep alive timer will be activated or not + */ + bool keepAliveEnabled_; + /** * Timer used to regularrly send re-register request based * on the "Expire" sip header (or the "expire" Contact parameter) */ pj_timer_entry keepAliveTimer_; + /** + * Once enabled, this variable tells if the keepalive timer is activated + * for this accout + */ + bool keepAliveTimerActive_; /** * Voice over IP Link contains a listener thread and calls */ SIPVoIPLink* link_; + + /** + * Optional: "received" parameter from VIA header + */ + std::string receivedParameter_; + + /** + * Optional: "rport" parameter from VIA header + */ + int rPort_; }; #endif diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp index dd31f3bdc387e2db9490d1602a5fc0defc73a56e..b663518613fc0226dad27922f29df136c63a33f9 100644 --- a/daemon/src/sip/sipcall.cpp +++ b/daemon/src/sip/sipcall.cpp @@ -32,7 +32,6 @@ */ #include "sipcall.h" -#include "audio/audiortp/audio_rtp_factory.h" #include "sdp.h" namespace { @@ -53,3 +52,16 @@ SIPCall::~SIPCall() delete local_sdp_; pj_pool_release(pool_); } + +void SIPCall::answer() +{ + pjsip_tx_data *tdata; + if (pjsip_inv_answer(inv, PJSIP_SC_OK, NULL, NULL, &tdata) != PJ_SUCCESS) + throw std::runtime_error("Could not init invite request answer (200 OK)"); + + if (pjsip_inv_send_msg(inv, tdata) != PJ_SUCCESS) + throw std::runtime_error("Could not send invite request answer (200 OK)"); + + setConnectionState(CONNECTED); + setState(ACTIVE); +} diff --git a/daemon/src/sip/sipcall.h b/daemon/src/sip/sipcall.h index dab99795a77a66809277723be08e990e28b25248..249d3b7976bafd949dc465cf5a480c87581b78b9 100644 --- a/daemon/src/sip/sipcall.h +++ b/daemon/src/sip/sipcall.h @@ -89,6 +89,7 @@ class SIPCall : public Call { pjsip_inv_session *inv; private: + virtual void answer(); NON_COPYABLE(SIPCall); diff --git a/daemon/src/sip/siptransport.cpp b/daemon/src/sip/siptransport.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e33545637b325640079e62fe9c54ae16cf31fd30 --- /dev/null +++ b/daemon/src/sip/siptransport.cpp @@ -0,0 +1,634 @@ +/* + * Copyright (C) [2004, 2012] Savoir-Faire Linux Inc. + * + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include <map> + +#include <pjsip.h> +#include <pjlib.h> +#include <pjsip_ua.h> +#include <pjlib-util.h> +#include <pjnath.h> +#include <pjnath/stun_config.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <arpa/inet.h> +#include <net/if.h> +#include <stdexcept> +#include <sstream> + +#include "logger.h" +#include "siptransport.h" +#include "manager.h" + +#include "sipaccount.h" + +#include "pjsip/sip_types.h" +#include "dbus/dbusmanager.h" +#include "dbus/configurationmanager.h" + +static const char * const DEFAULT_INTERFACE = "default"; + +static pjsip_transport *localUDPTransport_ = NULL; /** The default transport (5060) */ + +std::string SipTransport::getSIPLocalIP() +{ + pj_sockaddr ip_addr; + + if (pj_gethostip(pj_AF_INET(), &ip_addr) == PJ_SUCCESS) + return pj_inet_ntoa(ip_addr.ipv4.sin_addr); + else { + ERROR("Could not get local IP"); + return ""; + } +} + +std::vector<std::string> SipTransport::getAllIpInterfaceByName() +{ + static ifreq ifreqs[20]; + ifconf ifconf; + + std::vector<std::string> ifaceList; + ifaceList.push_back("default"); + + ifconf.ifc_buf = (char*) (ifreqs); + ifconf.ifc_len = sizeof(ifreqs); + + int sock = socket(AF_INET,SOCK_STREAM,0); + + if (sock >= 0) { + if (ioctl(sock, SIOCGIFCONF, &ifconf) >= 0) + for (unsigned i = 0; i < ifconf.ifc_len / sizeof(ifreq); ++i) + ifaceList.push_back(std::string(ifreqs[i].ifr_name)); + + close(sock); + } + + return ifaceList; +} + +std::string SipTransport::getInterfaceAddrFromName(const std::string &ifaceName) +{ + int fd = socket(AF_INET, SOCK_DGRAM,0); + + if (fd < 0) { + ERROR("Error: could not open socket: %m"); + return ""; + } + + ifreq ifr; + strcpy(ifr.ifr_name, ifaceName.c_str()); + memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); + ifr.ifr_addr.sa_family = AF_INET; + + ioctl(fd, SIOCGIFADDR, &ifr); + close(fd); + + sockaddr_in *saddr_in = (sockaddr_in *) &ifr.ifr_addr; + return inet_ntoa(saddr_in->sin_addr); +} + +std::vector<std::string> SipTransport::getAllIpInterface() +{ + pj_sockaddr addrList[16]; + unsigned addrCnt = PJ_ARRAY_SIZE(addrList); + + std::vector<std::string> ifaceList; + + if (pj_enum_ip_interface(pj_AF_INET(), &addrCnt, addrList) == PJ_SUCCESS) { + for (unsigned i = 0; i < addrCnt; i++) { + char addr[PJ_INET_ADDRSTRLEN]; + pj_sockaddr_print(&addrList[i], addr, sizeof(addr), 0); + ifaceList.push_back(std::string(addr)); + } + } + + return ifaceList; +} + +SipTransport::SipTransport(pjsip_endpoint *endpt, pj_caching_pool *cp, pj_pool_t *pool) : transportMap_(), stunSocketMap_(), cp_(cp), pool_(pool), endpt_(endpt) +{} + +pj_bool_t +stun_sock_on_status_cb(pj_stun_sock * /*stun_sock*/, pj_stun_sock_op op, + pj_status_t status) +{ + switch (op) { + case PJ_STUN_SOCK_DNS_OP: + DEBUG("STUN operation dns resolution"); + break; + case PJ_STUN_SOCK_BINDING_OP: + DEBUG("STUN operation binding"); + break; + case PJ_STUN_SOCK_KEEP_ALIVE_OP: + DEBUG("STUN operation keep alive"); + break; + case PJ_STUN_SOCK_MAPPED_ADDR_CHANGE: + DEBUG("STUN operation address mapping change"); + break; + default: + DEBUG("STUN unknown operation"); + break; + } + + if (status == PJ_SUCCESS) { + DEBUG("STUN operation success"); + } else { + ERROR("STUN operation failure"); + } + + // Always return true so the stun transport registration retry even on failure + return true; +} + +static pj_bool_t +stun_sock_on_rx_data_cb(pj_stun_sock * /*stun_sock*/, void * /*pkt*/, + unsigned /*pkt_len*/, + const pj_sockaddr_t * /*src_addr*/, + unsigned /*addr_len*/) +{ + return PJ_TRUE; +} + + +pj_status_t SipTransport::createStunResolver(pj_str_t serverName, pj_uint16_t port) +{ + std::string stunResolverName(serverName.ptr, serverName.slen); + if (stunSocketMap_.find(stunResolverName) != stunSocketMap_.end()) { + DEBUG("%s already added", stunResolverName.c_str()); + return PJ_SUCCESS; + } + + pj_stun_config stunCfg; + pj_stun_config_init(&stunCfg, &cp_->factory, 0, + pjsip_endpt_get_ioqueue(endpt_), pjsip_endpt_get_timer_heap(endpt_)); + + static const pj_stun_sock_cb stun_sock_cb = { + stun_sock_on_rx_data_cb, + NULL, + stun_sock_on_status_cb + }; + + pj_stun_sock *stun_sock = NULL; + pj_status_t status = pj_stun_sock_create(&stunCfg, + stunResolverName.c_str(), pj_AF_INET(), &stun_sock_cb, NULL, NULL, + &stun_sock); + + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(status, errmsg, sizeof(errmsg)); + ERROR("Failed to create STUN socket for %.*s: %s", + (int) serverName.slen, serverName.ptr, errmsg); + return status; + } + + status = pj_stun_sock_start(stun_sock, &serverName, port, NULL); + + // store socket inside list + if (status == PJ_SUCCESS) { + DEBUG("Adding %s resolver", stunResolverName.c_str()); + stunSocketMap_[stunResolverName] = stun_sock; + } else { + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(status, errmsg, sizeof(errmsg)); + DEBUG("Error starting STUN socket for %.*s: %s", + (int) serverName.slen, serverName.ptr, errmsg); + pj_stun_sock_destroy(stun_sock); + } + + return status; +} + +pj_status_t SipTransport::destroyStunResolver(const std::string &serverName) +{ + std::map<std::string, pj_stun_sock *>::iterator it; + it = stunSocketMap_.find(serverName); + + DEBUG("***************** Destroy Stun Resolver *********************"); + + if (it != stunSocketMap_.end()) { + DEBUG("Deleting STUN resolver %s", it->first.c_str()); + if (it->second) + pj_stun_sock_destroy(it->second); + stunSocketMap_.erase(it); + } + + return PJ_SUCCESS; +} + + +pjsip_tpfactory* SipTransport::createTlsListener(SIPAccount &account) +{ + pj_sockaddr_in local_addr; + pj_sockaddr_in_init(&local_addr, 0, 0); + local_addr.sin_port = pj_htons(account.getTlsListenerPort()); + + if (account.getTlsSetting() == NULL) { + ERROR("Error TLS settings not specified"); + return NULL; + } + + std::string interface(account.getLocalInterface()); + std::string listeningAddress; + if (interface == DEFAULT_INTERFACE) + listeningAddress = getSIPLocalIP(); + else + listeningAddress = getInterfaceAddrFromName(interface); + + if (listeningAddress.empty()) + ERROR("Could not determine IP address for this transport"); + + pj_str_t pjAddress; + pj_cstr(&pjAddress, listeningAddress.c_str()); + pj_sockaddr_in_set_str_addr(&local_addr, &pjAddress); + pj_sockaddr_in_set_port(&local_addr, account.getTlsListenerPort()); + + pjsip_tpfactory *listener = NULL; + if (pjsip_tls_transport_start(endpt_, account.getTlsSetting(), &local_addr, + NULL, 1, &listener) != PJ_SUCCESS) { + ERROR("Failed to start tls listener"); + listener = NULL; + } + return listener; +} + + +pjsip_transport * +SipTransport::createTlsTransport(SIPAccount &account) +{ + std::string remoteSipUri(account.getServerUri()); + static const char SIPS_PREFIX[] = "<sips:"; + size_t sips = remoteSipUri.find(SIPS_PREFIX) + (sizeof SIPS_PREFIX) - 1; + size_t trns = remoteSipUri.find(";transport"); + std::string remoteAddr(remoteSipUri.substr(sips, trns-sips)); + std::string ipAddr = ""; + int port = DEFAULT_SIP_TLS_PORT; + + // parse c string + size_t pos = remoteAddr.find(":"); + if (pos != std::string::npos) { + ipAddr = remoteAddr.substr(0, pos); + port = atoi(remoteAddr.substr(pos + 1, remoteAddr.length() - pos).c_str()); + } else { + ipAddr = remoteAddr; + } + + pj_str_t remote; + pj_cstr(&remote, ipAddr.c_str()); + + pj_sockaddr_in rem_addr; + pj_sockaddr_in_init(&rem_addr, &remote, (pj_uint16_t) port); + + // The local tls listener + static pjsip_tpfactory *localTlsListener = NULL; + + if (localTlsListener == NULL) + localTlsListener = createTlsListener(account); + + DEBUG("Get new tls transport from transport manager"); + pjsip_transport *transport = NULL; + pjsip_endpt_acquire_transport(endpt_, PJSIP_TRANSPORT_TLS, &rem_addr, + sizeof rem_addr, NULL, &transport); + if (transport == NULL) + ERROR("Could not create new TLS transport\n"); + + return transport; +} + +void SipTransport::createSipTransport(SIPAccount &account) +{ + shutdownSipTransport(account); + + if (account.isTlsEnabled()) { + account.transport_ = createTlsTransport(account); + } else if (account.isStunEnabled()) { + account.transport_ = createStunTransport(account); + if (account.transport_ == NULL) { + WARN("falling back to UDP transport"); + account.transport_ = createUdpTransport(account.getLocalInterface(), account.getLocalPort()); + } + } else { + account.transport_ = createUdpTransport(account.getLocalInterface(), account.getLocalPort()); + } + + if (!account.transport_) { + std::ostringstream key; + key << account.getLocalInterface(); + key << ":"; + key << account.getLocalPort(); + DEBUG("Looking into previously created transport map for" + " %s", key.str().c_str()); + // Could not create new transport, this transport may already exists + pjsip_transport *cachedTransport = transportMap_[key.str()]; + + if (cachedTransport) { + account.transport_ = cachedTransport; + pjsip_transport_add_ref(account.transport_); + } else { + if (account.isTlsEnabled()) + throw std::runtime_error("SipTransport: Could not create TLS connection"); + assert(localUDPTransport_); + account.transport_ = localUDPTransport_; + account.setLocalPort(localUDPTransport_->local_name.port); + } + } +} + +void SipTransport::createDefaultSipUdpTransport() +{ + DEBUG("Create default sip udp transport"); + + SIPAccount *account = Manager::instance().getIP2IPAccount(); + + pjsip_transport *transport = NULL; + pj_uint16_t port = 0; + static const int DEFAULT_TRANSPORT_ATTEMPTS = 5; + for (int counter = 0; transport == NULL and counter < DEFAULT_TRANSPORT_ATTEMPTS; ++counter) { + // if default udp transport fails to init on 5060, try other ports + // with 2 step size increment (i.e. 5062, 5064, ...) + port = account->getLocalPort() + (counter * 2); + transport = createUdpTransport(account->getLocalInterface(), port); + } + + if (transport == NULL) { + ERROR("Could not create UDP transport"); + return; + } + + DEBUG("Created default sip transport on %d", port); + + // set transport for this account + account->transport_ = transport; + + // set local udp transport + localUDPTransport_ = account->transport_; +} + +pjsip_transport * +SipTransport::createUdpTransport(const std::string &interface, unsigned int port) +{ + // init socket to bind this transport to + pj_uint16_t listeningPort = (pj_uint16_t) port; + + DEBUG("Create UDP transport on %s:%d", interface.c_str(), port); + + // determine the ip address for this transport + std::string listeningAddress; + if (interface == DEFAULT_INTERFACE) + listeningAddress = getSIPLocalIP(); + else + listeningAddress = getInterfaceAddrFromName(interface); + + if (listeningAddress.empty()) { + ERROR("Could not determine ip address for this transport"); + return NULL; + } + + if (listeningPort == 0) { + ERROR("Could not determine port for this transport"); + return NULL; + } + + std::ostringstream fullAddress; + fullAddress << listeningAddress << ":" << listeningPort; + pj_str_t udpString; + std::string fullAddressStr(fullAddress.str()); + pj_cstr(&udpString, fullAddressStr.c_str()); + pj_sockaddr boundAddr; + pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &udpString, &boundAddr); + pj_status_t status; + pjsip_transport *transport = NULL; + + + + if (boundAddr.addr.sa_family == pj_AF_INET()) { + status = pjsip_udp_transport_start(endpt_, &boundAddr.ipv4, NULL, 1, &transport); + if (status != PJ_SUCCESS) { + return NULL; + } + } else if (boundAddr.addr.sa_family == pj_AF_INET6()) { + status = pjsip_udp_transport_start6(endpt_, &boundAddr.ipv6, NULL, 1, &transport); + if (status != PJ_SUCCESS) { + return NULL; + } + } + + DEBUG("Listening address %s", fullAddressStr.c_str()); + // dump debug information to stdout + pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); + transportMap_[fullAddressStr] = transport; + + return transport; +} + +pjsip_transport * +SipTransport::createUdpTransport(const std::string &interface, unsigned int port, const std::string &publicAddr, unsigned int publicPort) +{ + // init socket to bind this transport to + pj_uint16_t listeningPort = (pj_uint16_t) port; + pjsip_transport *transport = NULL; + + DEBUG("Update UDP transport on %s:%d with public addr %s:%d", + interface.c_str(), port, publicAddr.c_str(), publicPort); + + // determine the ip address for this transport + std::string listeningAddress; + if (interface == DEFAULT_INTERFACE) + listeningAddress = getSIPLocalIP(); + else + listeningAddress = getInterfaceAddrFromName(interface); + + if (listeningAddress.empty()) { + ERROR("Could not determine ip address for this transport"); + return NULL; + } + + std::ostringstream fullAddress; + fullAddress << listeningAddress << ":" << listeningPort; + pj_str_t udpString; + std::string fullAddressStr(fullAddress.str()); + pj_cstr(&udpString, fullAddressStr.c_str()); + pj_sockaddr boundAddr; + pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &udpString, &boundAddr); + + pj_str_t public_addr = pj_str((char *) publicAddr.c_str()); + pjsip_host_port hostPort; + hostPort.host = public_addr; + hostPort.port = publicPort; + + pj_status_t status; + // status = pjsip_udp_transport_restart(transport, PJSIP_UDP_TRANSPORT_DESTROY_SOCKET, PJ_INVALID_SOCKET, &boundAddr.ipv4, &hostPort); + status = pjsip_udp_transport_start(endpt_, &boundAddr.ipv4, &hostPort, 1, &transport); + if (status != PJ_SUCCESS) { + ERROR("Could not start new transport with address %s:%d, error code %d", publicAddr.c_str(), publicPort, status); + } + + // dump debug information to stdout + pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); + + return transport; +} + +pjsip_tpselector *SipTransport::initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const +{ + if (!transport) { + ERROR("Transport is not initialized"); + return NULL; + } + pjsip_tpselector *tp = (pjsip_tpselector *) pj_pool_zalloc(tp_pool, sizeof(pjsip_tpselector)); + tp->type = PJSIP_TPSELECTOR_TRANSPORT; + tp->u.transport = transport; + return tp; +} + +pjsip_transport *SipTransport::createStunTransport(SIPAccount &account) +{ + pj_str_t serverName = account.getStunServerName(); + pj_uint16_t port = account.getStunPort(); + + DEBUG("Create STUN transport server name: %s, port: %d", serverName, port); + if (createStunResolver(serverName, port) != PJ_SUCCESS) { + ERROR("Can't resolve STUN server"); + Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure(account.getAccountID()); + return NULL; + } + + pj_sock_t sock = PJ_INVALID_SOCKET; + + pj_sockaddr_in boundAddr; + + if (pj_sockaddr_in_init(&boundAddr, &serverName, 0) != PJ_SUCCESS) { + ERROR("Can't initialize IPv4 socket on %*s:%i", serverName.slen, serverName.ptr, port); + Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure(account.getAccountID()); + return NULL; + } + + if (pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock) != PJ_SUCCESS) { + ERROR("Can't create or bind socket"); + Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure(account.getAccountID()); + return NULL; + } + + // Query the mapped IP address and port on the 'outside' of the NAT + pj_sockaddr_in pub_addr; + + if (pjstun_get_mapped_addr(&cp_->factory, 1, &sock, &serverName, port, &serverName, port, &pub_addr) != PJ_SUCCESS) { + ERROR("Can't contact STUN server"); + pj_sock_close(sock); + Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure(account.getAccountID()); + return NULL; + } + + pjsip_host_port a_name = { + pj_str(pj_inet_ntoa(pub_addr.sin_addr)), + pj_ntohs(pub_addr.sin_port) + }; + + pjsip_transport *transport; + pjsip_udp_transport_attach2(endpt_, PJSIP_TRANSPORT_UDP, sock, &a_name, 1, + &transport); + + pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); + + return transport; +} + +void SipTransport::shutdownSipTransport(SIPAccount &account) +{ + if (account.isStunEnabled()) { + pj_str_t stunServerName = account.getStunServerName(); + std::string server(stunServerName.ptr, stunServerName.slen); + destroyStunResolver(server); + } + + if (account.transport_) { + pjsip_transport_dec_ref(account.transport_); + account.transport_ = NULL; + } +} + +void SipTransport::findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &addr, std::string &port) const +{ + // Initialize the sip port with the default SIP port + std::stringstream ss; + ss << DEFAULT_SIP_PORT; + port = ss.str(); + + // Initialize the sip address with the hostname + const pj_str_t *pjMachineName = pj_gethostname(); + addr = std::string(pjMachineName->ptr, pjMachineName->slen); + + // Update address and port with active transport + if (!transport) { + ERROR("Transport is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str()); + return; + } + + // get the transport manager associated with the SIP enpoint + pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt_); + if (!tpmgr) { + ERROR("Transport manager is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str()); + return; + } + + // initialize a transport selector + // TODO Need to determine why we exclude TLS here... + // if (transportType == PJSIP_TRANSPORT_UDP and transport_) + pjsip_tpselector *tp_sel = initTransportSelector(transport, pool_); + if (!tp_sel) { + ERROR("Could not initialize transport selector, using local address %s:%s", addr.c_str(), port.c_str()); + return; + } + + pj_str_t localAddress = {0,0}; + int i_port = 0; + + // Find the local address and port for this transport + if (pjsip_tpmgr_find_local_addr(tpmgr, pool_, transportType, tp_sel, &localAddress, &i_port) != PJ_SUCCESS) { + WARN("SipTransport: Could not retrieve local address and port from transport, using %s:%s", addr.c_str(), port.c_str()); + return; + } + + // Update local address based on the transport type + addr = std::string(localAddress.ptr, localAddress.slen); + + // Fallback on local ip provided by pj_gethostip() + if (addr == "0.0.0.0") + addr = getSIPLocalIP(); + + // Determine the local port based on transport information + ss.str(""); + ss << i_port; + port = ss.str(); +} diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h new file mode 100644 index 0000000000000000000000000000000000000000..e37db61ae79a5178dd6147ed7074d3539fdc6ed2 --- /dev/null +++ b/daemon/src/sip/siptransport.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) [2004, 2012] Savoir-Faire Linux Inc. + * + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef SIPTRANSPORT_H_ +#define SIPTRANSPORT_H_ + +#include <string> +#include <vector> + +#include <pjsip.h> +#include <pjlib.h> +#include <pjsip_ua.h> +#include <pjlib-util.h> +#include <pjnath.h> +#include <pjnath/stun_config.h> +#include "noncopyable.h" + +class SIPAccount; + +class SipTransport { + public: + SipTransport(pjsip_endpoint *endpt, pj_caching_pool *cp, pj_pool_t *pool); + static std::string getSIPLocalIP(); + + /** + * List all the interfaces on the system and return + * a vector list containing their name (eth0, eth0:1 ...). + * @param void + * @return std::vector<std::string> A std::string vector + * of interface name available on all of the interfaces on + * the system. + */ + static std::vector<std::string> getAllIpInterfaceByName(); + + /** + * List all the interfaces on the system and return + * a vector list containing their name (eth0, eth0:1 ...). + * @param void + * @return std::vector<std::string> A std::string vector + * of interface name available on all of the interfaces on + * the system. + */ + static std::string getInterfaceAddrFromName(const std::string &ifaceName); + + /** + * List all the interfaces on the system and return + * a vector list containing their IPV4 address. + * @param void + * @return std::vector<std::string> A std::string vector + * of IPV4 address available on all of the interfaces on + * the system. + */ + static std::vector<std::string> getAllIpInterface(); + + void setEndpoint(pjsip_endpoint *endpt) { + endpt_ = endpt; + } + + void setCachingPool(pj_caching_pool *cp) { + cp_ = cp; + } + + void setPool(pj_pool_t *pool) { + pool_ = pool; + } + + pj_status_t destroyStunResolver(const std::string &serverName); + + /** + * General Sip transport creation method according to the + * transport type specified in account settings + * @param account The account for which a transport must be created. + */ + void createSipTransport(SIPAccount &account); + + /** + * Create the default sip transport on 5060. In case this port is already used + * increme + */ + void createDefaultSipUdpTransport(); + + /** + * Initialize the transport selector + * @param transport A transport associated with an account + * + * @return A pointer to the transport selector structure + */ + pjsip_tpselector *initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const; + + /** + * This function unset the transport for a given account. + */ + void shutdownSipTransport(SIPAccount &account); + + /** + * Get the correct address to use (ie advertised) from + * a uri. The corresponding transport that should be used + * with that uri will be discovered. + * + * @param uri The uri from which we want to discover the address to use + * @param transport The transport to use to discover the address + */ + void findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &address, std::string &port) const; + + /** + * Create a new udp transport specifying the bound address AND the published address. + * The published address is the address to appears in the sip VIA header. This is used + * essentially when the client is behind a trafic routing device. + * + * @param The interface to bind this transport with + * @param The requested udp port number + * @param The public address for this transport + * @param The public port for this transport + */ + pjsip_transport *createUdpTransport(const std::string &interface, unsigned int port, const std::string &publicAddr, unsigned int publicPort); + + private: + NON_COPYABLE(SipTransport); + + pjsip_transport * + createStunTransport(SIPAccount &account); + /** + * Create a connection oriented TLS transport and register to the specified remote address. + * First, initialize the TLS listener sole instance. This means that, for the momment, only one TLS transport + * is allowed to be created in the application. Any subsequent account attempting to + * register a new using this transport even if new settings are specified. + * @param the account that is creating the TLS transport + */ + pjsip_transport * + createTlsTransport(SIPAccount &account); + + /** + * Create The default TLS listener which is global to the application. This means that + * only one TLS connection can be established for the momment. + * @param the SIPAccount for which we are creating the TLS listener + * @return a pointer to the new listener + */ + pjsip_tpfactory * + createTlsListener(SIPAccount &account); + + /** + * Create a new stun resolver. Store it inside the array. Resolve public address for this + * server name. + * @param serverName The name of the stun server + * @param port number + */ + pj_status_t createStunResolver(pj_str_t serverName, pj_uint16_t port); + + /** + * Create SIP UDP transport from account's setting + * @param account The account for which a transport must be created. + */ + pjsip_transport *createUdpTransport(const std::string &interface, + unsigned int port); + + /** + * UDP Transports are stored in this map in order to retreive them in case + * several accounts would share the same port number. + */ + std::map<std::string, pjsip_transport*> transportMap_; + + /** + * Stun resolver array + */ + std::map<std::string, pj_stun_sock *> stunSocketMap_; + + pj_caching_pool *cp_; + + pj_pool_t *pool_; + + pjsip_endpoint *endpt_; +}; + +#endif // SIPTRANSPORT_H_ diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 9b0d18be145d1c86ef5e7e97c07976a67919c153..cdd149919bc28331fbe2a8903605241f4c55df48 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Savoir-Faire Linux Inc. - * * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Yun Liu <yun.liu@savoirfairelinux.com> * Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com> @@ -36,20 +35,24 @@ #include "config.h" #endif -#include "sipvoiplink.h" +#include "sip_utils.h" +#include "sipvoiplink.h" +#include "array_size.h" #include "manager.h" +#include "logger.h" #include "sip/sdp.h" #include "sipcall.h" #include "sipaccount.h" #include "eventthread.h" #include "sdes_negotiator.h" +#include "array_size.h" #include "dbus/dbusmanager.h" #include "dbus/callmanager.h" +#include "dbus/configurationmanager.h" -#include "hooks/urlhook.h" #include "im/instant_messaging.h" #include "audio/audiolayer.h" @@ -57,26 +60,23 @@ #include "pjsip/sip_endpoint.h" #include "pjsip/sip_transport_tls.h" #include "pjsip/sip_uri.h" -#include <pjnath.h> +#include "pjnath.h" #include <netinet/in.h> #include <arpa/nameser.h> +#include <arpa/inet.h> #include <resolv.h> #include <istream> #include <utility> // for std::pair -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <linux/if.h> - #include <map> using namespace sfl; -namespace { +SIPVoIPLink *SIPVoIPLink::instance_ = 0; +bool SIPVoIPLink::destroyed_ = false; -static pjsip_transport *localUDPTransport_ = NULL; /** The default transport (5060) */ +namespace { /** A map to retreive SFLphone internal call id * Given a SIP call ID (usefull for transaction sucha as transfer)*/ @@ -91,18 +91,13 @@ static std::map<std::string, std::string> transferCallID; */ void setCallMediaLocal(SIPCall* call, const std::string &localIP); -/** - * Helper function to parser header from incoming sip messages - */ -std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field); - static pj_caching_pool pool_cache, *cp_ = &pool_cache; static pj_pool_t *pool_; static pjsip_endpoint *endpt_; static pjsip_module mod_ua_; -static pj_thread_t *thread; +static pj_thread_t *thread_; -void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status UNUSED); +void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status); void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer); void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer); void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e); @@ -110,7 +105,7 @@ void outgoing_request_forked_cb(pjsip_inv_session *inv, pjsip_event *e); void transaction_state_changed_cb(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e); void registration_cb(pjsip_regc_cbparam *param); pj_bool_t transaction_request_cb(pjsip_rx_data *rdata); -pj_bool_t transaction_response_cb(pjsip_rx_data *rdata UNUSED) ; +pj_bool_t transaction_response_cb(pjsip_rx_data *rdata) ; void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event); @@ -126,43 +121,6 @@ int SIPSessionReinvite(SIPCall *); */ void onCallTransfered(pjsip_inv_session *inv, pjsip_rx_data *rdata); -std::string getSIPLocalIP() -{ - pj_sockaddr ip_addr; - - if (pj_gethostip(pj_AF_INET(), &ip_addr) == PJ_SUCCESS) - return pj_inet_ntoa(ip_addr.ipv4.sin_addr); - else { - ERROR("SIPVoIPLink: Could not get local IP"); - return ""; - } -} - -pjsip_route_hdr *createRouteSet(const std::string &route, pj_pool_t *hdr_pool) -{ - int port = 0; - std::string host; - - size_t found = route.find(":"); - - if (found != std::string::npos) { - host = route.substr(0, found); - port = atoi(route.substr(found + 1, route.length()).c_str()); - } else - host = route; - - pjsip_route_hdr *route_set = pjsip_route_hdr_create(hdr_pool); - pjsip_route_hdr *routing = pjsip_route_hdr_create(hdr_pool); - pjsip_sip_uri *url = pjsip_sip_uri_create(hdr_pool, 0); - routing->name_addr.uri = (pjsip_uri*) url; - pj_strdup2(hdr_pool, &url->host, host.c_str()); - url->port = port; - - pj_list_push_back(route_set, pjsip_hdr_clone(hdr_pool, routing)); - - return route_set; -} - void handleIncomingOptions(pjsip_rx_data *rdata) { pjsip_tx_data *tdata; @@ -174,7 +132,7 @@ void handleIncomingOptions(pjsip_rx_data *rdata) const pjsip_hdr *cap_hdr = hdr; \ if (cap_hdr) \ pjsip_msg_add_hdr (tdata->msg, (pjsip_hdr*) pjsip_hdr_clone (tdata->pool, cap_hdr)); \ -} while(0) +} while (0) #define ADD_CAP(cap) ADD_HDR(pjsip_endpt_get_capability(endpt_, cap, NULL)); ADD_CAP(PJSIP_H_ALLOW); @@ -207,75 +165,61 @@ pj_bool_t transaction_response_cb(pjsip_rx_data *rdata) * ACK for a 2xx response must be send using this method. */ pjsip_tx_data *tdata; - pjsip_dlg_create_request(dlg, &pjsip_ack_method, rdata->msg_info.cseq->cseq, &tdata); - pjsip_dlg_send_request(dlg, tdata, -1, NULL); + if (rdata->msg_info.cseq) { + pjsip_dlg_create_request(dlg, &pjsip_ack_method, rdata->msg_info.cseq->cseq, &tdata); + pjsip_dlg_send_request(dlg, tdata, -1, NULL); + } } return PJ_SUCCESS; } -std::string parseDisplayName(const char * buffer) -{ - const char* from_header = strstr(buffer, "From: "); - - if (!from_header) - return ""; - - std::string temp(from_header); - size_t begin_displayName = temp.find("\"") + 1; - size_t end_displayName = temp.rfind("\""); - std::string displayName(temp.substr(begin_displayName, end_displayName - begin_displayName)); - - static const size_t MAX_DISPLAY_NAME_SIZE = 25; - if (displayName.size() > MAX_DISPLAY_NAME_SIZE) - return ""; - - return displayName; -} - -void stripSipUriPrefix(std::string& sipUri) -{ - // Remove sip: prefix - static const char SIP_PREFIX[] = "sip:"; - size_t found = sipUri.find(SIP_PREFIX); - - if (found != std::string::npos) - sipUri.erase(found, found + (sizeof SIP_PREFIX) - 1); - - found = sipUri.find("@"); - - if (found != std::string::npos) - sipUri.erase(found); -} - pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) { + if (!rdata or !rdata->msg_info.msg) { + ERROR("rx_data is NULL"); + return false; + } pjsip_method *method = &rdata->msg_info.msg->line.req.method; + if (!method) { + ERROR("method is NULL"); + return false; + } if (method->id == PJSIP_ACK_METHOD && pjsip_rdata_get_dlg(rdata)) return true; + if (!rdata->msg_info.to or !rdata->msg_info.from) { + ERROR("NULL from/to fields"); + return false; + } pjsip_sip_uri *sip_to_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.to->uri); pjsip_sip_uri *sip_from_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.from->uri); + if (!sip_to_uri or !sip_from_uri) { + ERROR("NULL uri"); + return false; + } std::string userName(sip_to_uri->user.ptr, sip_to_uri->user.slen); std::string server(sip_from_uri->host.ptr, sip_from_uri->host.slen); std::string account_id(Manager::instance().getAccountIdFromNameAndServer(userName, server)); - std::string displayName(parseDisplayName(rdata->msg_info.msg_buf)); + std::string displayName(sip_utils::parseDisplayName(rdata->msg_info.msg_buf)); + pjsip_msg_body *body = rdata->msg_info.msg->body; if (method->id == PJSIP_OTHER_METHOD) { pj_str_t *str = &method->name; std::string request(str->ptr, str->slen); - if (request.find("NOTIFY") != (size_t)-1) { - int voicemail; - - if (sscanf((const char*)rdata->msg_info.msg->body->data, "Voice-Message: %d/", &voicemail) == 1 && voicemail != 0) - Manager::instance().startVoiceMessageNotification(account_id, voicemail); + if (request.find("NOTIFY") != std::string::npos) { + if (body and body->data) { + int voicemail = 0; + int ret = sscanf((const char*) body->data, "Voice-Message: %d/", &voicemail); + if (ret == 1 and voicemail != 0) + Manager::instance().startVoiceMessageNotification(account_id, voicemail); + } } pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_OK, NULL, NULL, NULL); - return true; } else if (method->id == PJSIP_OPTIONS_METHOD) { handleIncomingOptions(rdata); @@ -288,7 +232,6 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(account_id)); pjmedia_sdp_session *r_sdp; - pjsip_msg_body *body = rdata->msg_info.msg->body; if (!body || pjmedia_sdp_parse(rdata->tp_info.pool, (char*) body->data, body->len, &r_sdp) != PJ_SUCCESS) r_sdp = NULL; @@ -308,32 +251,29 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) return true; } - if (Manager::instance().hookPreference.getSipEnabled()) { - std::string header_value(fetchHeaderValue(rdata->msg_info.msg, Manager::instance().hookPreference.getUrlSipField())); - UrlHook::runAction(Manager::instance().hookPreference.getUrlCommand(), header_value); - } + Manager::instance().hookPreference.runHook(rdata->msg_info.msg); SIPCall* call = new SIPCall(Manager::instance().getNewCallID(), Call::INCOMING, cp_); Manager::instance().associateCallToAccount(call->getCallId(), account_id); // May use the published address as well - std::string addrToUse = SIPVoIPLink::instance()->getInterfaceAddrFromName(account->getLocalInterface()); + std::string addrToUse = SipTransport::getInterfaceAddrFromName(account->getLocalInterface()); std::string addrSdp = account->isStunEnabled() ? account->getPublishedAddress() : addrToUse; - pjsip_tpselector *tp = SIPVoIPLink::instance()->initTransportSelector(account->transport_, call->getMemoryPool()); + pjsip_tpselector *tp = SIPVoIPLink::instance()->sipTransport.initTransportSelector(account->transport_, call->getMemoryPool()); if (addrToUse == "0.0.0.0") - addrToUse = getSIPLocalIP(); + addrToUse = SipTransport::getSIPLocalIP(); if (addrSdp == "0.0.0.0") addrSdp = addrToUse; char tmp[PJSIP_MAX_URL_SIZE]; - int length = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_from_uri, tmp, PJSIP_MAX_URL_SIZE); - std::string peerNumber(tmp, length); - stripSipUriPrefix(peerNumber); + size_t length = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_from_uri, tmp, PJSIP_MAX_URL_SIZE); + std::string peerNumber(tmp, std::min(length, sizeof tmp)); + sip_utils::stripSipUriPrefix(peerNumber); call->setConnectionState(Call::PROGRESSING); call->setPeerNumber(peerNumber); @@ -344,17 +284,17 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) call->getLocalSDP()->setLocalIP(addrSdp); - call->getAudioRtp().initAudioRtpConfig(); - call->getAudioRtp().initAudioSymmetricRtpSession(); + call->getAudioRtp().initConfig(); + call->getAudioRtp().initSession(); - if (rdata->msg_info.msg->body) { + if (body) { char sdpbuffer[1000]; - int len = rdata->msg_info.msg->body->print_body(rdata->msg_info.msg->body, sdpbuffer, sizeof sdpbuffer); + int len = body->print_body(body, sdpbuffer, sizeof sdpbuffer); if (len == -1) // error len = 0; - std::string sdpoffer(sdpbuffer, len); + std::string sdpoffer(sdpbuffer, std::min(len, (int) sizeof sdpbuffer)); size_t start = sdpoffer.find("a=crypto:"); // Found crypto header in SDP @@ -362,10 +302,11 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) CryptoOffer crypto_offer; crypto_offer.push_back(std::string(sdpoffer.substr(start, (sdpoffer.size() - start) - 1))); - std::vector<sfl::CryptoSuiteDefinition>localCapabilities; + const size_t size = ARRAYSIZE(sfl::CryptoSuites); + std::vector<sfl::CryptoSuiteDefinition> localCapabilities(size); - for (int i = 0; i < 3; i++) - localCapabilities.push_back(sfl::CryptoSuites[i]); + std::copy(sfl::CryptoSuites, sfl::CryptoSuites + size, + localCapabilities.begin()); sfl::SdesNegotiator sdesnego(localCapabilities, crypto_offer); @@ -378,8 +319,13 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) call->getLocalSDP()->receiveOffer(r_sdp, account->getActiveCodecs()); - sfl::Codec* audiocodec = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW); - call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec)); + sfl::AudioCodec* ac = dynamic_cast<sfl::AudioCodec*>(Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW)); + if (!ac) { + ERROR("Could not instantiate codec"); + delete call; + return false; + } + call->getAudioRtp().start(ac); pjsip_dialog* dialog; @@ -393,6 +339,12 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) PJ_ASSERT_RETURN(pjsip_dlg_set_transport(dialog, tp) == PJ_SUCCESS, 1); + if (!call->inv) { + ERROR("Call invite is not initialized"); + delete call; + return false; + } + call->inv->mod_data[mod_ua_.id] = call; // Check whether Replaces header is present in the request and process accordingly. @@ -425,7 +377,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) call->setConnectionState(Call::RINGING); - Manager::instance().incomingCall(call, account_id); + Manager::instance().incomingCall(*call, account_id); Manager::instance().getAccountLink(account_id)->addCall(call); } @@ -435,19 +387,20 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) /*************************************************************************************************/ -SIPVoIPLink::SIPVoIPLink() : transportMap_(), evThread_(new EventThread(this)) +SIPVoIPLink::SIPVoIPLink() : sipTransport(endpt_, cp_, pool_), evThread_(this) { #define TRY(ret) do { \ if (ret != PJ_SUCCESS) \ throw VoipLinkException(#ret " failed"); \ -} while(0) +} while (0) srand(time(NULL)); // to get random number for RANDOM_PORT TRY(pj_init()); TRY(pjlib_util_init()); // From 0 (min) to 6 (max) - pj_log_set_level(Logger::getDebugMode() ? 6 : 0); + // pj_log_set_level(Logger::getDebugMode() ? 6 : 0); + pj_log_set_level(0); TRY(pjnath_init()); pj_caching_pool_init(cp_, &pj_pool_factory_default_policy, 0); @@ -458,7 +411,11 @@ SIPVoIPLink::SIPVoIPLink() : transportMap_(), evThread_(new EventThread(this)) TRY(pjsip_endpt_create(&cp_->factory, pj_gethostname()->ptr, &endpt_)); - if (getSIPLocalIP().empty()) + sipTransport.setEndpoint(endpt_); + sipTransport.setCachingPool(cp_); + sipTransport.setPool(pool_); + + if (SipTransport::getSIPLocalIP().empty()) throw VoipLinkException("UserAgent: Unable to determine network capabilities"); TRY(pjsip_tsx_layer_init_module(endpt_)); @@ -498,19 +455,28 @@ SIPVoIPLink::SIPVoIPLink() : transportMap_(), evThread_(new EventThread(this)) static const pj_str_t accepted = { (char*) "application/sdp", 15 }; pjsip_endpt_add_capability(endpt_, &mod_ua_, PJSIP_H_ACCEPT, NULL, 1, &accepted); - DEBUG("UserAgent: pjsip version %s for %s initialized", pj_get_version(), PJ_OS_NAME); + DEBUG("pjsip version %s for %s initialized", pj_get_version(), PJ_OS_NAME); TRY(pjsip_replaces_init_module(endpt_)); #undef TRY - evThread_->start(); + handlingEvents_ = true; + evThread_.start(); } SIPVoIPLink::~SIPVoIPLink() { - delete evThread_; - pj_thread_join(thread); - pj_thread_destroy(thread); + const int MAX_TIMEOUT_ON_LEAVING = 5; + for (int timeout = 0; pjsip_tsx_layer_get_tsx_count() and timeout < MAX_TIMEOUT_ON_LEAVING; timeout++) + sleep(1); + + handlingEvents_ = false; + if (thread_) { + pj_thread_join(thread_); + pj_thread_destroy(thread_); + DEBUG("PJ thread destroy finished"); + thread_ = 0; + } const pj_time_val tv = {0, 10}; pjsip_endpt_handle_events(endpt_, &tv); @@ -524,35 +490,42 @@ SIPVoIPLink::~SIPVoIPLink() SIPVoIPLink* SIPVoIPLink::instance() { - static SIPVoIPLink* instance = NULL; - - if (!instance) - instance = new SIPVoIPLink; - - return instance; + assert(!destroyed_); + if (!instance_) + instance_ = new SIPVoIPLink; + return instance_; } -void SIPVoIPLink::init() {} - -void SIPVoIPLink::terminate() {} +void SIPVoIPLink::destroy() +{ + delete instance_; + destroyed_ = true; + instance_ = 0; +} -void -SIPVoIPLink::getEvent() +// Called from EventThread::run (not main thread) +bool SIPVoIPLink::getEvent() { static pj_thread_desc desc; // We have to register the external thread so it could access the pjsip frameworks - if (!pj_thread_is_registered()) - pj_thread_register(NULL, desc, &thread); + if (!pj_thread_is_registered()) { + DEBUG("Registering thread"); + pj_thread_register(NULL, desc, &thread_); + } static const pj_time_val timeout = {0, 10}; pjsip_endpt_handle_events(endpt_, &timeout); + return handlingEvents_; } void SIPVoIPLink::sendRegister(Account *a) { SIPAccount *account = dynamic_cast<SIPAccount*>(a); - createSipTransport(account); + + if (!account) + throw VoipLinkException("SipVoipLink: Account is not SIPAccount"); + sipTransport.createSipTransport(*account); account->setRegister(true); account->setRegistrationState(Trying); @@ -572,19 +545,32 @@ void SIPVoIPLink::sendRegister(Account *a) std::string from(account->getFromUri()); pj_str_t pjFrom = pj_str((char*) from.c_str()); - // Get the contact header for this account - std::string contact(account->getContactHeader()); + // Get the received header + std::string received(account->getReceivedParameter()); + + // Get the contact header + std::string contact = account->getContactHeader(); pj_str_t pjContact = pj_str((char*) contact.c_str()); + if (!received.empty()) { + // Set received parameter string to empty in order to avoid creating new transport for each register + account->setReceivedParameter(""); + // Explicitely set the bound address port to 0 so that pjsip determine a random port by itself + account->transport_= sipTransport.createUdpTransport(account->getLocalInterface(), 0, received, account->getRPort()); + account->setRPort(-1); + if(account->transport_ == NULL) { + ERROR("Could not create new udp transport with public address: %s:%d", received.c_str(), account->getLocalPort()); + } + } + if (pjsip_regc_init(regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, account->getRegistrationExpire()) != PJ_SUCCESS) throw VoipLinkException("Unable to initialize account registration structure"); - if (!account->getServiceRoute().empty()) - pjsip_regc_set_route_set(regc, createRouteSet(account->getServiceRoute(), pool_)); + if (not account->getServiceRoute().empty()) + pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(account->getServiceRoute(), pool_)); pjsip_regc_set_credentials(regc, account->getCredentialCount(), account->getCredInfo()); - pjsip_hdr hdr_list; pj_list_init(&hdr_list); std::string useragent(account->getUserAgentName()); @@ -595,13 +581,12 @@ void SIPVoIPLink::sendRegister(Account *a) pj_list_push_back(&hdr_list, (pjsip_hdr*) h); pjsip_regc_add_headers(regc, &hdr_list); - pjsip_tx_data *tdata; if (pjsip_regc_register(regc, PJ_TRUE, &tdata) != PJ_SUCCESS) throw VoipLinkException("Unable to initialize transaction data for account registration"); - if (pjsip_regc_set_transport(regc, initTransportSelector(account->transport_, pool_)) != PJ_SUCCESS) + if (pjsip_regc_set_transport(regc, sipTransport.initTransportSelector(account->transport_, pool_)) != PJ_SUCCESS) throw VoipLinkException("Unable to set transport"); // decrease transport's ref count, counter incrementation is managed when acquiring transport @@ -620,7 +605,8 @@ void SIPVoIPLink::sendRegister(Account *a) // start the periodic registration request based on Expire header // account determines itself if a keep alive is required - account->startKeepAliveTimer(); + if(account->isKeepAliveEnabled()) + account->startKeepAliveTimer(); } void SIPVoIPLink::sendUnregister(Account *a) @@ -652,13 +638,26 @@ void SIPVoIPLink::sendUnregister(Account *a) account->setRegister(false); } -void SIPVoIPLink::registerKeepAliveTimer(pj_timer_entry& timer, pj_time_val& delay) +void SIPVoIPLink::registerKeepAliveTimer(pj_timer_entry &timer, pj_time_val &delay) { - pj_status_t status; + DEBUG("Register new keep alive timer %d with delay %d", timer.id, delay.sec); - status = pjsip_endpt_schedule_timer(endpt_, &timer, &delay); - if (status != PJ_SUCCESS) - ERROR("Could not schedule new timer in pjsip endpoint"); + if (timer.id == -1) + WARN("Timer already scheduled"); + + switch (pjsip_endpt_schedule_timer(endpt_, &timer, &delay)) { + case PJ_SUCCESS: + break; + default: + ERROR("Could not schedule new timer in pjsip endpoint"); + /* fallthrough */ + case PJ_EINVAL: + ERROR("Invalid timer or delay entry"); + break; + case PJ_EINVALIDOP: + ERROR("Invalid timer entry, maybe already scheduled"); + break; + } } void SIPVoIPLink::cancelKeepAliveTimer(pj_timer_entry& timer) @@ -666,8 +665,96 @@ void SIPVoIPLink::cancelKeepAliveTimer(pj_timer_entry& timer) pjsip_endpt_cancel_timer(endpt_, &timer); } +bool isValidIpAddress(const std::string &address) +{ + size_t pos = address.find(":"); + std::string address_without_port(address); + if (pos != std::string::npos) + address_without_port = address.substr(0, pos); + + DEBUG("Testing address %s", address_without_port.c_str()); + struct sockaddr_in sa; + int result = inet_pton(AF_INET, address_without_port.data(), &(sa.sin_addr)); + return result != 0; +} + Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toUrl) { + DEBUG("New outgoing call to %s", toUrl.c_str()); + std::string toCpy = toUrl; + + sip_utils::stripSipUriPrefix(toCpy); + + bool IPToIP = isValidIpAddress(toCpy); + Manager::instance().setIPToIPForCall(id, IPToIP); + + try { + if (IPToIP) { + Manager::instance().associateCallToAccount(id, SIPAccount::IP2IP_PROFILE); + return SIPNewIpToIpCall(id, toUrl); + } + else { + return newRegisteredAccountCall(id, toUrl); + } + } + catch(...) { + throw; + } +} + +Call *SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to) +{ + DEBUG("New IP to IP call to %s", to.c_str()); + + SIPAccount *account = Manager::instance().getIP2IPAccount(); + + if (!account) + throw VoipLinkException("Could not retrieve default account for IP2IP call"); + + SIPCall *call = new SIPCall(id, Call::OUTGOING, cp_); + + call->setIPToIP(true); + call->initRecFilename(to); + + std::string localAddress(SipTransport::getInterfaceAddrFromName(account->getLocalInterface())); + + if (localAddress == "0.0.0.0") + localAddress = SipTransport::getSIPLocalIP(); + + setCallMediaLocal(call, localAddress); + + std::string toUri = account->getToUri(to); + call->setPeerNumber(toUri); + + sfl::AudioCodec* ac = dynamic_cast<sfl::AudioCodec*>(Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW)); + + if (!ac) { + delete call; + throw VoipLinkException("Could not instantiate codec"); + } + // Audio Rtp Session must be initialized before creating initial offer in SDP session + // since SDES require crypto attribute. + call->getAudioRtp().initConfig(); + call->getAudioRtp().initSession(); + call->getAudioRtp().initLocalCryptoInfo(); + call->getAudioRtp().start(ac); + + // Building the local SDP offer + call->getLocalSDP()->setLocalIP(localAddress); + call->getLocalSDP()->createOffer(account->getActiveCodecs()); + + if (!SIPStartCall(call)) { + delete call; + throw VoipLinkException("Could not create new call"); + } + + return call; +} + +Call *SIPVoIPLink::newRegisteredAccountCall(const std::string& id, const std::string& toUrl) +{ + DEBUG("UserAgent: New registered account call to %s", toUrl.c_str()); + SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(Manager::instance().getAccountFromCall(id))); if (account == NULL) // TODO: We should investigate how we could get rid of this error and create a IP2IP call instead @@ -675,7 +762,7 @@ Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toU SIPCall* call = new SIPCall(id, Call::OUTGOING, cp_); - // If toUri is not a well formated sip URI, use account information to process it + // If toUri is not a well formatted sip URI, use account information to process it std::string toUri; if (toUrl.find("sip:") != std::string::npos or @@ -685,36 +772,36 @@ Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toU toUri = account->getToUri(toUrl); call->setPeerNumber(toUri); - std::string localAddr(getInterfaceAddrFromName(account->getLocalInterface())); + std::string localAddr(SipTransport::getInterfaceAddrFromName(account->getLocalInterface())); if (localAddr == "0.0.0.0") - localAddr = getSIPLocalIP(); + localAddr = SipTransport::getSIPLocalIP(); setCallMediaLocal(call, localAddr); // May use the published address as well std::string addrSdp = account->isStunEnabled() ? account->getPublishedAddress() : - getInterfaceAddrFromName(account->getLocalInterface()); + SipTransport::getInterfaceAddrFromName(account->getLocalInterface()); if (addrSdp == "0.0.0.0") - addrSdp = getSIPLocalIP(); + addrSdp = SipTransport::getSIPLocalIP(); // Initialize the session using ULAW as default codec in case of early media // The session should be ready to receive media once the first INVITE is sent, before // the session initialization is completed - sfl::Codec* audiocodec = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW); + sfl::AudioCodec* ac = dynamic_cast<sfl::AudioCodec*>(Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW)); - if (audiocodec == NULL) { + if (ac == NULL) { delete call; throw VoipLinkException("Could not instantiate codec for early media"); } try { - call->getAudioRtp().initAudioRtpConfig(); - call->getAudioRtp().initAudioSymmetricRtpSession(); + call->getAudioRtp().initConfig(); + call->getAudioRtp().initSession(); call->getAudioRtp().initLocalCryptoInfo(); - call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec)); + call->getAudioRtp().start(ac); } catch (...) { delete call; throw VoipLinkException("Could not start rtp session for early media"); @@ -734,23 +821,11 @@ Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toU } void -SIPVoIPLink::answer(Call *c) +SIPVoIPLink::answer(Call *call) { - SIPCall *call = dynamic_cast<SIPCall*>(c); - if (!call) return; - - pjsip_tx_data *tdata; - - if (pjsip_inv_answer(call->inv, PJSIP_SC_OK, NULL, NULL, &tdata) != PJ_SUCCESS) - throw VoipLinkException("Could not init invite request answer (200 OK)"); - - if (pjsip_inv_send_msg(call->inv, tdata) != PJ_SUCCESS) - throw VoipLinkException("Could not send invite request answer (200 OK)"); - - call->setConnectionState(Call::CONNECTED); - call->setState(Call::ACTIVE); + call->answer(); } void @@ -771,7 +846,7 @@ SIPVoIPLink::hangup(const std::string& id) // Looks for sip routes if (not account->getServiceRoute().empty()) { - pjsip_route_hdr *route_set = createRouteSet(account->getServiceRoute(), inv->pool); + pjsip_route_hdr *route_set = sip_utils::createRouteSet(account->getServiceRoute(), inv->pool); pjsip_dlg_set_route_set(inv->dlg, route_set); } @@ -821,6 +896,7 @@ SIPVoIPLink::onhold(const std::string& id) { SIPCall *call = getSIPCall(id); call->setState(Call::HOLD); + call->getAudioRtp().saveLocalContext(); call->getAudioRtp().stop(); Sdp *sdpSession = call->getLocalSDP(); @@ -853,16 +929,18 @@ SIPVoIPLink::offhold(const std::string& id) pl = sessionMedia->getPayloadType(); // Create a new instance for this codec - sfl::Codec* audiocodec = Manager::instance().audioCodecFactory.instantiateCodec(pl); + sfl::AudioCodec* ac = dynamic_cast<sfl::AudioCodec*>(Manager::instance().audioCodecFactory.instantiateCodec(pl)); - if (audiocodec == NULL) + if (ac == NULL) throw VoipLinkException("Could not instantiate codec"); - call->getAudioRtp().initAudioRtpConfig(); - call->getAudioRtp().initAudioSymmetricRtpSession(); - call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec)); + call->getAudioRtp().initConfig(); + call->getAudioRtp().initSession(); + call->getAudioRtp().restoreLocalContext(); + call->getAudioRtp().initLocalCryptoInfoOnOffHold(); + call->getAudioRtp().start(ac); } catch (const SdpException &e) { - ERROR("UserAgent: Exception: %s", e.what()); + ERROR("%s", e.what()); } catch (...) { throw VoipLinkException("Could not create audio rtp session"); } @@ -875,9 +953,11 @@ SIPVoIPLink::offhold(const std::string& id) call->setState(Call::ACTIVE); } -void -SIPVoIPLink::sendTextMessage(sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from) +void SIPVoIPLink::sendTextMessage(const std::string &callID, + const std::string &message, + const std::string &from) { + using namespace sfl::InstantMessaging; SIPCall *call; try { @@ -887,18 +967,19 @@ SIPVoIPLink::sendTextMessage(sfl::InstantMessaging *module, const std::string& c } /* Send IM message */ - sfl::InstantMessaging::UriList list; - sfl::InstantMessaging::UriEntry entry; + UriList list; + UriEntry entry; entry[sfl::IM_XML_URI] = std::string("\"" + from + "\""); // add double quotes for xml formating - list.push_front(entry); - - module->send_sip_message(call->inv, callID, module->appendUriList(message, list)); + send_sip_message(call->inv, callID, appendUriList(message, list)); } bool SIPVoIPLink::transferCommon(SIPCall *call, pj_str_t *dst) { + if (!call or !call->inv) + return false; + pjsip_evsub_user xfer_cb; pj_bzero(&xfer_cb, sizeof(xfer_cb)); xfer_cb.on_evsub_state = &transfer_client_cb; @@ -938,6 +1019,10 @@ void SIPVoIPLink::transfer(const std::string& id, const std::string& to) { SIPCall *call = getSIPCall(id); + if (call == NULL) { + ERROR("Could not find call %s", id.c_str()); + return; + } call->stopRecording(); std::string account_id(Manager::instance().getAccountFromCall(id)); @@ -960,10 +1045,13 @@ SIPVoIPLink::transfer(const std::string& id, const std::string& to) bool SIPVoIPLink::attendedTransfer(const std::string& id, const std::string& to) { - pjsip_dialog *target_dlg = getSIPCall(to)->inv->dlg; + SIPCall *call = getSIPCall(to); + if (!call or !call->inv or !call->inv->dlg) + throw VoipLinkException("Couldn't get invite dialog"); + pjsip_dialog *target_dlg = call->inv->dlg; pjsip_uri *uri = (pjsip_uri*) pjsip_uri_get_uri(target_dlg->remote.info->uri); - char str_dest_buf[PJSIP_MAX_URL_SIZE*2] = { '<' }; + char str_dest_buf[PJSIP_MAX_URL_SIZE * 2] = { '<' }; pj_str_t dst = { str_dest_buf, 1 }; dst.slen += pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, str_dest_buf+1, sizeof(str_dest_buf)-1); @@ -988,13 +1076,12 @@ SIPVoIPLink::refuse(const std::string& id) { SIPCall *call = getSIPCall(id); - if (!call->isIncoming() or call->getConnectionState() == Call::CONNECTED) + if (!call or !call->isIncoming() or call->getConnectionState() == Call::CONNECTED or !call->inv) return; call->getAudioRtp().stop(); pjsip_tx_data *tdata; - if (pjsip_inv_end_session(call->inv, PJSIP_SC_DECLINE, NULL, &tdata) != PJ_SUCCESS) return; @@ -1017,7 +1104,7 @@ void SIPVoIPLink::carryingDTMFdigits(const std::string& id, char code) { std::string accountID(Manager::instance().getAccountFromCall(id)); - SIPAccount *account = static_cast<SIPAccount*>(Manager::instance().getAccount(accountID)); + SIPAccount *account = dynamic_cast<SIPAccount*>(Manager::instance().getAccount(accountID)); if (account) { try { @@ -1073,14 +1160,13 @@ SIPVoIPLink::SIPStartCall(SIPCall *call) std::string id(Manager::instance().getAccountFromCall(call->getCallId())); SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(id)); - if (account == NULL) + if (account == NULL) { + ERROR("Account is NULL in SIPStartCall"); return false; + } std::string toUri(call->getPeerNumber()); // expecting a fully well formed sip uri - // std::string address, port; - // findLocalAddressFromUri(toUri, account->transport_, address, port); - pj_str_t pjTo = pj_str((char*) toUri.c_str()); // Create the from header @@ -1093,31 +1179,44 @@ SIPVoIPLink::SIPStartCall(SIPCall *call) pjsip_dialog *dialog = NULL; - if (pjsip_dlg_create_uac(pjsip_ua_instance(), &pjFrom, &pjContact, &pjTo, NULL, &dialog) != PJ_SUCCESS) + if (pjsip_dlg_create_uac(pjsip_ua_instance(), &pjFrom, &pjContact, &pjTo, NULL, &dialog) != PJ_SUCCESS) { + ERROR("Unable to sip create dialogs for user agent client"); return false; + } - if (pjsip_inv_create_uac(dialog, call->getLocalSDP()->getLocalSdpSession(), 0, &call->inv) != PJ_SUCCESS) + if (pjsip_inv_create_uac(dialog, call->getLocalSDP()->getLocalSdpSession(), 0, &call->inv) != PJ_SUCCESS) { + ERROR("Unable to create invite session for user agent client"); return false; + } if (not account->getServiceRoute().empty()) - pjsip_dlg_set_route_set(dialog, createRouteSet(account->getServiceRoute(), call->inv->pool)); + pjsip_dlg_set_route_set(dialog, sip_utils::createRouteSet(account->getServiceRoute(), call->inv->pool)); - pjsip_auth_clt_set_credentials(&dialog->auth_sess, account->getCredentialCount(), account->getCredInfo()); + if (pjsip_auth_clt_set_credentials(&dialog->auth_sess, account->getCredentialCount(), account->getCredInfo()) != PJ_SUCCESS) { + ERROR("Could not initiaize credential for invite session authentication"); + return false; + } call->inv->mod_data[mod_ua_.id] = call; pjsip_tx_data *tdata; - if (pjsip_inv_invite(call->inv, &tdata) != PJ_SUCCESS) + if (pjsip_inv_invite(call->inv, &tdata) != PJ_SUCCESS) { + ERROR("Could not initialize invite messager for this call"); return false; + } - pjsip_tpselector *tp = initTransportSelector(account->transport_, call->inv->pool); + pjsip_tpselector *tp = sipTransport.initTransportSelector(account->transport_, call->inv->pool); - if (pjsip_dlg_set_transport(dialog, tp) != PJ_SUCCESS) + if (pjsip_dlg_set_transport(dialog, tp) != PJ_SUCCESS) { + ERROR("Unable to associate transport fir invite session dialog"); return false; + } - if (pjsip_inv_send_msg(call->inv, tdata) != PJ_SUCCESS) + if (pjsip_inv_send_msg(call->inv, tdata) != PJ_SUCCESS) { + ERROR("Unable to send invite message for this call"); return false; + } call->setConnectionState(Call::PROGRESSING); call->setState(Call::ACTIVE); @@ -1147,7 +1246,7 @@ SIPVoIPLink::SIPCallClosed(SIPCall *call) } void -SIPVoIPLink::SIPCallAnswered(SIPCall *call, pjsip_rx_data *rdata UNUSED) +SIPVoIPLink::SIPCallAnswered(SIPCall *call, pjsip_rx_data * /*rdata*/) { if (call->getConnectionState() != Call::CONNECTED) { call->setConnectionState(Call::CONNECTED); @@ -1168,410 +1267,51 @@ SIPVoIPLink::getSIPCall(const std::string& id) return result; } -bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to) -{ - SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(IP2IP_PROFILE)); - - if (!account) - return false; - - SIPCall *call = new SIPCall(id, Call::OUTGOING, cp_); - call->setIPToIP(true); - call->initRecFilename(to); - - std::string localAddress(getInterfaceAddrFromName(account->getLocalInterface())); - - if (localAddress == "0.0.0.0") - localAddress = getSIPLocalIP(); - - setCallMediaLocal(call, localAddress); - - std::string toUri = account->getToUri(to); - call->setPeerNumber(toUri); - - sfl::Codec* audiocodec = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW); - - // Audio Rtp Session must be initialized before creating initial offer in SDP session - // since SDES require crypto attribute. - call->getAudioRtp().initAudioRtpConfig(); - call->getAudioRtp().initAudioSymmetricRtpSession(); - call->getAudioRtp().initLocalCryptoInfo(); - call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec)); - - // Building the local SDP offer - call->getLocalSDP()->setLocalIP(localAddress); - call->getLocalSDP()->createOffer(account->getActiveCodecs()); - - // Init TLS transport if enabled - if (account->isTlsEnabled()) { - size_t at = toUri.find("@"); - size_t trns = toUri.find(";transport"); - if (at == std::string::npos or trns == std::string::npos) { - ERROR("UserAgent: Error \"@\" or \";transport\" not in URI %s", toUri.c_str()); - delete call; - return false; - } - - std::string remoteAddr(toUri.substr(at + 1, trns - at - 1)); - - if (toUri.find("sips:") != 1) { - DEBUG("UserAgent: Error \"sips\" scheme required for TLS call"); - delete call; - return false; - } - - shutdownSipTransport(account); - createTlsTransport(account, remoteAddr); - - if (!account->transport_) { - delete call; - return false; - } - } - - if (!SIPStartCall(call)) { - delete call; - return false; - } - - return true; -} - - /////////////////////////////////////////////////////////////////////////////// // Private functions /////////////////////////////////////////////////////////////////////////////// -pj_bool_t stun_sock_on_status_cb(pj_stun_sock *stun_sock UNUSED, pj_stun_sock_op op UNUSED, pj_status_t status) -{ - return status == PJ_SUCCESS; -} - -pj_bool_t stun_sock_on_rx_data_cb(pj_stun_sock *stun_sock UNUSED, void *pkt UNUSED, unsigned pkt_len UNUSED, const pj_sockaddr_t *src_addr UNUSED, unsigned addr_len UNUSED) -{ - return PJ_TRUE; -} - - -pj_status_t SIPVoIPLink::stunServerResolve(SIPAccount *account) -{ - pj_stun_config stunCfg; - pj_stun_config_init(&stunCfg, &cp_->factory, 0, pjsip_endpt_get_ioqueue(endpt_), pjsip_endpt_get_timer_heap(endpt_)); - - static const pj_stun_sock_cb stun_sock_cb = { - stun_sock_on_rx_data_cb, - NULL, - stun_sock_on_status_cb - }; - - pj_stun_sock *stun_sock; - pj_status_t status = pj_stun_sock_create(&stunCfg, "stunresolve", pj_AF_INET(), &stun_sock_cb, NULL, NULL, &stun_sock); - - pj_str_t stunServer = account->getStunServerName(); - - if (status != PJ_SUCCESS) { - char errmsg[PJ_ERR_MSG_SIZE]; - pj_strerror(status, errmsg, sizeof(errmsg)); - DEBUG("Error creating STUN socket for %.*s: %s", (int) stunServer.slen, stunServer.ptr, errmsg); - return status; - } - - status = pj_stun_sock_start(stun_sock, &stunServer, account->getStunPort(), NULL); - - if (status != PJ_SUCCESS) { - char errmsg[PJ_ERR_MSG_SIZE]; - pj_strerror(status, errmsg, sizeof(errmsg)); - DEBUG("Error starting STUN socket for %.*s: %s", (int) stunServer.slen, stunServer.ptr, errmsg); - pj_stun_sock_destroy(stun_sock); - } - - return status; -} - - -void SIPVoIPLink::createDefaultSipUdpTransport() -{ - SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(IP2IP_PROFILE)); - createUdpTransport(account); - assert(account->transport_); - - localUDPTransport_ = account->transport_; -} - -void SIPVoIPLink::createTlsListener(SIPAccount *account, pjsip_tpfactory **listener) -{ - pj_sockaddr_in local_addr; - pj_sockaddr_in_init(&local_addr, 0, 0); - local_addr.sin_port = pj_htons(account->getTlsListenerPort()); - - pj_str_t pjAddress; - pj_cstr(&pjAddress, PJ_INADDR_ANY); - pj_sockaddr_in_set_str_addr(&local_addr, &pjAddress); - std::string localIP(getSIPLocalIP()); - - pjsip_host_port a_name = { - pj_str((char*) localIP.c_str()), - local_addr.sin_port - }; - - pjsip_tls_transport_start(endpt_, account->getTlsSetting(), &local_addr, &a_name, 1, listener); -} - - -void SIPVoIPLink::createTlsTransport(SIPAccount *account, std::string remoteAddr) -{ - pj_str_t remote; - pj_cstr(&remote, remoteAddr.c_str()); - - pj_sockaddr_in rem_addr; - pj_sockaddr_in_init(&rem_addr, &remote, (pj_uint16_t) DEFAULT_SIP_TLS_PORT); - - static pjsip_tpfactory *localTlsListener = NULL; /** The local tls listener */ - - if (localTlsListener == NULL) - createTlsListener(account, &localTlsListener); - - pjsip_endpt_acquire_transport(endpt_, PJSIP_TRANSPORT_TLS, &rem_addr, - sizeof rem_addr, NULL, &account->transport_); -} - - -void SIPVoIPLink::createSipTransport(SIPAccount *account) -{ - shutdownSipTransport(account); - - if (account->isTlsEnabled()) { - std::string remoteSipUri(account->getServerUri()); - static const char SIPS_PREFIX[] = "<sips:"; - size_t sips = remoteSipUri.find(SIPS_PREFIX) + (sizeof SIPS_PREFIX) - 1; - size_t trns = remoteSipUri.find(";transport"); - std::string remoteAddr(remoteSipUri.substr(sips, trns-sips)); - - createTlsTransport(account, remoteAddr); - } else if (account->isStunEnabled()) - createStunTransport(account); - else - createUdpTransport(account); - - if (!account->transport_) { - // Could not create new transport, this transport may already exists - account->transport_ = transportMap_[account->getLocalPort()]; - - if (account->transport_) - pjsip_transport_add_ref(account->transport_); - else { - account->transport_ = localUDPTransport_; - account->setLocalPort(localUDPTransport_->local_name.port); - } - } -} - -void SIPVoIPLink::createUdpTransport(SIPAccount *account) -{ - std::string listeningAddress; - pj_uint16_t listeningPort = account->getLocalPort(); - - pj_sockaddr_in bound_addr; - pj_bzero(&bound_addr, sizeof(bound_addr)); - bound_addr.sin_port = pj_htons(listeningPort); - bound_addr.sin_family = PJ_AF_INET; - - if (account->getLocalInterface() == "default") { - listeningAddress = getSIPLocalIP(); - bound_addr.sin_addr.s_addr = pj_htonl(PJ_INADDR_ANY); - } else { - listeningAddress = getInterfaceAddrFromName(account->getLocalInterface()); - bound_addr.sin_addr = pj_inet_addr2(listeningAddress.c_str()); - } - - if (!account->getPublishedSameasLocal()) { - listeningAddress = account->getPublishedAddress(); - listeningPort = account->getPublishedPort(); - } - - // We must specify this here to avoid the IP2IP_PROFILE creating a - // transport with the name 0.0.0.0 appearing in the via header - if (account->getAccountID() == IP2IP_PROFILE) - listeningAddress = getSIPLocalIP(); - - if (listeningAddress.empty() or listeningPort == 0) - return; - - const pjsip_host_port a_name = { - pj_str((char*) listeningAddress.c_str()), - listeningPort - }; - - pjsip_udp_transport_start(endpt_, &bound_addr, &a_name, 1, &account->transport_); - pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); // dump debug information to stdout - - if (account->transport_) - transportMap_[account->getLocalPort()] = account->transport_; -} - -pjsip_tpselector *SIPVoIPLink::initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const -{ - assert(transport); - pjsip_tpselector *tp = (pjsip_tpselector *) pj_pool_zalloc(tp_pool, sizeof(pjsip_tpselector)); - tp->type = PJSIP_TPSELECTOR_TRANSPORT; - tp->u.transport = transport; - return tp; -} - - - -void SIPVoIPLink::createStunTransport(SIPAccount *account) -{ - pj_str_t stunServer = account->getStunServerName(); - pj_uint16_t stunPort = account->getStunPort(); - - if (stunServerResolve(account) != PJ_SUCCESS) { - ERROR("Can't resolve STUN server"); - return; - } - - pj_sock_t sock = PJ_INVALID_SOCKET; - - pj_sockaddr_in boundAddr; - - if (pj_sockaddr_in_init(&boundAddr, &stunServer, 0) != PJ_SUCCESS) { - ERROR("Can't initialize IPv4 socket on %*s:%i", stunServer.slen, stunServer.ptr, stunPort); - return; - } - - if (pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock) != PJ_SUCCESS) { - ERROR("Can't create or bind socket"); - return; - } - - // Query the mapped IP address and port on the 'outside' of the NAT - pj_sockaddr_in pub_addr; - - if (pjstun_get_mapped_addr(&cp_->factory, 1, &sock, &stunServer, stunPort, &stunServer, stunPort, &pub_addr) != PJ_SUCCESS) { - ERROR("Can't contact STUN server"); - pj_sock_close(sock); - return; - } - - pjsip_host_port a_name = { - pj_str(pj_inet_ntoa(pub_addr.sin_addr)), - pj_ntohs(pub_addr.sin_port) - }; - - std::string listeningAddress = std::string(a_name.host.ptr, a_name.host.slen); - - account->setPublishedAddress(listeningAddress); - account->setPublishedPort(a_name.port); - - pjsip_udp_transport_attach2(endpt_, PJSIP_TRANSPORT_UDP, sock, &a_name, 1, - &account->transport_); - - pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); -} - - -void SIPVoIPLink::shutdownSipTransport(SIPAccount *account) -{ - if (account->transport_) { - pjsip_transport_dec_ref(account->transport_); - account->transport_ = NULL; - } -} - -void SIPVoIPLink::findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &addr, std::string &port) const -{ - // Initialize the sip port with the default SIP port - std::stringstream ss; - ss << DEFAULT_SIP_PORT; - port = ss.str(); - - // Initialize the sip address with the hostname - const pj_str_t *pjMachineName = pj_gethostname(); - addr = std::string(pjMachineName->ptr, pjMachineName->slen); - - // Update address and port with active transport - if (!transport) { - ERROR("SIPVoIPLink: Transport is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str()); - return; - } - - // get the transport manager associated with the SIP enpoint - pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt_); - if (!tpmgr) { - ERROR("SIPVoIPLink: Transport manager is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str()); - return; - } - - // initialize a transport selector - // TODO Need to determine why we exclude TLS here... - // if (transportType == PJSIP_TRANSPORT_UDP and transport_) - pjsip_tpselector *tp_sel = initTransportSelector(transport, pool_); - if (!tp_sel) { - ERROR("SIPVoIPLink: Could not initialize transport selector, using local address %s:%s", addr.c_str(), port.c_str()); - return; - } - - pj_str_t localAddress = {0,0}; - int i_port = 0; - - // Find the local address and port for this transport - if (pjsip_tpmgr_find_local_addr(tpmgr, pool_, transportType, tp_sel, &localAddress, &i_port) != PJ_SUCCESS) { - WARN("SIPVoIPLink: Could not retreive local address and port from transport, using %s:%s", addr.c_str(), port.c_str()); - return; - } - - // Update local address based on the transport type - addr = std::string(localAddress.ptr, localAddress.slen); - - // Fallback on local ip provided by pj_gethostip() - if (addr == "0.0.0.0") - addr = getSIPLocalIP(); - - // Determine the local port based on transport information - ss.str(""); - ss << i_port; - port = ss.str(); -} - namespace { int SIPSessionReinvite(SIPCall *call) { - pjsip_tx_data *tdata; - pjmedia_sdp_session *local_sdp = call->getLocalSDP()->getLocalSdpSession(); - + pjsip_tx_data *tdata; if (local_sdp && pjsip_inv_reinvite(call->inv, NULL, local_sdp, &tdata) == PJ_SUCCESS) return pjsip_inv_send_msg(call->inv, tdata); return !PJ_SUCCESS; } -void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e) +void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *ev) { + if (!inv) + return; SIPCall *call = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]); if (call == NULL) return; - SIPVoIPLink *link = SIPVoIPLink::instance(); - - if (inv->state != PJSIP_INV_STATE_CONFIRMED) { + if (ev and inv->state != PJSIP_INV_STATE_CONFIRMED) { // Update UI with the current status code and description - pjsip_transaction * tsx = e->body.tsx_state.tsx; + pjsip_transaction * tsx = ev->body.tsx_state.tsx; int statusCode = tsx ? tsx->status_code : 404; if (statusCode) { const pj_str_t * description = pjsip_get_status_text(statusCode); - Manager::instance().getDbusManager()->getCallManager()->sipCallStateChanged(call->getCallId(), std::string(description->ptr, description->slen), statusCode); + std::string desc(description->ptr, description->slen); + CallManager *cm = Manager::instance().getDbusManager()->getCallManager(); + cm->sipCallStateChanged(call->getCallId(), desc, statusCode); } } - if (inv->state == PJSIP_INV_STATE_EARLY and e->body.tsx_state.tsx->role == PJSIP_ROLE_UAC) { + SIPVoIPLink *link = SIPVoIPLink::instance(); + if (inv->state == PJSIP_INV_STATE_EARLY and ev and ev->body.tsx_state.tsx and + ev->body.tsx_state.tsx->role == PJSIP_ROLE_UAC) { call->setConnectionState(Call::RINGING); Manager::instance().peerRingingCall(call->getCallId()); - } else if (inv->state == PJSIP_INV_STATE_CONFIRMED) { + } else if (inv->state == PJSIP_INV_STATE_CONFIRMED and ev) { // After we sent or received a ACK - The connection is established - link->SIPCallAnswered(call, e->body.tsx_state.src.rdata); + link->SIPCallAnswered(call, ev->body.tsx_state.src.rdata); } else if (inv->state == PJSIP_INV_STATE_DISCONNECTED) { std::string accId(Manager::instance().getAccountFromCall(call->getCallId())); @@ -1582,7 +1322,6 @@ void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e) link->SIPCallClosed(call); break; case PJSIP_SC_DECLINE: - if (inv->role != PJSIP_ROLE_UAC) break; @@ -1604,13 +1343,17 @@ void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e) void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer) { - SIPCall *call = (SIPCall*) inv->mod_data[mod_ua_.id ]; + if (!inv) + return; + SIPCall *call = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]); if (!call) return; std::string accId(Manager::instance().getAccountFromCall(call->getCallId())); SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(accId)); + if (!account) + return; call->getLocalSDP()->receiveOffer(offer, account->getActiveCodecs()); call->getLocalSDP()->startNegotiation(); @@ -1620,16 +1363,20 @@ void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *off void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) { + if (!inv or !p_offer) + return; SIPCall *call = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]); + if (!call) + return; std::string accountid(Manager::instance().getAccountFromCall(call->getCallId())); SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(accountid)); - std::string localAddress(SIPVoIPLink::instance()->getInterfaceAddrFromName(account->getLocalInterface())); + std::string localAddress(SipTransport::getInterfaceAddrFromName(account->getLocalInterface())); std::string addrSdp(localAddress); if (localAddress == "0.0.0.0") - localAddress = getSIPLocalIP(); + localAddress = SipTransport::getSIPLocalIP(); if (addrSdp == "0.0.0.0") addrSdp = localAddress; @@ -1645,44 +1392,49 @@ void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) // This callback is called after SDP offer/answer session has completed. void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) { - const pjmedia_sdp_session *remote_sdp; - const pjmedia_sdp_session *local_sdp; - + if (!inv) + return; SIPCall *call = static_cast<SIPCall *>(inv->mod_data[mod_ua_.id]); if (call == NULL) { - DEBUG("UserAgent: Call declined by peer, SDP negotiation stopped"); + DEBUG("Call declined by peer, SDP negotiation stopped"); return; } if (status != PJ_SUCCESS) { - WARN("UserAgent: Error: while negotiating the offer"); + WARN("Could not negotiate offer"); SIPVoIPLink::instance()->hangup(call->getCallId()); Manager::instance().callFailure(call->getCallId()); return; } if (!inv->neg) { - WARN("UserAgent: Error: no negotiator for this session"); + WARN("No negotiator for this session"); return; } // Retreive SDP session for this call Sdp *sdpSession = call->getLocalSDP(); + if (!sdpSession) { + ERROR("No SDP session"); + return; + } // Get active session sessions + const pjmedia_sdp_session *remote_sdp; pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp); + const pjmedia_sdp_session *local_sdp; pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp); // Print SDP session char buffer[1000]; memset(buffer, 0, sizeof buffer); - pjmedia_sdp_print(remote_sdp, buffer, 1000); - DEBUG("SDP: Remote active SDP Session:\n%s", buffer); + pjmedia_sdp_print(remote_sdp, buffer, sizeof buffer); + DEBUG("Remote active SDP Session:\n%s", buffer); - memset(buffer, 0, 1000); - pjmedia_sdp_print(local_sdp, buffer, 1000); - DEBUG("SDP: Local active SDP Session:\n%s", buffer); + memset(buffer, 0, sizeof buffer); + pjmedia_sdp_print(local_sdp, buffer, sizeof buffer); + DEBUG("Local active SDP Session:\n%s", buffer); // Set active SDP sessions sdpSession->setActiveRemoteSdpSession(remote_sdp); @@ -1701,15 +1453,14 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) bool nego_success = false; if (!crypto_offer.empty()) { - std::vector<sfl::CryptoSuiteDefinition>localCapabilities; + std::vector<sfl::CryptoSuiteDefinition> localCapabilities; - for (int i = 0; i < 3; i++) + for (size_t i = 0; i < ARRAYSIZE(sfl::CryptoSuites); ++i) localCapabilities.push_back(sfl::CryptoSuites[i]); sfl::SdesNegotiator sdesnego(localCapabilities, crypto_offer); if (sdesnego.negotiate()) { - DEBUG("UserAgent: SDES negotiation successfull"); nego_success = true; try { @@ -1718,25 +1469,26 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) Manager::instance().getDbusManager()->getCallManager()->secureSdesOn(call->getCallId()); } else { + ERROR("SDES negotiation failure"); Manager::instance().getDbusManager()->getCallManager()->secureSdesOff(call->getCallId()); } } + else { + DEBUG("No crypto offer available"); + } - - // We did not found any crypto context for this media, RTP fallback + // We did not find any crypto context for this media, RTP fallback if (!nego_success && call->getAudioRtp().isSdesEnabled()) { + ERROR("Negotiation failed but SRTP is enabled, fallback on RTP"); call->getAudioRtp().stop(); call->getAudioRtp().setSrtpEnabled(false); std::string accountID = Manager::instance().getAccountFromCall(call->getCallId()); - if (((SIPAccount *) Manager::instance().getAccount(accountID))->getSrtpFallback()) - call->getAudioRtp().initAudioSymmetricRtpSession(); + if (dynamic_cast<SIPAccount*>(Manager::instance().getAccount(accountID))->getSrtpFallback()) + call->getAudioRtp().initSession(); } - if (!sdpSession) - return; - sfl::AudioCodec *sessionMedia = sdpSession->getSessionMedia(); if (!sessionMedia) @@ -1750,42 +1502,43 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) int pl = sessionMedia->getPayloadType(); if (pl != call->getAudioRtp().getSessionMedia()) { - sfl::Codec* audiocodec = Manager::instance().audioCodecFactory.instantiateCodec(pl); - call->getAudioRtp().updateSessionMedia(static_cast<sfl::AudioCodec *>(audiocodec)); + sfl::AudioCodec *ac = dynamic_cast<sfl::AudioCodec*>(Manager::instance().audioCodecFactory.instantiateCodec(pl)); + if (!ac) + throw std::runtime_error("Could not instantiate codec"); + call->getAudioRtp().updateSessionMedia(ac); } } catch (const SdpException &e) { - ERROR("UserAgent: Exception: %s", e.what()); - } catch (const std::exception& rtpException) { - ERROR("UserAgent: Exception: %s", rtpException.what()); + ERROR("%s", e.what()); + } catch (const std::exception &rtpException) { + ERROR("%s", rtpException.what()); } } -void outgoing_request_forked_cb(pjsip_inv_session *inv UNUSED, pjsip_event *e UNUSED) -{ -} +void outgoing_request_forked_cb(pjsip_inv_session * /*inv*/, pjsip_event * /*e*/) +{} -void transaction_state_changed_cb(pjsip_inv_session *inv UNUSED, pjsip_transaction *tsx, pjsip_event *e) +void transaction_state_changed_cb(pjsip_inv_session * inv, + pjsip_transaction *tsx, pjsip_event *event) { - assert(tsx); - assert(e); - - if (tsx->role != PJSIP_ROLE_UAS || tsx->state != PJSIP_TSX_STATE_TRYING) + if (!tsx or !event or !inv or tsx->role != PJSIP_ROLE_UAS or + tsx->state != PJSIP_TSX_STATE_TRYING) return; - if (pjsip_method_cmp(&tsx->method, &pjsip_refer_method) ==0) { - onCallTransfered(inv, e->body.tsx_state.src.rdata); /** Handle the refer method **/ + // Handle the refer method + if (pjsip_method_cmp(&tsx->method, &pjsip_refer_method) == 0) { + onCallTransfered(inv, event->body.tsx_state.src.rdata); return; } pjsip_tx_data* t_data; - if (e->body.rx_msg.rdata) { - pjsip_rx_data *r_data = e->body.rx_msg.rdata; + if (event->body.rx_msg.rdata) { + pjsip_rx_data *r_data = event->body.rx_msg.rdata; if (r_data && r_data->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD) { std::string request = pjsip_rx_data_get_info(r_data); - DEBUG("UserAgent: %s", request.c_str()); + DEBUG("%s", request.c_str()); if (request.find("NOTIFY") == std::string::npos && request.find("INFO") != std::string::npos) { pjsip_dlg_create_response(inv->dlg, r_data, PJSIP_SC_OK, NULL, &t_data); @@ -1795,14 +1548,19 @@ void transaction_state_changed_cb(pjsip_inv_session *inv UNUSED, pjsip_transacti } } - if (!e->body.tsx_state.src.rdata) + if (!event->body.tsx_state.src.rdata) return; // Incoming TEXT message // Get the message inside the transaction - pjsip_rx_data *r_data = e->body.tsx_state.src.rdata; - std::string formatedMessage = (char*) r_data->msg_info.msg->body->data; + pjsip_rx_data *r_data = event->body.tsx_state.src.rdata; + if (!r_data->msg_info.msg->body) + return; + const char *formattedMsgPtr = static_cast<const char*>(r_data->msg_info.msg->body->data); + if (!formattedMsgPtr) + return; + std::string formattedMessage(formattedMsgPtr, strlen(formattedMsgPtr)); // Try to determine who is the recipient of the message SIPCall *call = static_cast<SIPCall *>(inv->mod_data[mod_ua_.id]); @@ -1814,12 +1572,12 @@ void transaction_state_changed_cb(pjsip_inv_session *inv UNUSED, pjsip_transacti pjsip_dlg_create_response(inv->dlg, r_data, PJSIP_SC_OK, NULL, &t_data); pjsip_dlg_send_response(inv->dlg, tsx, t_data); - sfl::InstantMessaging *module = Manager::instance().getInstantMessageModule(); + using namespace sfl::InstantMessaging; try { // retreive the recipient-list of this message - std::string urilist = module->findTextUriList(formatedMessage); - sfl::InstantMessaging::UriList list = module->parseXmlUriList(urilist); + std::string urilist = findTextUriList(formattedMessage); + UriList list = parseXmlUriList(urilist); // If no item present in the list, peer is considered as the sender std::string from; @@ -1837,47 +1595,50 @@ void transaction_state_changed_cb(pjsip_inv_session *inv UNUSED, pjsip_transacti if (from[0] == '<' && from[from.size()-1] == '>') from = from.substr(1, from.size()-2); - Manager::instance().incomingMessage(call->getCallId(), from, module->findTextMessage(formatedMessage)); + Manager::instance().incomingMessage(call->getCallId(), from, findTextMessage(formattedMessage)); } catch (const sfl::InstantMessageException &except) { - ERROR("SipVoipLink: %s", except.what()); + ERROR("%s", except.what()); } } void update_contact_header(pjsip_regc_cbparam *param, SIPAccount *account) { - SIPVoIPLink *siplink = dynamic_cast<SIPVoIPLink *>(account->getVoIPLink()); - if(siplink == NULL) { - ERROR("SIPVoIPLink: Could not find voip link from account"); + if (siplink == NULL) { + ERROR("Could not find voip link from account"); return; } pj_pool_t *pool = pj_pool_create(&cp_->factory, "tmp", 512, 512, NULL); - if(pool == NULL) { - ERROR("SIPVoIPLink: Could not create temporary memory pool in transport header"); + if (pool == NULL) { + ERROR("Could not create temporary memory pool in transport header"); return; } - if (param->contact_cnt == 0) { + if (!param or param->contact_cnt == 0) { WARN("SIPVoIPLink: No contact header in registration callback"); pj_pool_release(pool); return; } pjsip_contact_hdr *contact_hdr = param->contact[0]; + if (!contact_hdr) + return; pjsip_sip_uri *uri = (pjsip_sip_uri*) contact_hdr->uri; if (uri == NULL) { - ERROR("SIPVoIPLink: Could not find uri in contact header"); + ERROR("Could not find uri in contact header"); pj_pool_release(pool); return; } // TODO: make this based on transport type // with pjsip_transport_get_default_port_for_type(tp_type); - if (uri->port == 0) + if (uri->port == 0) { + ERROR("Port is 0 in uri"); uri->port = DEFAULT_SIP_PORT; + } std::string recvContactHost(uri->host.ptr, uri->host.slen); std::stringstream ss; @@ -1885,107 +1646,141 @@ void update_contact_header(pjsip_regc_cbparam *param, SIPAccount *account) std::string recvContactPort = ss.str(); std::string currentAddress, currentPort; - siplink->findLocalAddressFromTransport(account->transport_, PJSIP_TRANSPORT_UDP, currentAddress, currentPort); + siplink->sipTransport.findLocalAddressFromTransport(account->transport_, PJSIP_TRANSPORT_UDP, currentAddress, currentPort); bool updateContact = false; std::string currentContactHeader = account->getContactHeader(); size_t foundHost = currentContactHeader.find(recvContactHost); - if(foundHost == std::string::npos) { + if (foundHost == std::string::npos) updateContact = true; - } size_t foundPort = currentContactHeader.find(recvContactPort); - if(foundPort == std::string::npos) { + if (foundPort == std::string::npos) updateContact = true; - } - if(updateContact) { - DEBUG("SIPVoIPLink: Update contact header: %s:%s\n", recvContactHost.c_str(), recvContactPort.c_str()); + if (updateContact) { + DEBUG("Update contact header: %s:%s\n", recvContactHost.c_str(), recvContactPort.c_str()); account->setContactHeader(recvContactHost, recvContactPort); siplink->sendRegister(account); } pj_pool_release(pool); } -void registration_cb(pjsip_regc_cbparam *param) +void lookForReceivedParameter(pjsip_regc_cbparam ¶m, SIPAccount &account) { - SIPAccount *account = static_cast<SIPAccount *>(param->token); - - if (account == NULL) { - ERROR("SipVoipLink: account does'nt exist in registration callback"); + if (!param.rdata or !param.rdata->msg_info.via) return; + pj_str_t receivedValue = param.rdata->msg_info.via->recvd_param; + + if (receivedValue.slen) { + std::string publicIpFromReceived(receivedValue.ptr, receivedValue.slen); + account.setReceivedParameter(publicIpFromReceived); } + account.setRPort(param.rdata->msg_info.via->rport_param); +} + +void processRegistrationError(SIPAccount &account, RegistrationState state) +{ + account.stopKeepAliveTimer(); + account.setRegistrationState(state); + account.setRegister(false); + SIPVoIPLink::instance()->sipTransport.shutdownSipTransport(account); +} + +void registration_cb(pjsip_regc_cbparam *param) +{ if (param == NULL) { - ERROR("SipVoipLink: regsitration callback param is NULL"); + ERROR("registration callback parameter is NULL"); return; } - if(account->isContactUpdateEnabled()) { - update_contact_header(param, account); + SIPAccount *account = static_cast<SIPAccount *>(param->token); + if (account == NULL) { + ERROR("account doesn't exist in registration callback"); + return; } + if (account->isContactUpdateEnabled()) + update_contact_header(param, account); + const pj_str_t *description = pjsip_get_status_text(param->code); + const std::string accountID = account->getAccountID(); + if (param->code && description) { std::string state(description->ptr, description->slen); - Manager::instance().getDbusManager()->getCallManager()->registrationStateChanged(account->getAccountID(), state, param->code); + Manager::instance().getDbusManager()->getCallManager()->registrationStateChanged(accountID, state, param->code); std::pair<int, std::string> details(param->code, state); // TODO: there id a race condition for this ressource when closing the application account->setRegistrationStateDetailed(details); - account->setRegistrationExpire(param->expiration); } - if (param->status != PJ_SUCCESS) { - account->setRegistrationState(ErrorAuth); - account->setRegister(false); +#define FAILURE_MESSAGE() ERROR("Could not register account %s with error %d", accountID.c_str(), param->code) - SIPVoIPLink::instance()->shutdownSipTransport(account); + if (param->status != PJ_SUCCESS) { + FAILURE_MESSAGE(); + processRegistrationError(*account, ErrorAuth); return; } if (param->code < 0 || param->code >= 300) { switch (param->code) { - case 606: - account->setRegistrationState(ErrorConfStun); + case PJSIP_SC_MULTIPLE_CHOICES: // 300 + case PJSIP_SC_MOVED_PERMANENTLY: // 301 + case PJSIP_SC_MOVED_TEMPORARILY: // 302 + case PJSIP_SC_USE_PROXY: // 305 + case PJSIP_SC_ALTERNATIVE_SERVICE: // 380 + FAILURE_MESSAGE(); + processRegistrationError(*account, Error); break; - - case 503: - case 408: - account->setRegistrationState(ErrorHost); + case PJSIP_SC_SERVICE_UNAVAILABLE: // 503 + FAILURE_MESSAGE(); + processRegistrationError(*account, ErrorHost); break; - - case 401: - case 403: - case 404: - account->setRegistrationState(ErrorAuth); + case PJSIP_SC_UNAUTHORIZED: // 401 + // Automatically answered by PJSIP + account->registerVoIPLink(); break; - - case 423: { // Expiration Interval Too Brief + case PJSIP_SC_FORBIDDEN: // 403 + case PJSIP_SC_NOT_FOUND: // 404 + FAILURE_MESSAGE(); + processRegistrationError(*account, ErrorAuth); + break; + case PJSIP_SC_REQUEST_TIMEOUT: // 408 + FAILURE_MESSAGE(); + processRegistrationError(*account, ErrorHost); + break; + case PJSIP_SC_INTERVAL_TOO_BRIEF: // 423 + // Expiration Interval Too Brief account->doubleRegistrationExpire(); account->registerVoIPLink(); - } - break; - + account->setRegister(false); + break; + case PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE: // 606 + lookForReceivedParameter(*param, *account); + account->setRegistrationState(ErrorNotAcceptable); + account->registerVoIPLink(); + break; default: - account->setRegistrationState(Error); + FAILURE_MESSAGE(); + processRegistrationError(*account, Error); break; } - account->setRegister(false); - - SIPVoIPLink::instance()->shutdownSipTransport(account); - } else { + lookForReceivedParameter(*param, *account); if (account->isRegistered()) account->setRegistrationState(Registered); else { account->setRegistrationState(Unregistered); - SIPVoIPLink::instance()->shutdownSipTransport(account); + SIPVoIPLink::instance()->sipTransport.shutdownSipTransport(*account); } } + +#undef FAILURE_MESSAGE } void onCallTransfered(pjsip_inv_session *inv, pjsip_rx_data *rdata) @@ -2012,6 +1807,8 @@ void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event) { switch (pjsip_evsub_get_state(sub)) { case PJSIP_EVSUB_STATE_ACCEPTED: + if (!event) + return; pj_assert(event->type == PJSIP_EVENT_TSX_STATE && event->body.tsx_state.type == PJSIP_EVENT_RX_MSG); break; @@ -2034,6 +1831,8 @@ void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event) pjsip_status_line status_line = { 500, *pjsip_get_status_text(500) }; + if (!r_data->msg_info.msg) + return; if (r_data->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD and request.find("NOTIFY") != std::string::npos) { pjsip_msg_body *body = r_data->msg_info.msg->body; @@ -2049,15 +1848,19 @@ void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event) return; } + if (r_data->msg_info.cid) + return; std::string transferID(r_data->msg_info.cid->id.ptr, r_data->msg_info.cid->id.slen); SIPCall *call = dynamic_cast<SIPCall *>(link->getCall(transferCallID[transferID])); if (!call) return; - if (status_line.code/100 == 2) { + if (status_line.code / 100 == 2) { pjsip_tx_data *tdata; + if (!call->inv) + return; if (pjsip_inv_end_session(call->inv, PJSIP_SC_GONE, NULL, &tdata) == PJ_SUCCESS) pjsip_inv_send_msg(call->inv, tdata); @@ -2076,6 +1879,8 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP) { std::string account_id(Manager::instance().getAccountFromCall(call->getCallId())); SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(account_id)); + if (!account) + return; unsigned int callLocalAudioPort = ((rand() % 27250) + 5250) * 2; @@ -2087,85 +1892,4 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP) call->setLocalAudioPort(callLocalAudioPort); call->getLocalSDP()->setLocalPublishedAudioPort(callLocalExternAudioPort); } - -std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field) -{ - pj_str_t name = pj_str((char*) field.c_str()); - - pjsip_generic_string_hdr *hdr = static_cast<pjsip_generic_string_hdr*>(pjsip_msg_find_hdr_by_name(msg, &name, NULL)); - - if (!hdr) - return ""; - - std::string value(std::string(hdr->hvalue.ptr, hdr->hvalue.slen)); - - size_t pos = value.find("\n"); - - if (pos == std::string::npos) - return ""; - - return value.substr(0, pos); -} } // end anonymous namespace - -std::vector<std::string> SIPVoIPLink::getAllIpInterfaceByName() -{ - static ifreq ifreqs[20]; - ifconf ifconf; - - std::vector<std::string> ifaceList; - ifaceList.push_back("default"); - - ifconf.ifc_buf = (char*) (ifreqs); - ifconf.ifc_len = sizeof(ifreqs); - - int sock = socket(AF_INET,SOCK_STREAM,0); - - if (sock >= 0) { - if (ioctl(sock, SIOCGIFCONF, &ifconf) >= 0) - for (unsigned i = 0; i < ifconf.ifc_len / sizeof(ifreq); ++i) - ifaceList.push_back(std::string(ifreqs[i].ifr_name)); - - close(sock); - } - - return ifaceList; -} - -std::string SIPVoIPLink::getInterfaceAddrFromName(const std::string &ifaceName) -{ - int fd = socket(AF_INET, SOCK_DGRAM,0); - - if (fd < 0) { - ERROR("UserAgent: Error: could not open socket: %m"); - return ""; - } - - ifreq ifr; - strcpy(ifr.ifr_name, ifaceName.c_str()); - memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); - ifr.ifr_addr.sa_family = AF_INET; - - ioctl(fd, SIOCGIFADDR, &ifr); - close(fd); - - sockaddr_in *saddr_in = (sockaddr_in *) &ifr.ifr_addr; - return inet_ntoa(saddr_in->sin_addr); -} - -std::vector<std::string> SIPVoIPLink::getAllIpInterface() -{ - pj_sockaddr addrList[16]; - unsigned addrCnt = PJ_ARRAY_SIZE(addrList); - - std::vector<std::string> ifaceList; - - if (pj_enum_ip_interface(pj_AF_INET(), &addrCnt, addrList) == PJ_SUCCESS) - for (unsigned i = 0; i < addrCnt; i++) { - char addr[PJ_INET_ADDRSTRLEN]; - pj_sockaddr_print(&addrList[i], addr, sizeof(addr), 0); - ifaceList.push_back(std::string(addr)); - } - - return ifaceList; -} diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index 12d63f7263c5e042df537bcc679641a1ab1ba191..01ea3c1ffd77087ba6d2cc094099d4f4bcdd4e04 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -13,6 +13,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * @@ -37,23 +38,18 @@ #include <map> -////////////////////////////// -/* PJSIP imports */ #include <pjsip.h> #include <pjlib.h> #include <pjsip_ua.h> #include <pjlib-util.h> +#include <pjnath.h> #include <pjnath/stun_config.h> -/////////////////////////////// #include "sipaccount.h" #include "voiplink.h" +#include "siptransport.h" +#include "eventthread.h" -namespace sfl { -class InstantMessaging; -} - -class EventThread; class SIPCall; class SIPAccount; @@ -66,7 +62,6 @@ class SIPAccount; class SIPVoIPLink : public VoIPLink { public: - ~SIPVoIPLink(); /** * Singleton method. Enable to retrieve the unique static instance @@ -75,19 +70,14 @@ class SIPVoIPLink : public VoIPLink { static SIPVoIPLink* instance(); /** - * Try to initiate the pjsip engine/thread and set config + * Destroy the singleton instance */ - virtual void init(); - - /** - * Shut the library and clean up - */ - virtual void terminate(); + static void destroy(); /** * Event listener. Each event send by the call manager is received and handled from here */ - virtual void getEvent(); + virtual bool getEvent(); /** * Build and send SIP registration request @@ -117,6 +107,20 @@ class SIPVoIPLink : public VoIPLink { */ virtual Call* newOutgoingCall(const std::string& id, const std::string& toUrl); + /** + * Start a new SIP call using the IP2IP profile + * @param The call id + * @param The target sip uri + */ + Call *SIPNewIpToIpCall(const std::string& id, const std::string& to); + + /** + * Place a call using the currently selected account + * @param The call id + * @param The target sip uri + */ + Call *newRegisteredAccountCall(const std::string& id, const std::string& toUrl); + /** * Answer the call * @param c The call @@ -179,13 +183,6 @@ class SIPVoIPLink : public VoIPLink { */ virtual void carryingDTMFdigits(const std::string& id, char code); - /** - * Start a new SIP call using the IP2IP profile - * @param The call id - * @param The target sip uri - */ - bool SIPNewIpToIpCall(const std::string& id, const std::string& to); - /** * Tell the user that the call was answered * @param @@ -224,75 +221,30 @@ class SIPVoIPLink : public VoIPLink { */ std::string getUseragentName(SIPAccount *) const; - /** - * List all the interfaces on the system and return - * a vector list containing their IPV4 address. - * @param void - * @return std::vector<std::string> A std::string vector - * of IPV4 address available on all of the interfaces on - * the system. - */ - static std::vector<std::string> getAllIpInterface(); - - /** - * List all the interfaces on the system and return - * a vector list containing their name (eth0, eth0:1 ...). - * @param void - * @return std::vector<std::string> A std::string vector - * of interface name available on all of the interfaces on - * the system. - */ - static std::vector<std::string> getAllIpInterfaceByName(); - - /** - * List all the interfaces on the system and return - * a vector list containing their name (eth0, eth0:1 ...). - * @param void - * @return std::vector<std::string> A std::string vector - * of interface name available on all of the interfaces on - * the system. - */ - static std::string getInterfaceAddrFromName(const std::string &ifaceName); - - /** - * Initialize the transport selector - * @param transport A transport associated with an account - * - * @return A pointer to the transport selector structure - */ - pjsip_tpselector *initTransportSelector(pjsip_transport *, pj_pool_t *) const; - - /** - * This function unset the transport for a given account. - */ - void shutdownSipTransport(SIPAccount *account); - /** * Send a SIP message to a call identified by its callid * - * @param The InstantMessaging module which contains formating, parsing and sending method * @param The Id of the call to send the message to * @param The actual message to be transmitted * @param The sender of this message (could be another participant of a conference) */ - void sendTextMessage(sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from); + void sendTextMessage(const std::string& callID, + const std::string& message, + const std::string& from); /** * Create the default UDP transport according ot Ip2Ip profile settings */ void createDefaultSipUdpTransport(); - /** - * Get the correct address to use (ie advertised) from - * a uri. The corresponding transport that should be used - * with that uri will be discovered. - * - * @param uri The uri from which we want to discover the address to use - * @param transport The transport to use to discover the address - */ - void findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &address, std::string &port) const; + SipTransport sipTransport; private: + + NON_COPYABLE(SIPVoIPLink); + + SIPVoIPLink(); + ~SIPVoIPLink(); /** * Start a SIP Call * @param call The current call @@ -302,57 +254,14 @@ class SIPVoIPLink : public VoIPLink { void dtmfSend(SIPCall *call, char code, const std::string &type); - NON_COPYABLE(SIPVoIPLink); - - SIPVoIPLink(); - - /** - * Resolve public address for this account - */ - pj_status_t stunServerResolve(SIPAccount *); - - /** - * Create the default TLS listener. - */ - void createTlsListener(SIPAccount*, pjsip_tpfactory **listener); - - /** - * General Sip transport creation method according to the - * transport type specified in account settings - * @param account The account for which a transport must be created. - */ - void createSipTransport(SIPAccount *account); - - /** - * Create SIP UDP transport from account's setting - * @param account The account for which a transport must be created. - */ - void createUdpTransport(SIPAccount *account); - - /** - * Create a TLS transport from the default TLS listener from - * @param account The account for which a transport must be created. - */ - void createTlsTransport(SIPAccount *, std::string remoteAddr); - - /** - * Create a UDP transport using stun server to resove public address - * @param account The account for which a transport must be created. - */ - void createStunTransport(SIPAccount *account); - - /** - * UDP Transports are stored in this map in order to retreive them in case - * several accounts would share the same port number. - */ - std::map<pj_uint16_t, pjsip_transport*> transportMap_; - /** * Threading object */ - EventThread *evThread_; + EventThread evThread_; friend class SIPTest; + static bool destroyed_; + static SIPVoIPLink *instance_; }; #endif // SIPVOIPLINK_H_ diff --git a/daemon/src/voiplink.cpp b/daemon/src/voiplink.cpp index 6a34ea5f4cf704ba933bfbd3f17ce70d6ca49cf2..0fb2432a6499f17244a44b59f0f3deae8552cfe0 100644 --- a/daemon/src/voiplink.cpp +++ b/daemon/src/voiplink.cpp @@ -32,9 +32,10 @@ */ #include "call.h" +#include "logger.h" #include "voiplink.h" -VoIPLink::VoIPLink() : callMap_(), callMapMutex_() {} +VoIPLink::VoIPLink() : callMap_(), callMapMutex_(), handlingEvents_(false) {} VoIPLink::~VoIPLink() { @@ -60,7 +61,7 @@ void VoIPLink::removeCall(const std::string& id) { ost::MutexLock m(callMapMutex_); - DEBUG("VoipLink: removing call %s from list", id.c_str()); + DEBUG("Removing call %s from list", id.c_str()); delete callMap_[id]; callMap_.erase(id); diff --git a/daemon/src/voiplink.h b/daemon/src/voiplink.h index 52257afd75300cd18bb07194652ce79382c77922..7889e471c50449e78d0ab7d4577de1c3f68445aa 100644 --- a/daemon/src/voiplink.h +++ b/daemon/src/voiplink.h @@ -36,21 +36,17 @@ #include <stdexcept> #include <map> -#include <cc++/thread.h> // for ost::Mutex +#include "cc_thread.h" // for ost::Mutex class Call; class Account; -namespace sfl { -class InstantMessaging; -}; - /** Define a map that associate a Call object to a call identifier */ typedef std::map<std::string, Call*> CallMap; class VoipLinkException : public std::runtime_error { public: - VoipLinkException(const std::string& str = "") : + VoipLinkException(const std::string &str = "") : std::runtime_error("UserAgent: VoipLinkException occured: " + str) {} }; @@ -67,13 +63,7 @@ class VoIPLink { * Virtual method * Event listener. Each event send by the call manager is received and handled from here */ - virtual void getEvent() = 0; - - /** - * Virtual method - * Try to initiate the communication layer and set config - */ - virtual void init() = 0; + virtual bool getEvent() = 0; /** * Virtual method @@ -93,7 +83,8 @@ class VoIPLink { * @param toUrl The address of the recipient of the call * @return Call* The current call */ - virtual Call* newOutgoingCall(const std::string& id, const std::string& toUrl) = 0; + virtual Call* newOutgoingCall(const std::string &id, + const std::string &toUrl) = 0; /** * Answer the call @@ -105,34 +96,34 @@ class VoIPLink { * Hang up a call * @param id The call identifier */ - virtual void hangup(const std::string& id) = 0; + virtual void hangup(const std::string &id) = 0; /** * Peer Hung up a call * @param id The call identifier */ - virtual void peerHungup(const std::string& id) = 0; + virtual void peerHungup(const std::string &id) = 0; /** * Put a call on hold * @param id The call identifier * @return bool True on success */ - virtual void onhold(const std::string& id) = 0; + virtual void onhold(const std::string &id) = 0; /** * Resume a call from hold state * @param id The call identifier * @return bool True on success */ - virtual void offhold(const std::string& id) = 0; + virtual void offhold(const std::string &id) = 0; /** * Transfer a call to specified URI * @param id The call identifier * @param to The recipient of the call */ - virtual void transfer(const std::string& id, const std::string& to) = 0; + virtual void transfer(const std::string &id, const std::string &to) = 0; /** * Attended transfer @@ -146,14 +137,14 @@ class VoIPLink { * Refuse incoming call * @param id The call identifier */ - virtual void refuse(const std::string& id) = 0; + virtual void refuse(const std::string &id) = 0; /** * Send DTMF * @param id The call identifier * @param code The char code */ - virtual void carryingDTMFdigits(const std::string& id, char code) = 0; + virtual void carryingDTMFdigits(const std::string &id, char code) = 0; /** * Return the codec protocol used for this call @@ -164,12 +155,13 @@ class VoIPLink { /** * Send a message to a call identified by its callid * - * @param The InstantMessaging module which contains formating, parsing and sending method * @param The Id of the call to send the message to * @param The actual message to be transmitted * @param The sender of this message (could be another participant of a conference) */ - virtual void sendTextMessage(sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from) = 0; + virtual void sendTextMessage(const std::string &callID, + const std::string &message, + const std::string &from) = 0; /** Add a call to the call map (protected by mutex) * @param call A call pointer with a unique pointer @@ -182,7 +174,7 @@ class VoIPLink { * @param id A Call ID * @return Call* Call pointer or 0 */ - Call* getCall(const std::string& id); + Call* getCall(const std::string &id); protected: /** Contains all the calls for this Link, protected by mutex */ @@ -191,10 +183,12 @@ class VoIPLink { /** Mutex to protect call map */ ost::Mutex callMapMutex_; + bool handlingEvents_; + /** Remove a call from the call map (protected by mutex) * @param id A Call ID */ - void removeCall(const std::string& id); + void removeCall(const std::string &id); }; #endif // __VOIP_LINK_H__ diff --git a/daemon/test/Makefile.am b/daemon/test/Makefile.am index 28c269d257e34af7e9c53d885d1deba3c7911399..156aa5bef412fcbaadd544c3ec3972a3723204ef 100644 --- a/daemon/test/Makefile.am +++ b/daemon/test/Makefile.am @@ -5,50 +5,42 @@ check_PROGRAMS = test TESTS = run_tests.sh -test_CXXFLAGS = -I . -test_LDADD = $(top_builddir)/src/libsflphone.la @ZRTPCPP_LIBS@ @LIBCRYPTO_LIBS@ @CPPUNIT_LIBS@ +test_CXXFLAGS = -DWORKSPACE="$(top_srcdir)/test/" +test_LDADD = $(top_builddir)/src/libsflphone.la @ZRTPCPP_LIBS@ @LIBCRYPTO_LIBS@ @CPPUNIT_LIBS@ @YAML_LIBS@ -EXTRA_DIST = $(test_SOURCES) sflphoned-sample.yml history-sample.tpl run_tests.sh -test_SOURCES = \ - constants.h \ - main.cpp \ - validator.cpp \ - validator.h \ - accounttest.h \ - accounttest.cpp \ - audiolayertest.h \ - audiolayertest.cpp \ - configurationtest.h \ - configurationtest.cpp \ - historytest.h \ - historytest.cpp \ - numbercleanertest.h \ - numbercleanertest.cpp \ - sdesnegotiatortest.h \ - sdesnegotiatortest.cpp \ - instantmessagingtest.h \ - instantmessagingtest.cpp \ - siptest.h \ - siptest.cpp \ - sdptest.h \ - sdptest.cpp \ - echocanceltest.h \ - echocanceltest.cpp \ - gaincontroltest.h \ - gaincontroltest.cpp - accounttest.h \ - audiolayertest.h \ - configurationtest.h \ - constants.h \ - delaydetectiontest.h \ - echocanceltest.h \ - gaincontroltest.h \ - historytest.h \ - instantmessagingtest.h \ - mainbuffertest.h \ - numbercleanertest.h \ - ringtonetest.h \ - sdesnegotiatortest.h \ - sdptest.h \ - siptest.h \ - validator.h +EXTRA_DIST = sflphoned-sample.yml history-sample.tpl run_tests.sh +test_SOURCES = constants.h \ + test_utils.h \ + main.cpp \ + validator.h \ + validator.cpp \ + accounttest.h \ + accounttest.cpp \ + audiolayertest.h \ + audiolayertest.cpp \ + configurationtest.h \ + configurationtest.cpp \ + historytest.h \ + historytest.cpp \ + numbercleanertest.h \ + numbercleanertest.cpp \ + sdesnegotiatortest.h \ + sdesnegotiatortest.cpp \ + instantmessagingtest.h \ + instantmessagingtest.cpp \ + siptest.h \ + siptest.cpp \ + sdptest.h \ + sdptest.cpp \ + echocanceltest.h \ + echocanceltest.cpp \ + gaincontroltest.h \ + gaincontroltest.cpp \ + mainbuffertest.h \ + mainbuffertest.cpp \ + resamplertest.h \ + resamplertest.cpp + +clean-local: + rm -rf cppunitresults.xml im:testfile1.txt im:testfile2.txt \ + sample_echocancel_500ms_8kHz_16bit.raw diff --git a/daemon/test/accounttest.cpp b/daemon/test/accounttest.cpp index 3df3153c230e7662d4d8fb61f853dab2eea4912d..57bd49dbf8c1e7c5481ac36ce4c86a87419abc84 100644 --- a/daemon/test/accounttest.cpp +++ b/daemon/test/accounttest.cpp @@ -36,9 +36,9 @@ #include "logger.h" #include "validator.h" -void AccountTest::TestAddRemove(void) +void AccountTest::TestAddRemove() { - DEBUG("-------------------- AccountTest::TestAddRemove --------------------\n"); + DEBUG("-------------------- %s --------------------\n", __PRETTY_FUNCTION__); std::map<std::string, std::string> details; details[CONFIG_ACCOUNT_TYPE] = "SIP"; diff --git a/daemon/test/accounttest.h b/daemon/test/accounttest.h index 486117fa3c384d462da3ab6cfdff18d6c79e2475..ce880cfcb70e41b195ad997723fb90367670847d 100644 --- a/daemon/test/accounttest.h +++ b/daemon/test/accounttest.h @@ -41,7 +41,7 @@ class AccountTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_END(); public: - void TestAddRemove(void); + void TestAddRemove(); }; CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AccountTest, "AccountTest"); CPPUNIT_TEST_SUITE_REGISTRATION(AccountTest); diff --git a/daemon/test/audiolayertest.cpp b/daemon/test/audiolayertest.cpp index 589271f04b33ef3d5d47ad93762c031b7719b174..3e80ef2f1fc0395c1bf14610ebe78ead56232b9c 100644 --- a/daemon/test/audiolayertest.cpp +++ b/daemon/test/audiolayertest.cpp @@ -28,23 +28,21 @@ * as that of the covered work. */ -#include <stdio.h> -#include <sstream> - #include "audiolayertest.h" -#include "audio/pulseaudio/audiostream.h" +#include "logger.h" +#include "manager.h" +#include "audio/alsa/alsalayer.h" +#include "audio/pulseaudio/pulselayer.h" +#include "test_utils.h" #include <unistd.h> -using std::cout; -using std::endl; - AudioLayerTest::AudioLayerTest() : manager_(0), pulselayer_(0), layer_(0) {} void AudioLayerTest::testAudioLayerConfig() { - DEBUG("-------------------- AudioLayerTest::testAudioLayerConfig --------------------\n"); + TITLE(); CPPUNIT_ASSERT(Manager::instance().audioPreference.getSmplrate() == 44100); @@ -68,12 +66,12 @@ void AudioLayerTest::testAudioLayerConfig() void AudioLayerTest::testAudioLayerSwitch() { - DEBUG("-------------------- AudioLayerTest::testAudioLayerSwitch --------------------\n"); + TITLE(); bool wasAlsa = dynamic_cast<AlsaLayer*>(Manager::instance().getAudioDriver()) != 0; for (int i = 0; i < 2; i++) { - DEBUG("iter - %i", i); + DEBUG("iter - %i", i); Manager::instance().switchAudioManager(); if (wasAlsa) @@ -82,17 +80,19 @@ void AudioLayerTest::testAudioLayerSwitch() CPPUNIT_ASSERT(dynamic_cast<AlsaLayer*>(Manager::instance().getAudioDriver())); wasAlsa = dynamic_cast<AlsaLayer*>(Manager::instance().getAudioDriver()) != 0; - usleep(100000); + const struct timespec req = {0, 100000000}; + nanosleep(&req, 0); } } void AudioLayerTest::testPulseConnect() { - DEBUG("-------------------- AudioLayerTest::testPulseConnect --------------------\n"); + TITLE(); if (dynamic_cast<AlsaLayer*>(Manager::instance().getAudioDriver())) { Manager::instance().switchAudioManager(); - usleep(100000); + const struct timespec req = {0, 100000000}; + nanosleep(&req, 0); } pulselayer_ = dynamic_cast<PulseLayer*>(Manager::instance().getAudioDriver()); diff --git a/daemon/test/audiolayertest.h b/daemon/test/audiolayertest.h index 994cbaa62f96f567d60f8b97bf7232f9ec0c1895..cdd7bfaeabc83f021ff45964b760e2d3e4281eda 100644 --- a/daemon/test/audiolayertest.h +++ b/daemon/test/audiolayertest.h @@ -33,8 +33,8 @@ * @brief Regroups unitary tests related to the plugin manager. */ -#ifndef _AUDIOLAYER_TEST_ -#define _AUDIOLAYER_TEST_ +#ifndef AUDIOLAYER_TEST_ +#define AUDIOLAYER_TEST_ // Cppunit import #include <cppunit/extensions/HelperMacros.h> @@ -42,18 +42,11 @@ #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include <cassert> - -// Application import -#include "manager.h" - -#include "config/config.h" - -#include "audio/audiolayer.h" -#include "audio/alsa/alsalayer.h" -#include "audio/pulseaudio/pulselayer.h" #include "noncopyable.h" +class ManagerImpl; +class PulseLayer; + class AudioLayerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(AudioLayerTest); @@ -79,4 +72,4 @@ class AudioLayerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AudioLayerTest, "AudioLayerTest"); CPPUNIT_TEST_SUITE_REGISTRATION(AudioLayerTest); -#endif +#endif // AUDIOLAYER_TEST_ diff --git a/daemon/test/configurationtest.cpp b/daemon/test/configurationtest.cpp index cb447c9d8beb52a3627be6254a2b3184e79acf2b..a3553bc55990819e7b68051d6c133dbef29ef9bf 100644 --- a/daemon/test/configurationtest.cpp +++ b/daemon/test/configurationtest.cpp @@ -28,24 +28,24 @@ * as that of the covered work. */ -#include <stdio.h> -#include <sstream> - #include "configurationtest.h" -#include "constants.h" +#include "manager.h" +#include "config/yamlemitter.h" +#include "config/yamlparser.h" +#include "account.h" +#include "logger.h" #include "audio/alsa/alsalayer.h" #include "audio/pulseaudio/pulselayer.h" - -using std::cout; -using std::endl; +#include "sip/sipaccount.h" +#include "test_utils.h" void ConfigurationTest::testDefaultValueAudio() { - DEBUG("-------------------- ConfigurationTest::testDefaultValueAudio() --------------------\n"); + TITLE(); - CPPUNIT_ASSERT(Manager::instance().audioPreference.getCardin() == 0); // ALSA_DFT_CARD); - CPPUNIT_ASSERT(Manager::instance().audioPreference.getCardout() == 0); // ALSA_DFT_CARD); - CPPUNIT_ASSERT(Manager::instance().audioPreference.getSmplrate() == 44100); // DFT_SAMPLE_RATE); + CPPUNIT_ASSERT(Manager::instance().audioPreference.getCardin() == ALSA_DFT_CARD_ID); + CPPUNIT_ASSERT(Manager::instance().audioPreference.getCardout() == ALSA_DFT_CARD_ID); + CPPUNIT_ASSERT(Manager::instance().audioPreference.getSmplrate() == 44100); CPPUNIT_ASSERT(Manager::instance().audioPreference.getPlugin() == PCM_DEFAULT); CPPUNIT_ASSERT(Manager::instance().audioPreference.getVolumespkr() == 100); CPPUNIT_ASSERT(Manager::instance().audioPreference.getVolumemic() == 100); @@ -53,25 +53,22 @@ void ConfigurationTest::testDefaultValueAudio() void ConfigurationTest::testDefaultValuePreferences() { - DEBUG("-------------------- ConfigurationTest::testDefaultValuePreferences --------------------\n"); - + TITLE(); CPPUNIT_ASSERT(Manager::instance().preferences.getZoneToneChoice() == Preferences::DFT_ZONE); } void ConfigurationTest::testDefaultValueSignalisation() { - DEBUG("-------------------- ConfigurationTest::testDefaultValueSignalisation --------------------\n"); - - CPPUNIT_ASSERT(Manager::instance().voipPreferences.getSymmetricRtp() == true); - CPPUNIT_ASSERT(Manager::instance().voipPreferences.getPlayDtmf() == true); - CPPUNIT_ASSERT(Manager::instance().voipPreferences.getPlayTones() == true); + TITLE(); + CPPUNIT_ASSERT(Manager::instance().voipPreferences.getSymmetricRtp()); + CPPUNIT_ASSERT(Manager::instance().voipPreferences.getPlayDtmf()); + CPPUNIT_ASSERT(Manager::instance().voipPreferences.getPlayTones()); CPPUNIT_ASSERT(Manager::instance().voipPreferences.getPulseLength() == 250); } void ConfigurationTest::testInitAudioDriver() { - DEBUG("-------------------- ConfigurationTest::testInitAudioDriver --------------------\n"); - + TITLE(); // Load the audio driver Manager::instance().initAudioDriver(); @@ -93,13 +90,11 @@ void ConfigurationTest::testInitAudioDriver() void ConfigurationTest::testYamlParser() { try { - Conf::YamlParser *parser = new Conf::YamlParser("ymlParser.yml"); - parser->serializeEvents(); - parser->composeEvents(); - parser->constructNativeData(); - - delete parser; - } catch (Conf::YamlParserException &e) { + Conf::YamlParser parser("ymlParser.yml"); + parser.serializeEvents(); + parser.composeEvents(); + parser.constructNativeData(); + } catch (const Conf::YamlParserException &e) { ERROR("ConfigTree: %s", e.what()); } } @@ -158,37 +153,37 @@ void ConfigurationTest::testYamlEmitter() ScalarNode verifyclient(true); ScalarNode verifyserver(true); - accountmap.setKeyValue(aliasKey, &alias); - accountmap.setKeyValue(typeKey, &type); - accountmap.setKeyValue(idKey, &id); - accountmap.setKeyValue(usernameKey, &username); - accountmap.setKeyValue(passwordKey, &password); - accountmap.setKeyValue(hostnameKey, &hostname); - accountmap.setKeyValue(accountEnableKey, &enable); - accountmap.setKeyValue(mailboxKey, &mailbox); - accountmap.setKeyValue(registrationExpireKey, &expire); - accountmap.setKeyValue(interfaceKey, &interface); - accountmap.setKeyValue(portKey, &port); - accountmap.setKeyValue(publishAddrKey, &publishAddr); - accountmap.setKeyValue(publishPortKey, &publishPort); - accountmap.setKeyValue(sameasLocalKey, &sameasLocal); - accountmap.setKeyValue(dtmfTypeKey, &dtmfType); - accountmap.setKeyValue(displayNameKey, &displayName); - - accountmap.setKeyValue(srtpKey, &srtpmap); - srtpmap.setKeyValue(srtpEnableKey, &srtpenabled); - srtpmap.setKeyValue(keyExchangeKey, &keyExchange); - srtpmap.setKeyValue(rtpFallbackKey, &rtpFallback); - - accountmap.setKeyValue(zrtpKey, &zrtpmap); - zrtpmap.setKeyValue(displaySasKey, &displaySas); - zrtpmap.setKeyValue(displaySasOnceKey, &displaySasOnce); - zrtpmap.setKeyValue(helloHashEnabledKey, &helloHashEnabled); - zrtpmap.setKeyValue(notSuppWarningKey, ¬SuppWarning); - - accountmap.setKeyValue(credKey, &credentialmap); + accountmap.setKeyValue(ALIAS_KEY, &alias); + accountmap.setKeyValue(TYPE_KEY, &type); + accountmap.setKeyValue(ID_KEY, &id); + accountmap.setKeyValue(USERNAME_KEY, &username); + accountmap.setKeyValue(PASSWORD_KEY, &password); + accountmap.setKeyValue(HOSTNAME_KEY, &hostname); + accountmap.setKeyValue(ACCOUNT_ENABLE_KEY, &enable); + accountmap.setKeyValue(MAILBOX_KEY, &mailbox); + accountmap.setKeyValue(Preferences::REGISTRATION_EXPIRE_KEY, &expire); + accountmap.setKeyValue(INTERFACE_KEY, &interface); + accountmap.setKeyValue(PORT_KEY, &port); + accountmap.setKeyValue(PUBLISH_ADDR_KEY, &publishAddr); + accountmap.setKeyValue(PUBLISH_PORT_KEY, &publishPort); + accountmap.setKeyValue(SAME_AS_LOCAL_KEY, &sameasLocal); + accountmap.setKeyValue(DTMF_TYPE_KEY, &dtmfType); + accountmap.setKeyValue(DISPLAY_NAME_KEY, &displayName); + + accountmap.setKeyValue(SRTP_KEY, &srtpmap); + srtpmap.setKeyValue(SRTP_ENABLE_KEY, &srtpenabled); + srtpmap.setKeyValue(KEY_EXCHANGE_KEY, &keyExchange); + srtpmap.setKeyValue(RTP_FALLBACK_KEY, &rtpFallback); + + accountmap.setKeyValue(ZRTP_KEY, &zrtpmap); + zrtpmap.setKeyValue(DISPLAY_SAS_KEY, &displaySas); + zrtpmap.setKeyValue(DISPLAY_SAS_ONCE_KEY, &displaySasOnce); + zrtpmap.setKeyValue(HELLO_HASH_ENABLED_KEY, &helloHashEnabled); + zrtpmap.setKeyValue(NOT_SUPP_WARNING_KEY, ¬SuppWarning); + + accountmap.setKeyValue(CRED_KEY, &credentialmap); SequenceNode credentialseq(NULL); - accountmap.setKeyValue(credKey, &credentialseq); + accountmap.setKeyValue(CRED_KEY, &credentialseq); MappingNode credmap1(NULL); MappingNode credmap2(NULL); @@ -198,38 +193,37 @@ void ConfigurationTest::testYamlEmitter() ScalarNode user2("john"); ScalarNode pass2("doe"); ScalarNode realm2("fbi"); - credmap1.setKeyValue(USERNAME, &user1); - credmap1.setKeyValue(PASSWORD, &pass1); - credmap1.setKeyValue(REALM, &realm1); - credmap2.setKeyValue(USERNAME, &user2); - credmap2.setKeyValue(PASSWORD, &pass2); - credmap2.setKeyValue(REALM, &realm2); + credmap1.setKeyValue(CONFIG_ACCOUNT_USERNAME, &user1); + credmap1.setKeyValue(CONFIG_ACCOUNT_PASSWORD, &pass1); + credmap1.setKeyValue(CONFIG_ACCOUNT_REALM, &realm1); + credmap2.setKeyValue(CONFIG_ACCOUNT_USERNAME, &user2); + credmap2.setKeyValue(CONFIG_ACCOUNT_PASSWORD, &pass2); + credmap2.setKeyValue(CONFIG_ACCOUNT_REALM, &realm2); credentialseq.addNode(&credmap1); credentialseq.addNode(&credmap2); - accountmap.setKeyValue(tlsKey, &tlsmap); - tlsmap.setKeyValue(tlsPortKey, &tlsport); - tlsmap.setKeyValue(certificateKey, &certificate); - tlsmap.setKeyValue(calistKey, &calist); - tlsmap.setKeyValue(ciphersKey, &ciphers); - tlsmap.setKeyValue(tlsEnableKey, &tlsenabled); - tlsmap.setKeyValue(methodKey, &tlsmethod); - tlsmap.setKeyValue(timeoutKey, &timeout); - tlsmap.setKeyValue(tlsPasswordKey, &tlspassword); - tlsmap.setKeyValue(privateKeyKey, &privatekey); - tlsmap.setKeyValue(requireCertifKey, &requirecertif); - tlsmap.setKeyValue(serverKey, &server); - tlsmap.setKeyValue(verifyClientKey, &verifyclient); - tlsmap.setKeyValue(verifyServerKey, &verifyserver); + accountmap.setKeyValue(TLS_KEY, &tlsmap); + tlsmap.setKeyValue(TLS_PORT_KEY, &tlsport); + tlsmap.setKeyValue(CERTIFICATE_KEY, &certificate); + tlsmap.setKeyValue(CALIST_KEY, &calist); + tlsmap.setKeyValue(CIPHERS_KEY, &ciphers); + tlsmap.setKeyValue(TLS_ENABLE_KEY, &tlsenabled); + tlsmap.setKeyValue(METHOD_KEY, &tlsmethod); + tlsmap.setKeyValue(TIMEOUT_KEY, &timeout); + tlsmap.setKeyValue(TLS_PASSWORD_KEY, &tlspassword); + tlsmap.setKeyValue(PRIVATE_KEY_KEY, &privatekey); + tlsmap.setKeyValue(REQUIRE_CERTIF_KEY, &requirecertif); + tlsmap.setKeyValue(SERVER_KEY, &server); + tlsmap.setKeyValue(VERIFY_CLIENT_KEY, &verifyclient); + tlsmap.setKeyValue(VERIFY_SERVER_KEY, &verifyserver); try { - YamlEmitter *emitter = new YamlEmitter("/tmp/ymlEmiter.txt"); + YamlEmitter emitter("/tmp/ymlEmiter.txt"); - emitter->serializeAccount(&accountmap); - emitter->serializeAccount(&accountmap); - emitter->serializeData(); + emitter.serializeAccount(&accountmap); + emitter.serializeAccount(&accountmap); + emitter.serializeData(); - delete emitter; } catch (const YamlEmitterException &e) { ERROR("ConfigTree: %s", e.what()); } diff --git a/daemon/test/configurationtest.h b/daemon/test/configurationtest.h index f8705d3dadec3c0004e77b48b5d7422fb8d063a2..d9f014db2a72e1dbaa1eae1a85b1df8ea61ed2dc 100644 --- a/daemon/test/configurationtest.h +++ b/daemon/test/configurationtest.h @@ -34,8 +34,8 @@ * Check if the default configuration has been successfully loaded */ -#ifndef _CONFIGURATION_TEST_ -#define _CONFIGURATION_TEST_ +#ifndef CONFIGURATION_TEST_ +#define CONFIGURATION_TEST_ // Cppunit import #include <cppunit/extensions/HelperMacros.h> @@ -43,29 +43,12 @@ #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include <assert.h> - -// Application import -#include "manager.h" -#include "audio/audiolayer.h" -#include "global.h" -#include "config/yamlparser.h" -#include "config/yamlemitter.h" -#include "config/yamlnode.h" -#include "sip/sipaccount.h" -#include "account.h" - class ConfigurationTest: public CppUnit::TestFixture { /* * Use cppunit library macros to add unit test the factory */ CPPUNIT_TEST_SUITE(ConfigurationTest); -// CPPUNIT_TEST( testDefaultValueAudio ); -// CPPUNIT_TEST( testDefaultValuePreferences ); -// CPPUNIT_TEST( testDefaultValueSignalisation ); -// CPPUNIT_TEST( testInitAudioDriver ); -// CPPUNIT_TEST( testYamlParser ); CPPUNIT_TEST(testYamlEmitter); CPPUNIT_TEST_SUITE_END(); @@ -103,4 +86,4 @@ class ConfigurationTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ConfigurationTest, "ConfigurationTest"); CPPUNIT_TEST_SUITE_REGISTRATION(ConfigurationTest); -#endif +#endif // CONFIGURATION_TEST_ diff --git a/daemon/test/constants.h b/daemon/test/constants.h index 684f00ebacce91ca15600f75aa1f50485a2607dd..74b8374dd6b6b242a5aa1b310f969ab049ef13e5 100644 --- a/daemon/test/constants.h +++ b/daemon/test/constants.h @@ -31,9 +31,15 @@ #ifndef CONSTANTS_H_ #define CONSTANTS_H_ -#define HISTORY_SAMPLE "history-sample.tpl" -#define HISTORY_SAMPLE_SIZE 3 -#define CONFIG_SAMPLE "sflphoned-sample.yml" +#define XSTRINGIFY(s) STRINGIFY(s) +#define STRINGIFY(s) #s +#define HISTORY_SAMPLE XSTRINGIFY(WORKSPACE) "history-sample.tpl" +#define HISTORY_SAMPLE_BAK HISTORY_SAMPLE ".bak" + +#define CONFIG_SAMPLE XSTRINGIFY(WORKSPACE) "sflphoned-sample.yml" +#define CONFIG_SAMPLE_BAK CONFIG_SAMPLE ".bak" + +#define HISTORY_SAMPLE_SIZE 3 #define HISTORY_LIMIT 30 #endif /* CONSTANTS_H_ */ diff --git a/daemon/test/delaydetectiontest.cpp b/daemon/test/delaydetectiontest.cpp index a140d208d52531599c62fd8b836d25072c92692d..6b744c79f1e97d1152ae55859f8f8a7ca006d359 100644 --- a/daemon/test/delaydetectiontest.cpp +++ b/daemon/test/delaydetectiontest.cpp @@ -30,14 +30,8 @@ #include "delaydetectiontest.h" - -#include <iostream> -#include <math.h> -#include <string.h> - -void DelayDetectionTest::setUp() {} - -void DelayDetectionTest::tearDown() {} +#include <cstring> +#include "array_size.h" void DelayDetectionTest::testCrossCorrelation() { @@ -54,7 +48,7 @@ void DelayDetectionTest::testCrossCorrelation() float tmp; - for (int i = 0; i < 10; i++) { + for (int i = 0; i < ARRAYSIZE(result); i++) { tmp = result[i] - expected[i]; if (tmp < 0.0) @@ -73,53 +67,46 @@ void DelayDetectionTest::testCrossCorrelationDelay() delaydetect_.crossCorrelate(ref, signal, result, 3, 10); - float expected[10] = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}; - +// float expected[10] = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}; } void DelayDetectionTest::testFirFilter() { - float decimationCoefs[] = {-0.09870257, 0.07473655, 0.05616626, 0.04448337, 0.03630817, 0.02944626, - 0.02244098, 0.01463477, 0.00610982, -0.00266367, -0.01120109, -0.01873722, - -0.02373243, -0.02602213, -0.02437806, -0.01869834, -0.00875287, 0.00500204, - 0.02183252, 0.04065763, 0.06015944, 0.0788299, 0.09518543, 0.10799179, - 0.1160644, 0.12889288, 0.1160644, 0.10799179, 0.09518543, 0.0788299, - 0.06015944, 0.04065763, 0.02183252, 0.00500204, -0.00875287, -0.01869834, - -0.02437806, -0.02602213, -0.02373243, -0.01873722, -0.01120109, -0.00266367, - 0.00610982, 0.01463477, 0.02244098, 0.02944626, 0.03630817, 0.04448337, - 0.05616626, 0.07473655, -0.09870257 - }; - std::vector<double> ird(decimationCoefs, decimationCoefs + sizeof(decimationCoefs) /sizeof(float)); - - float bandpassCoefs[] = {0.06278034, -0.0758545, -0.02274943, -0.0084497, 0.0702427, 0.05986113, - 0.06436469, -0.02412049, -0.03433526, -0.07568665, -0.03214543, -0.07236507, - -0.06979052, -0.12446371, -0.05530828, 0.00947243, 0.15294699, 0.17735563, - 0.15294699, 0.00947243, -0.05530828, -0.12446371, -0.06979052, -0.07236507, - -0.03214543, -0.07568665, -0.03433526, -0.02412049, 0.06436469, 0.05986113, - 0.0702427, -0.0084497, -0.02274943, -0.0758545, 0.06278034 - }; - std::vector<double> irb(bandpassCoefs, bandpassCoefs + sizeof(bandpassCoefs) /sizeof(float)); + const float decimationCoefs[] = {-0.09870257, 0.07473655, 0.05616626, 0.04448337, 0.03630817, 0.02944626, + 0.02244098, 0.01463477, 0.00610982, -0.00266367, -0.01120109, -0.01873722, + -0.02373243, -0.02602213, -0.02437806, -0.01869834, -0.00875287, 0.00500204, + 0.02183252, 0.04065763, 0.06015944, 0.0788299, 0.09518543, 0.10799179, + 0.1160644, 0.12889288, 0.1160644, 0.10799179, 0.09518543, 0.0788299, + 0.06015944, 0.04065763, 0.02183252, 0.00500204, -0.00875287, -0.01869834, + -0.02437806, -0.02602213, -0.02373243, -0.01873722, -0.01120109, -0.00266367, + 0.00610982, 0.01463477, 0.02244098, 0.02944626, 0.03630817, 0.04448337, + 0.05616626, 0.07473655, -0.09870257}; + const std::vector<double> ird(decimationCoefs, decimationCoefs + ARRAYSIZE(decimationCoefs)); + + const float bandpassCoefs[] = {0.06278034, -0.0758545, -0.02274943, -0.0084497, 0.0702427, 0.05986113, + 0.06436469, -0.02412049, -0.03433526, -0.07568665, -0.03214543, -0.07236507, + -0.06979052, -0.12446371, -0.05530828, 0.00947243, 0.15294699, 0.17735563, + 0.15294699, 0.00947243, -0.05530828, -0.12446371, -0.06979052, -0.07236507, + -0.03214543, -0.07568665, -0.03433526, -0.02412049, 0.06436469, 0.05986113, + 0.0702427, -0.0084497, -0.02274943, -0.0758545, 0.06278034}; + const std::vector<double> irb(bandpassCoefs, bandpassCoefs + ARRAYSIZE(bandpassCoefs)); float impulse[100]; - memset(impulse, 0, sizeof(float) *100); + memset(impulse, 0, sizeof(impulse)) impulse[0] = 1.0; FirFilter decimationFilter_(ird); FirFilter bandpassFilter_(irb); float impulseresponse[100]; - memset(impulseresponse, 0, sizeof(float) *100); + memset(impulseresponse, 0, sizeof impulseresponse); // compute impulse response - for (int i = 0; i < 100; i++) { + for (int i = 0; i < ARRAYSIZE(impulse); i++) impulseresponse[i] = decimationFilter_.getOutputSample(impulse[i]); - } - - float tmp; - int size = sizeof(decimationCoefs) /sizeof(float); - for (int i = 0; i < size; i++) { - tmp = decimationCoefs[i] - impulseresponse[i]; + for (int i = 0; i < ARRAYSIZE(decimationCoefs); ++i) { + float tmp = decimationCoefs[i] - impulseresponse[i]; if (tmp < 0.0) CPPUNIT_ASSERT(tmp > -0.000001); @@ -128,13 +115,10 @@ void DelayDetectionTest::testFirFilter() } - for (int i = 0; i < 100; i++) { + for (size_t i = 0; i < ARRAYSIZE(impulseresponse); ++i) impulseresponse[i] = bandpassFilter_.getOutputSample(impulse[i]); - } - size = sizeof(bandpassCoefs) /sizeof(float); - - for (int i = 0; i < size; i++) { + for (size_t i = 0; i < ARRAYSIZE(bandpassCoefs); ++i) { tmp = bandpassCoefs[i] - impulseresponse[i]; if (tmp < 0.0) @@ -142,51 +126,48 @@ void DelayDetectionTest::testFirFilter() else CPPUNIT_ASSERT(tmp < 0.000001); } - } void DelayDetectionTest::testIntToFloatConversion() { - - SFLDataFormat data[32768*2]; - float converted[32768*2]; + SFLDataFormat data[32768 * 2]; + float converted[ARRAYSIZE(data)]; for (int i = -32768; i < 32768; i++) - data[i+32768] = i; + data[i + 32768] = i; - delaydetect_.convertInt16ToFloat32(data, converted, 32768*2); + delaydetect_.convertInt16ToFloat32(data, converted, ARRAYSIZE(data)); for (int i = -32768; i < 0; i++) { - CPPUNIT_ASSERT(converted[i+32768] >= -1.0); - CPPUNIT_ASSERT(converted[i+32768] <= 0.0); + CPPUNIT_ASSERT(converted[i + 32768] >= -1.0); + CPPUNIT_ASSERT(converted[i + 32768] <= 0.0); } for (int i = 0; i < 32768; i++) { - CPPUNIT_ASSERT(converted[i+32768] >= 0.0); - CPPUNIT_ASSERT(converted[i+32768] <= 1.0); + CPPUNIT_ASSERT(converted[i + 32768] >= 0.0); + CPPUNIT_ASSERT(converted[i + 32768] <= 1.0); } } void DelayDetectionTest::testDownSamplingData() { - - SFLDataFormat data[32768*2]; - float converted[32768*2]; - float resampled[32768*2]; + SFLDataFormat data[32768 * 2]; + float converted[ARRAYSIZE(data)]; + float resampled[ARRAYSIZE(data)]; for (int i = -32768; i < 32768; i++) - data[i+32768] = i; + data[i + 32768] = i; - delaydetect_.convertInt16ToFloat32(data, converted, 32768*2); + delaydetect_.convertInt16ToFloat32(data, converted, 32768 * 2); - delaydetect_.downsampleData(converted, resampled, 32768*2, 8); + delaydetect_.downsampleData(converted, resampled, 32768 * 2, 8); - for (int i = 0; i < 32768/8; i++) { + for (size_t i = 0; i < 32768 / 8; ++i) { CPPUNIT_ASSERT(resampled[i] >= -1.0); CPPUNIT_ASSERT(resampled[i] <= 0.0); } - for (int i = 32768/8+1; i < 32768/4; i++) { + for (size_t i = 32768 / 8 + 1; i < 32768 / 4; i++) { CPPUNIT_ASSERT(resampled[i] >= 0.0); CPPUNIT_ASSERT(resampled[i] <= 1.0); } @@ -197,25 +178,16 @@ void DelayDetectionTest::testDownSamplingData() void DelayDetectionTest::testDelayDetection() { - - int delay = 100; - SFLDataFormat spkr[WINDOW_SIZE]; - memset(spkr, 0, sizeof(SFLDataFormat) *WINDOW_SIZE); - spkr[0] = 32000; - spkr[1] = 32000; - spkr[2] = 32000; - spkr[3] = 32000; - spkr[4] = 32000; + memset(spkr, 0, sizeof spkr); + for (size_t i = 0; i < 5; ++i) + spkr[i] = 32000; SFLDataFormat mic[DELAY_BUFF_SIZE]; - memset(mic, 0, sizeof(SFLDataFormat) *DELAY_BUFF_SIZE); - mic[delay] = 32000; - mic[delay+1] = 32000; - mic[delay+2] = 32000; - mic[delay+3] = 32000; - mic[delay+4] = 32000; - - delaydetect_.putData(spkr, WINDOW_SIZE); - delaydetect_.process(mic, DELAY_BUFF_SIZE); + memset(mic, 0, sizeof mic); + for (size_t delay = 100; delay < 105; ++delay) + mic[delay] = 32000; + + delaydetect_.putData(spkr, ARRAYSIZE(spkr)); + delaydetect_.process(mic, ARRAYSIZE(mic)); } diff --git a/daemon/test/delaydetectiontest.h b/daemon/test/delaydetectiontest.h index 11d4eef7d5a3afc917ebdbc7217a969fb7e0b2ba..3075fb6186b4dfd23edeb01d547b3eaf9dd3425b 100644 --- a/daemon/test/delaydetectiontest.h +++ b/daemon/test/delaydetectiontest.h @@ -35,33 +35,10 @@ #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include <assert.h> - -#include <stdio.h> -#include <sstream> -#include <ccrtp/rtp.h> - - -// pjsip import -#include <pjsip.h> -#include <pjlib.h> -#include <pjsip_ua.h> -#include <pjlib-util.h> -#include <pjnath/stun_config.h> - -// Application import -#include "manager.h" -#include "audio/mainbuffer.h" -#include "audio/ringbuffer.h" -#include "call.h" -// #include "config/config.h" -// #include "user_cfg.h" - - #include "audio/delaydetection.h" -#ifndef _DELAYDETECTION_TEST_ -#define _DELAYDETECTION_TEST_ +#ifndef DELAYDETECTION_TEST_ +#define DELAYDETECTION_TEST_ /* * @file delaydetection.cpp @@ -83,10 +60,6 @@ class DelayDetectionTest : public CppUnit::TestCase { DelayDetectionTest() : CppUnit::TestCase("Delay Detection Tests") {} - void setUp(); - - void tearDown(); - void testCrossCorrelation(); void testCrossCorrelationDelay(); @@ -109,4 +82,4 @@ class DelayDetectionTest : public CppUnit::TestCase { CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DelayDetectionTest, "DelayDetectionTest"); CPPUNIT_TEST_SUITE_REGISTRATION(DelayDetectionTest); -#endif +#endif // DELAYDETECTION_TEST_ diff --git a/daemon/test/echocanceltest.cpp b/daemon/test/echocanceltest.cpp index 53b03faed8b26b8237e923cb2d6452079c095d83..c872003641eb081dd9d4cb8972f2427eaa511b43 100644 --- a/daemon/test/echocanceltest.cpp +++ b/daemon/test/echocanceltest.cpp @@ -31,17 +31,14 @@ #include <iostream> #include "echocanceltest.h" -#include "config/config.h" - -using namespace std; +#include "config/sfl_config.h" EchoCancelTest::EchoCancelTest() : echoCanceller_() {} void EchoCancelTest::testEchoCancelProcessing() { - const int nbSamples = 160; - int inputFileLength = 0; - int remainingLength = 0; + using std::ifstream; + using std::ofstream; SFLDataFormat micData[1000]; SFLDataFormat spkrData[1000]; @@ -54,13 +51,12 @@ void EchoCancelTest::testEchoCancelProcessing() // echo cancelled output ofstream echoCancelFile("sample_echocancel_500ms_8kHz_16bit.raw", ofstream::out); - micFile.seekg(0, ios::end); - inputFileLength = micFile.tellg() / sizeof(SFLDataFormat); - micFile.seekg(0, ios::beg); - - remainingLength = inputFileLength; + micFile.seekg(0, std::ios::end); + size_t inputFileLength = micFile.tellg() / sizeof(SFLDataFormat); + micFile.seekg(0, std::ios::beg); - while (remainingLength >= nbSamples) { + const int nbSamples = 160; + for (int remainingLength = inputFileLength; remainingLength >= nbSamples; remainingLength -= nbSamples) { micFile.read(reinterpret_cast<char *>(micData), nbSamples * sizeof(SFLDataFormat)); spkrFile.read(reinterpret_cast<char *>(spkrData), nbSamples * sizeof(SFLDataFormat)); @@ -68,8 +64,6 @@ void EchoCancelTest::testEchoCancelProcessing() echoCanceller_.process(micData, echoCancelData, nbSamples); echoCancelFile.write(reinterpret_cast<char *>(echoCancelData), nbSamples * sizeof(SFLDataFormat)); - - remainingLength -= nbSamples; } CPPUNIT_ASSERT(true); diff --git a/daemon/test/echocanceltest.h b/daemon/test/echocanceltest.h index 6bd8f3a4c8358e2a8e82ddd11ea3e1d16e7cc370..7c378fc9f054dbb2a7ee574454890fc64687856d 100644 --- a/daemon/test/echocanceltest.h +++ b/daemon/test/echocanceltest.h @@ -42,8 +42,6 @@ #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include <cassert> - #include "audio/speexechocancel.h" class EchoCancelTest: public CppUnit::TestFixture { diff --git a/daemon/test/gaincontroltest.cpp b/daemon/test/gaincontroltest.cpp index 916a110d71e0126a3d6d3ac18d96d8a20cc31ec6..ed5492099b141bf04b61b8be2fb8b6d966f8f3b0 100644 --- a/daemon/test/gaincontroltest.cpp +++ b/daemon/test/gaincontroltest.cpp @@ -28,12 +28,9 @@ * as that of the covered work. */ -#include <iostream> - #include "gaincontroltest.h" -#include "config/config.h" - -using namespace std; +#include "audio/gaincontrol.h" +#include "config/sfl_config.h" void GainControlTest::testGainProcessing() { diff --git a/daemon/test/gaincontroltest.h b/daemon/test/gaincontroltest.h index 14f55d09b36a209961efd5893eba6e16c021941d..1f1bef03607bf39cce561d98f25eaabcb79b4c91 100644 --- a/daemon/test/gaincontroltest.h +++ b/daemon/test/gaincontroltest.h @@ -33,8 +33,8 @@ * @brief Regroups unitary tests related to the plugin manager. */ -#ifndef _GAINCONTROL_TEST_ -#define _GAINCONTROL_TEST_ +#ifndef GAINCONTROL_TEST_ +#define GAINCONTROL_TEST_ // Cppunit import #include <cppunit/extensions/HelperMacros.h> @@ -42,9 +42,7 @@ #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include <assert.h> - -#include "audio/gaincontrol.h" +#include "sfl_types.h" class GainControlTest: public CppUnit::TestFixture { @@ -55,12 +53,8 @@ class GainControlTest: public CppUnit::TestFixture { public: void testGainProcessing(); - - private: - - }; CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(GainControlTest, "GainControlTest"); CPPUNIT_TEST_SUITE_REGISTRATION(GainControlTest); -#endif +#endif // GAINCONTROL_TEST_ diff --git a/daemon/test/historytest.cpp b/daemon/test/historytest.cpp index 1c6ec3596cf47fef70163e357ed7123df42e6bf4..fe6aa20baed4d2764e77dc9f0427973bf6328cee 100644 --- a/daemon/test/historytest.cpp +++ b/daemon/test/historytest.cpp @@ -28,28 +28,23 @@ * as that of the covered work. */ -#include <cstdio> -#include <sstream> #include <cstdlib> #include "historytest.h" +#include "history/history.h" #include "logger.h" #include "constants.h" -#include "validator.h" - -using std::cout; -using std::endl; namespace { void restore() { - if (system("mv " HISTORY_SAMPLE ".bak " HISTORY_SAMPLE) < 0) - ERROR("Restoration of %s failed" HISTORY_SAMPLE); + if (system("mv " HISTORY_SAMPLE_BAK " " HISTORY_SAMPLE) < 0) + ERROR("Restoration of %s failed", HISTORY_SAMPLE); } void backup() { - if (system("cp " HISTORY_SAMPLE " " HISTORY_SAMPLE ".bak") < 0) + if (system("cp " HISTORY_SAMPLE " " HISTORY_SAMPLE_BAK) < 0) ERROR("Backup of %s failed", HISTORY_SAMPLE); } } diff --git a/daemon/test/historytest.h b/daemon/test/historytest.h index 19f2b372e8b5b45579394a80e27f2b197b601901..5f92cf38e2c82fd106c94e99fb13f9d13c0ce718 100644 --- a/daemon/test/historytest.h +++ b/daemon/test/historytest.h @@ -38,8 +38,8 @@ // Application import #include "noncopyable.h" -#include "history/history.h" +class History; /* * @file historyTest.h * @brief Regroups unitary tests related to the phone number cleanup function. diff --git a/daemon/test/instantmessagingtest.cpp b/daemon/test/instantmessagingtest.cpp index 89f0041a3f465f168c1d798a37c14d1fa448bc81..82571a2f3c7ab23fbcf6dbde186634391ec6200a 100644 --- a/daemon/test/instantmessagingtest.cpp +++ b/daemon/test/instantmessagingtest.cpp @@ -28,44 +28,37 @@ * as that of the covered work. */ -#include <stdio.h> #include <iostream> #include <fstream> +#include <expat.h> +#include "test_utils.h" #include "instantmessagingtest.h" - -#include "expat.h" -#include <stdio.h> +#include "im/instant_messaging.h" +#include "logger.h" #define MAXIMUM_SIZE 10 #define DELIMITER_CHAR "\n\n" -using std::cout; -using std::endl; - - -void InstantMessagingTest::setUp() -{ - im_ = new sfl::InstantMessaging(); -} +using namespace sfl::InstantMessaging; void InstantMessagingTest::testSaveSingleMessage() { - DEBUG("-------------------- InstantMessagingTest::testSaveSingleMessage --------------------\n"); - - std::string input, tmp; + TITLE(); std::string callID = "testfile1.txt"; std::string filename = "im:"; // Open a file stream and try to write in it - CPPUNIT_ASSERT(im_->saveMessage("Bonjour, c'est un test d'archivage de message", "Manu", callID, std::ios::out) == true); + CPPUNIT_ASSERT(saveMessage("Bonjour, c'est un test d'archivage de message", "Manu", callID, std::ios::out)); filename.append(callID); // Read it to check it has been successfully written std::ifstream testfile(filename.c_str(), std::ios::in); - CPPUNIT_ASSERT(testfile.is_open() == true); + CPPUNIT_ASSERT(testfile.is_open()); + std::string input; while (!testfile.eof()) { + std::string tmp; std::getline(testfile, tmp); input.append(tmp); } @@ -76,22 +69,23 @@ void InstantMessagingTest::testSaveSingleMessage() void InstantMessagingTest::testSaveMultipleMessage() { - DEBUG("-------------------- InstantMessagingTest::testSaveMultipleMessage --------------------\n"); + TITLE(); - std::string input, tmp; std::string callID = "testfile2.txt"; std::string filename = "im:"; // Open a file stream and try to write in it - CPPUNIT_ASSERT(im_->saveMessage("Bonjour, c'est un test d'archivage de message", "Manu", callID, std::ios::out) == true); - CPPUNIT_ASSERT(im_->saveMessage("Cool", "Alex", callID, std::ios::out || std::ios::app) == true); + CPPUNIT_ASSERT(saveMessage("Bonjour, c'est un test d'archivage de message", "Manu", callID, std::ios::out)); + CPPUNIT_ASSERT(saveMessage("Cool", "Alex", callID, std::ios::out || std::ios::app)); filename.append(callID); // Read it to check it has been successfully written std::ifstream testfile(filename.c_str(), std::ios::in); - CPPUNIT_ASSERT(testfile.is_open() == true); + CPPUNIT_ASSERT(testfile.is_open()); + std::string input; while (!testfile.eof()) { + std::string tmp; std::getline(testfile, tmp); input.append(tmp); } @@ -113,14 +107,12 @@ static void XMLCALL startElementCallback(void *userData, const char *name, const std::cout << "startElement " << name << std::endl; - int *nbEntry = (int *)userData; + int *nbEntry = (int *) userData; char attribute[50]; char value[50]; - const char **att; - - for (att = atts; *att; att += 2) { + for (const char **att = atts; *att; att += 2) { const char **val = att+1; @@ -140,17 +132,14 @@ static void XMLCALL startElementCallback(void *userData, const char *name, const } *nbEntry += 1; - } -static void XMLCALL endElementCallback(void * /*userData*/, const char * /*name*/) -{ - // std::cout << "endElement " << name << std::endl; -} +static void XMLCALL +endElementCallback(void * /*userData*/, const char * /*name*/) +{} void InstantMessagingTest::testGenerateXmlUriList() { - std::cout << std::endl; // Create a test list with two entries @@ -165,7 +154,7 @@ void InstantMessagingTest::testGenerateXmlUriList() list.push_front(entry1); list.push_front(entry2); - std::string buffer = im_->generateXmlUriList(list); + std::string buffer = generateXmlUriList(list); CPPUNIT_ASSERT(buffer.size() != 0); std::cout << buffer << std::endl; @@ -177,16 +166,12 @@ void InstantMessagingTest::testGenerateXmlUriList() XML_SetElementHandler(parser, startElementCallback, endElementCallback); if (XML_Parse(parser, buffer.c_str(), buffer.size(), 1) == XML_STATUS_ERROR) { - std::cout << "Error: " << XML_ErrorString(XML_GetErrorCode(parser)) - << " at line " << XML_GetCurrentLineNumber(parser) << std::endl; + ERROR("%s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); CPPUNIT_ASSERT(false); } XML_ParserFree(parser); - CPPUNIT_ASSERT(nbEntry == 4); - - CPPUNIT_ASSERT(true); } void InstantMessagingTest::testXmlUriListParsing() @@ -200,27 +185,20 @@ void InstantMessagingTest::testXmlUriListParsing() xmlbuffer.append("</resource-lists>"); - sfl::InstantMessaging::UriList list = im_->parseXmlUriList(xmlbuffer); + sfl::InstantMessaging::UriList list = parseXmlUriList(xmlbuffer); CPPUNIT_ASSERT(list.size() == 2); // An iterator over xml attribute sfl::InstantMessaging::UriEntry::iterator iterAttr; // An iterator over list entries - sfl::InstantMessaging::UriList::iterator iterEntry = list.begin(); - - - while (iterEntry != list.end()) { + for (sfl::InstantMessaging::UriList::iterator iterEntry = list.begin(); + iterEntry != list.end(); ++iterEntry) { sfl::InstantMessaging::UriEntry entry = static_cast<sfl::InstantMessaging::UriEntry>(*iterEntry); iterAttr = entry.find(sfl::IM_XML_URI); - if ((iterAttr->second == std::string("sip:alex@example.com")) || - (iterAttr->second == std::string("sip:manu@example.com"))) - CPPUNIT_ASSERT(true); - else - CPPUNIT_ASSERT(false); - - iterEntry++; + CPPUNIT_ASSERT((iterAttr->second == std::string("sip:alex@example.com")) or + (iterAttr->second == std::string("sip:manu@example.com"))); } } @@ -241,14 +219,12 @@ void InstantMessagingTest::testGetTextArea() formatedText.append("</resource-lists>"); formatedText.append("--boundary--"); - std::string message = im_->findTextMessage(formatedText); - - std::cout << "message " << message << std::endl; + std::string message(findTextMessage(formatedText)); + DEBUG("Message %s", message.c_str()); CPPUNIT_ASSERT(message == "Here is the text area"); } - void InstantMessagingTest::testGetUriListArea() { std::string formatedText = "--boundary Content-Type: text/plain"; @@ -265,13 +241,13 @@ void InstantMessagingTest::testGetUriListArea() formatedText.append("</resource-lists>"); formatedText.append("--boundary--"); - std::string urilist = im_->findTextUriList(formatedText); + std::string urilist = findTextUriList(formatedText); CPPUNIT_ASSERT(urilist.compare("<?xml version=\"1.0\" encoding=\"UTF-8\"?><resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\"><list><entry uri=\"sip:alex@example.com\" cp:copyControl=\"to\" /><entry uri=\"sip:manu@example.com\" cp:copyControl=\"to\" /></list></resource-lists>") == 0); std::cout << "urilist: " << urilist << std::endl; - sfl::InstantMessaging::UriList list = im_->parseXmlUriList(urilist); + sfl::InstantMessaging::UriList list = parseXmlUriList(urilist); CPPUNIT_ASSERT(list.size() == 2); // order may be important, for example to identify message sender @@ -281,7 +257,7 @@ void InstantMessagingTest::testGetUriListArea() sfl::InstantMessaging::UriEntry::iterator iterAttr = entry.find(sfl::IM_XML_URI); if (iterAttr == entry.end()) { - std::cout << "Error, did not found attribute" << std::endl; + ERROR("Did not find attribute"); CPPUNIT_ASSERT(false); } @@ -289,7 +265,6 @@ void InstantMessagingTest::testGetUriListArea() CPPUNIT_ASSERT(from == "sip:alex@example.com"); } - void InstantMessagingTest::testIllFormatedMessage() { bool exceptionCaught = false; @@ -310,21 +285,10 @@ void InstantMessagingTest::testIllFormatedMessage() formatedText.append("--boundary--"); try { - std::string message = im_->findTextMessage(formatedText); - } catch (sfl::InstantMessageException &e) { + std::string message = findTextMessage(formatedText); + } catch (const sfl::InstantMessageException &e) { exceptionCaught = true; } - if (exceptionCaught) - CPPUNIT_ASSERT(true); - else - CPPUNIT_ASSERT(false); - -} - - -void InstantMessagingTest::tearDown() -{ - delete im_; - im_ = 0; + CPPUNIT_ASSERT(exceptionCaught); } diff --git a/daemon/test/instantmessagingtest.h b/daemon/test/instantmessagingtest.h index 867e19eedfdcfa91424c5870b5d203e9ad04113e..0977397e6ad237928ce9e6b4953b976e24e328fa 100644 --- a/daemon/test/instantmessagingtest.h +++ b/daemon/test/instantmessagingtest.h @@ -34,25 +34,15 @@ #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include <cassert> - -// Application import -#include "im/instant_messaging.h" -#include "noncopyable.h" - /* * @file instantmessagingtest.h - * @brief Regroups unitary tests related to the instant messagin module + * @brief Unit tests related to the instant messaging module */ -#ifndef _INSTANTMANAGER_TEST_ -#define _INSTANTMANAGER_TEST_ +#ifndef INSTANTMANAGER_TEST_ +#define INSTANTMANAGER_TEST_ class InstantMessagingTest : public CppUnit::TestCase { - - /** - * Use cppunit library macros to add unit test the factory - */ CPPUNIT_TEST_SUITE(InstantMessagingTest); CPPUNIT_TEST(testSaveSingleMessage); CPPUNIT_TEST(testSaveMultipleMessage); @@ -64,37 +54,15 @@ class InstantMessagingTest : public CppUnit::TestCase { CPPUNIT_TEST_SUITE_END(); public: - InstantMessagingTest() : CppUnit::TestCase("Instant messaging module Tests"), im_(0) {} - - /* - * Code factoring - Common resources can be initialized here. - * This method is called by unitcpp before each test - */ - void setUp(); - - /* - * Code factoring - Common resources can be released here. - * This method is called by unitcpp after each test - */ - void tearDown(); + InstantMessagingTest() : CppUnit::TestCase("Instant messaging module Tests") {} void testSaveSingleMessage(); - void testSaveMultipleMessage(); - void testGenerateXmlUriList(); - void testXmlUriListParsing(); - void testGetTextArea(); - void testGetUriListArea(); - void testIllFormatedMessage(); - - private: - NON_COPYABLE(InstantMessagingTest); - sfl::InstantMessaging *im_; }; /* Register our test module */ diff --git a/daemon/test/main.cpp b/daemon/test/main.cpp index 59026375fdea675bebcbc87fe528193acc78cee1..624c6531e33ab4299ea1b1c1c553cce1a498700f 100644 --- a/daemon/test/main.cpp +++ b/daemon/test/main.cpp @@ -31,6 +31,7 @@ #include "logger.h" #include "manager.h" #include "constants.h" +#include "fileutils.h" #include <cstdlib> @@ -42,12 +43,12 @@ namespace { void restore() { - if (system("mv " CONFIG_SAMPLE ".bak " CONFIG_SAMPLE) < 0) + if (system("mv " CONFIG_SAMPLE_BAK " " CONFIG_SAMPLE) < 0) ERROR("Restoration of %s failed", CONFIG_SAMPLE); } void backup() { - if (system("cp " CONFIG_SAMPLE " " CONFIG_SAMPLE ".bak") < 0) + if (system("cp " CONFIG_SAMPLE " " CONFIG_SAMPLE_BAK) < 0) ERROR("Backup of %s failed", CONFIG_SAMPLE); } } @@ -57,6 +58,8 @@ int main(int argc, char* argv[]) printf("\nSFLphone Daemon Test Suite, by Savoir-Faire Linux 2004-2010\n\n"); Logger::setConsoleLog(true); Logger::setDebugMode(true); + if (!fileutils::create_pidfile()) + return 1; int argvIndex = 1; bool xmlOutput = false; diff --git a/daemon/test/mainbuffertest.cpp b/daemon/test/mainbuffertest.cpp index 94085b0c9ca68a83392e233d28fcae534006798a..5a3f40790509c837efac373b371984805752e245 100644 --- a/daemon/test/mainbuffertest.cpp +++ b/daemon/test/mainbuffertest.cpp @@ -28,44 +28,16 @@ * as that of the covered work. */ -#include <stdio.h> -#include <sstream> -#include <ccrtp/rtp.h> -#include <assert.h> #include <string> -#include <cstring> -#include <math.h> -#include <dlfcn.h> -#include <iostream> -#include <sstream> - - #include "mainbuffertest.h" - -#include <unistd.h> - - -using std::cout; -using std::endl; - - -void MainBufferTest::setUp() -{ - - -} - - -void MainBufferTest::tearDown() -{ - -} - +#include "audio/mainbuffer.h" +#include "audio/ringbuffer.h" +#include "logger.h" +#include "test_utils.h" void MainBufferTest::testRingBufferCreation() { - DEBUG("-------------------- MainBufferTest::testRingBufferCreation --------------------\n"); - + TITLE(); std::string test_id = "1234"; std::string null_id = "null id"; @@ -73,46 +45,45 @@ void MainBufferTest::testRingBufferCreation() RingBufferMap::iterator iter; // test mainbuffer ringbuffer map size - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 0); - test_ring_buffer = mainbuffer_.createRingBuffer(test_id); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 1); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.empty()); + test_ring_buffer = mainbuffer_->createRingBuffer(test_id); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 1); - // test mainbuffer_.getRingBuffer method + // test mainbuffer_->getRingBuffer method CPPUNIT_ASSERT(test_ring_buffer != NULL); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(null_id) == NULL); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 1); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(test_id) == test_ring_buffer); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(null_id) == NULL); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 1); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(test_id) == test_ring_buffer); // test mainbuffer_ ringBufferMap_ - iter = mainbuffer_.ringBufferMap_.find(null_id); - CPPUNIT_ASSERT(iter == mainbuffer_.ringBufferMap_.end()); - iter = mainbuffer_.ringBufferMap_.find(test_id); + iter = mainbuffer_->ringBufferMap_.find(null_id); + CPPUNIT_ASSERT(iter == mainbuffer_->ringBufferMap_.end()); + iter = mainbuffer_->ringBufferMap_.find(test_id); CPPUNIT_ASSERT(iter->first == test_id); CPPUNIT_ASSERT(iter->second == test_ring_buffer); - CPPUNIT_ASSERT(iter->second == mainbuffer_.getRingBuffer(test_id)); + CPPUNIT_ASSERT(iter->second == mainbuffer_->getRingBuffer(test_id)); // test creating twice a buffer (should not create it) - mainbuffer_.createRingBuffer(test_id); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 1); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(test_id) == test_ring_buffer); + mainbuffer_->createRingBuffer(test_id); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 1); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(test_id) == test_ring_buffer); // test remove ring buffer - CPPUNIT_ASSERT(mainbuffer_.removeRingBuffer(null_id) == true); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 1); - CPPUNIT_ASSERT(mainbuffer_.removeRingBuffer(test_id) == true); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 0); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(test_id) == NULL); + CPPUNIT_ASSERT(mainbuffer_->removeRingBuffer(null_id)); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 1); + CPPUNIT_ASSERT(mainbuffer_->removeRingBuffer(test_id)); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.empty()); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(test_id) == NULL); - iter = mainbuffer_.ringBufferMap_.find(test_id); - CPPUNIT_ASSERT(iter == mainbuffer_.ringBufferMap_.end()); + iter = mainbuffer_->ringBufferMap_.find(test_id); + CPPUNIT_ASSERT(iter == mainbuffer_->ringBufferMap_.end()); } void MainBufferTest::testRingBufferReadPointer() { - DEBUG("-------------------- MainBufferTest::testRingBufferReadPointer --------------------\n"); - + TITLE(); std::string call_id = "call id"; std::string read_id = "read id"; std::string null_id = "null id"; @@ -121,7 +92,7 @@ void MainBufferTest::testRingBufferReadPointer() RingBuffer* test_ring_buffer; // test ring buffer read pointers (one per participant) - test_ring_buffer = mainbuffer_.createRingBuffer(call_id); + test_ring_buffer = mainbuffer_->createRingBuffer(call_id); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 0); CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(read_id) == (int) NULL); @@ -158,7 +129,7 @@ void MainBufferTest::testRingBufferReadPointer() void MainBufferTest::testCallIDSet() { - DEBUG("-------------------- MainBufferTest::testCallIDSet --------------------\n"); + TITLE(); std::string test_id = "set id"; std::string false_id = "false set id"; @@ -171,46 +142,45 @@ void MainBufferTest::testCallIDSet() std::string call_id_2 = "call id 2"; // test initial settings - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 0); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 0); - iter_map = mainbuffer_.callIDMap_.find(test_id); - CPPUNIT_ASSERT(iter_map ==mainbuffer_.callIDMap_.end()); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.empty()); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.empty()); + iter_map = mainbuffer_->callIDMap_.find(test_id); + CPPUNIT_ASSERT(iter_map == mainbuffer_->callIDMap_.end()); // test callidset creation - mainbuffer_.createCallIDSet(test_id); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 1); - iter_map = mainbuffer_.callIDMap_.find(test_id); + mainbuffer_->createCallIDSet(test_id); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 1); + iter_map = mainbuffer_->callIDMap_.find(test_id); CPPUNIT_ASSERT(iter_map->first == test_id); - CPPUNIT_ASSERT(iter_map->second == mainbuffer_.getCallIDSet(test_id)); - - CPPUNIT_ASSERT(mainbuffer_.getCallIDSet(false_id) == NULL); - CPPUNIT_ASSERT(mainbuffer_.getCallIDSet(test_id) != NULL); + CPPUNIT_ASSERT(iter_map->second == mainbuffer_->getCallIDSet(test_id)); + CPPUNIT_ASSERT(mainbuffer_->getCallIDSet(false_id) == NULL); + CPPUNIT_ASSERT(mainbuffer_->getCallIDSet(test_id) != NULL); // Test callIDSet add call_ids - mainbuffer_.addCallIDtoSet(test_id, call_id_1); - iter_map = mainbuffer_.callIDMap_.find(test_id); + mainbuffer_->addCallIDtoSet(test_id, call_id_1); + iter_map = mainbuffer_->callIDMap_.find(test_id); CPPUNIT_ASSERT(iter_map->second->size() == 1); iter_set = iter_map->second->find(call_id_1); CPPUNIT_ASSERT(*iter_set == call_id_1); // test add second call id to set - mainbuffer_.addCallIDtoSet(test_id, call_id_2); - iter_map = mainbuffer_.callIDMap_.find(test_id); + mainbuffer_->addCallIDtoSet(test_id, call_id_2); + iter_map = mainbuffer_->callIDMap_.find(test_id); CPPUNIT_ASSERT(iter_map->second->size() == 2); iter_set = iter_map->second->find(call_id_2); CPPUNIT_ASSERT(*iter_set == call_id_2); // test add a call id twice - mainbuffer_.addCallIDtoSet(test_id, call_id_2); - iter_map = mainbuffer_.callIDMap_.find(test_id); + mainbuffer_->addCallIDtoSet(test_id, call_id_2); + iter_map = mainbuffer_->callIDMap_.find(test_id); CPPUNIT_ASSERT(iter_map->second->size() == 2); iter_set = iter_map->second->find(call_id_2); CPPUNIT_ASSERT(*iter_set == call_id_2); // test remove a call id - mainbuffer_.removeCallIDfromSet(test_id, call_id_2); - iter_map = mainbuffer_.callIDMap_.find(test_id); + mainbuffer_->removeCallIDfromSet(test_id, call_id_2); + iter_map = mainbuffer_->callIDMap_.find(test_id); CPPUNIT_ASSERT(iter_map->second->size() == 1); iter_set = iter_map->second->find(call_id_1); CPPUNIT_ASSERT(*iter_set == call_id_1); @@ -218,8 +188,8 @@ void MainBufferTest::testCallIDSet() CPPUNIT_ASSERT(iter_set == iter_map->second->end()); // test remove a call id twice - mainbuffer_.removeCallIDfromSet(test_id, call_id_2); - iter_map = mainbuffer_.callIDMap_.find(test_id); + mainbuffer_->removeCallIDfromSet(test_id, call_id_2); + iter_map = mainbuffer_->callIDMap_.find(test_id); CPPUNIT_ASSERT(iter_map->second->size() == 1); iter_set = iter_map->second->find(call_id_1); CPPUNIT_ASSERT(*iter_set == call_id_1); @@ -227,162 +197,119 @@ void MainBufferTest::testCallIDSet() CPPUNIT_ASSERT(iter_set == iter_map->second->end()); // Test removeCallIDSet - CPPUNIT_ASSERT(mainbuffer_.removeCallIDSet(false_id) == false); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 1); - CPPUNIT_ASSERT(mainbuffer_.removeCallIDSet(test_id) == true); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 0); - - iter_map = mainbuffer_.callIDMap_.find(test_id); - CPPUNIT_ASSERT(iter_map ==mainbuffer_.callIDMap_.end()); - + CPPUNIT_ASSERT(!mainbuffer_->removeCallIDSet(false_id)); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 1); + CPPUNIT_ASSERT(mainbuffer_->removeCallIDSet(test_id)); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.empty()); + iter_map = mainbuffer_->callIDMap_.find(test_id); + CPPUNIT_ASSERT(iter_map == mainbuffer_->callIDMap_.end()); } void MainBufferTest::testRingBufferInt() { - DEBUG("-------------------- MainBufferTest::testRingBufferInt --------------------\n"); - - // CallID test_id = "test_int"; + TITLE(); int testint1 = 12; int testint2 = 13; - int init_put_size; - // test with default ring buffer - RingBuffer* test_ring_buffer = mainbuffer_.createRingBuffer(default_id); + RingBuffer* test_ring_buffer = mainbuffer_->createRingBuffer(MainBuffer::DEFAULT_ID); // initial state - init_put_size = test_ring_buffer->AvailForPut(); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 0); // add some data - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint1, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 0); // add some other data - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint2, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint2, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - 2* (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 0); int testget = (int) NULL; // get some data (without any read pointers) CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int)) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == 2*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 2*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->getLen(MainBuffer::DEFAULT_ID) == 2*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int), MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 2*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->getLen(MainBuffer::DEFAULT_ID) == 2*sizeof(int)); CPPUNIT_ASSERT(testget == (int) NULL); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - 2* (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 0); // get some data (with a read pointer) CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 0); - test_ring_buffer->createReadPointer(default_id); + test_ring_buffer->createReadPointer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 0); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(test_ring_buffer->getLen(MainBuffer::DEFAULT_ID) == 0); // add some data - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint1, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 2*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 2*sizeof(int)); // add some other data - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint2, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint2, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - 2* (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 2*sizeof(int)); - - CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int), 100, default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == sizeof(int)); - CPPUNIT_ASSERT(testget == testint1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 3*sizeof(int)); - - CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int)) == sizeof(int)); - CPPUNIT_ASSERT(testget == testint2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 0); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 4*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 2*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int), MainBuffer::DEFAULT_ID) == sizeof(int)); // test flush data - init_put_size = test_ring_buffer->AvailForPut(); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == sizeof(int)); + test_ring_buffer->Put(&testint1, sizeof(int)); - - test_ring_buffer->flush(); + test_ring_buffer->flush(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 0); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 5*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->getLen(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 5*sizeof(int)); // test flush data - init_put_size = test_ring_buffer->AvailForPut(); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint1, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 5*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->getLen(MainBuffer::DEFAULT_ID) == sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 5*sizeof(int)); - test_ring_buffer->Discard(sizeof(int)); + test_ring_buffer->Discard(sizeof(int), MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 0); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 6*sizeof(int)); - - + CPPUNIT_ASSERT(test_ring_buffer->getLen(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 6*sizeof(int)); } void MainBufferTest::testRingBufferNonDefaultID() { - DEBUG("-------------------- MainBufferTest::testRingBufferNonDefaultID --------------------\n"); + TITLE(); std::string test_id = "test_int"; int testint1 = 12; int testint2 = 13; - int init_put_size; - // test putData, getData with arbitrary read pointer id - RingBuffer* test_ring_buffer = mainbuffer_.createRingBuffer(default_id); + RingBuffer* test_ring_buffer = mainbuffer_->createRingBuffer(MainBuffer::DEFAULT_ID); test_ring_buffer->createReadPointer(test_id); - init_put_size = test_ring_buffer->AvailForPut(); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(default_id) == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 0); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint1, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(default_id) == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 0); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint2, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint2, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - 2* (int) sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(default_id) == 0); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 0); int testget; @@ -392,47 +319,39 @@ void MainBufferTest::testRingBufferNonDefaultID() CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == sizeof(int)); CPPUNIT_ASSERT(testget == testint1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int), 100, test_id) == sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, 100, test_id) == sizeof(int)); CPPUNIT_ASSERT(testget == testint2); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == 0); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size); CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 2*sizeof(int)); // test flush data - init_put_size = test_ring_buffer->AvailForPut(); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint1, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == sizeof(int)); test_ring_buffer->flush(test_id); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == 0); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == 0); CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 3*sizeof(int)); // test flush data - init_put_size = test_ring_buffer->AvailForPut(); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint1, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int) sizeof(int))); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 3*sizeof(int)); test_ring_buffer->Discard(sizeof(int), test_id); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == 0); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == 0); CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 4*sizeof(int)); @@ -444,33 +363,32 @@ void MainBufferTest::testRingBufferNonDefaultID() void MainBufferTest::testRingBufferFloat() { - DEBUG("-------------------- MainBufferTest::testRingBufferFloat --------------------\n"); - + TITLE(); float testfloat1 = 12.5; float testfloat2 = 13.4; - RingBuffer* test_ring_buffer = mainbuffer_.createRingBuffer(default_id); - test_ring_buffer->createReadPointer(default_id); + RingBuffer* test_ring_buffer = mainbuffer_->createRingBuffer(MainBuffer::DEFAULT_ID); + test_ring_buffer->createReadPointer(MainBuffer::DEFAULT_ID); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testfloat1, sizeof(float)) == sizeof(float)); + test_ring_buffer->Put(&testfloat1, sizeof(float)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(float)); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testfloat2, sizeof(float)) == sizeof(float)); + test_ring_buffer->Put(&testfloat2, sizeof(float)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(float)); float testget; - CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(float)) == sizeof(float)); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == sizeof(float)); + CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(float), MainBuffer::DEFAULT_ID) == sizeof(float)); + CPPUNIT_ASSERT(test_ring_buffer->getLen(MainBuffer::DEFAULT_ID) == sizeof(float)); CPPUNIT_ASSERT(testget == testfloat1); - CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(float)) == sizeof(float)); + CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(float), MainBuffer::DEFAULT_ID) == sizeof(float)); CPPUNIT_ASSERT(testget == testfloat2); - CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0); + CPPUNIT_ASSERT(test_ring_buffer->getLen(MainBuffer::DEFAULT_ID) == 0); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testfloat1, sizeof(float)) == sizeof(float)); - test_ring_buffer->flush(); + test_ring_buffer->Put(&testfloat1, sizeof(float)); + test_ring_buffer->flush(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); } @@ -478,24 +396,23 @@ void MainBufferTest::testRingBufferFloat() void MainBufferTest::testTwoPointer() { - DEBUG("-------------------- MainBufferTest::testTwoPointer --------------------\n"); - - RingBuffer* input_buffer = mainbuffer_.createRingBuffer(default_id); - input_buffer->createReadPointer(default_id); - RingBuffer* output_buffer = mainbuffer_.getRingBuffer(default_id); + TITLE(); + RingBuffer* input_buffer = mainbuffer_->createRingBuffer(MainBuffer::DEFAULT_ID); + input_buffer->createReadPointer(MainBuffer::DEFAULT_ID); + RingBuffer* output_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); int test_input = 12; - int test_output; + int test_output = 0; - CPPUNIT_ASSERT(input_buffer->Put(&test_input, sizeof(int)) == sizeof(int)); - CPPUNIT_ASSERT(output_buffer->Get(&test_output, sizeof(float)) == sizeof(float)); + input_buffer->Put(&test_input, sizeof(int)); + CPPUNIT_ASSERT(output_buffer->Get(&test_output, sizeof(float), MainBuffer::DEFAULT_ID) == sizeof(float)); CPPUNIT_ASSERT(test_input == test_output); } void MainBufferTest::testBindUnbindBuffer() { - DEBUG("-------------------- MainBufferTest::testBindUnbindBuffer --------------------\n"); + TITLE(); std::string test_id1 = "bind unbind 1"; std::string test_id2 = "bind unbind 2"; @@ -509,266 +426,266 @@ void MainBufferTest::testBindUnbindBuffer() RingBuffer* ringbuffer; // test initial state with no ring brffer created - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 0); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 0); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 0); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 0); - iter_buffer = mainbuffer_.ringBufferMap_.find(default_id); - CPPUNIT_ASSERT(iter_buffer == mainbuffer_.ringBufferMap_.end()); - iter_idset = mainbuffer_.callIDMap_.find(default_id); - CPPUNIT_ASSERT(iter_idset == mainbuffer_.callIDMap_.end()); + iter_buffer = mainbuffer_->ringBufferMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer == mainbuffer_->ringBufferMap_.end()); + iter_idset = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_idset == mainbuffer_->callIDMap_.end()); - // bind test_id1 with default_id (both buffer not already created) - mainbuffer_.bindCallID(test_id1); + // bind test_id1 with MainBuffer::DEFAULT_ID (both buffer not already created) + mainbuffer_->bindCallID(test_id1, MainBuffer::DEFAULT_ID); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 2); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 2); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 2); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 2); - iter_buffer = mainbuffer_.ringBufferMap_.find(default_id); - CPPUNIT_ASSERT(iter_buffer->first == default_id); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(default_id)); + iter_buffer = mainbuffer_->ringBufferMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->first == MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id1); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id1); CPPUNIT_ASSERT(iter_buffer->first == test_id1); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id1)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id1)); - iter_idset = mainbuffer_.callIDMap_.find(default_id); + iter_idset = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_idset->second->size() == 1); iter_id = iter_idset->second->find(test_id1); CPPUNIT_ASSERT(*iter_id == test_id1); - iter_idset = mainbuffer_.callIDMap_.find(test_id1); + iter_idset = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_idset->second->size() == 1); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); - ringbuffer = mainbuffer_.getRingBuffer(default_id); + ringbuffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(test_id1); + iter_readpointer = ringbuffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - ringbuffer = mainbuffer_.getRingBuffer(test_id1); + ringbuffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - // unbind test_id1 with default_id - mainbuffer_.unBindCallID(test_id1); + // unbind test_id1 with MainBuffer::DEFAULT_ID + mainbuffer_->unBindCallID(test_id1, MainBuffer::DEFAULT_ID); - DEBUG("%i", (int)(mainbuffer_.ringBufferMap_.size())); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 0); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 0); + DEBUG("%i", (int)(mainbuffer_->ringBufferMap_.size())); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 0); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 0); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(default_id) == NULL); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(test_id1) == NULL); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID) == NULL); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(test_id1) == NULL); - // bind test_id2 with default_id (default_id already created) + // bind test_id2 with MainBuffer::DEFAULT_ID (MainBuffer::DEFAULT_ID already created) // calling it twice not supposed to break anything - mainbuffer_.bindCallID(test_id1, default_id); - mainbuffer_.bindCallID(test_id1, default_id); + mainbuffer_->bindCallID(test_id1, MainBuffer::DEFAULT_ID); + mainbuffer_->bindCallID(test_id1, MainBuffer::DEFAULT_ID); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 2); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 2); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 2); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 2); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id2); - CPPUNIT_ASSERT(iter_buffer == mainbuffer_.ringBufferMap_.end()); - iter_idset = mainbuffer_.callIDMap_.find(test_id2); - CPPUNIT_ASSERT(iter_idset == mainbuffer_.callIDMap_.end()); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id2); + CPPUNIT_ASSERT(iter_buffer == mainbuffer_->ringBufferMap_.end()); + iter_idset = mainbuffer_->callIDMap_.find(test_id2); + CPPUNIT_ASSERT(iter_idset == mainbuffer_->callIDMap_.end()); - mainbuffer_.bindCallID(test_id2, default_id); - mainbuffer_.bindCallID(test_id2, default_id); + mainbuffer_->bindCallID(test_id2, MainBuffer::DEFAULT_ID); + mainbuffer_->bindCallID(test_id2, MainBuffer::DEFAULT_ID); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 3); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 3); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 3); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 3); - iter_buffer = mainbuffer_.ringBufferMap_.find(default_id); - CPPUNIT_ASSERT(iter_buffer->first == default_id); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(default_id)); + iter_buffer = mainbuffer_->ringBufferMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->first == MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id1); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id1); CPPUNIT_ASSERT(iter_buffer->first == test_id1); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id1)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id1)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id2); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id2); CPPUNIT_ASSERT(iter_buffer->first == test_id2); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id2)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id2)); - iter_idset = mainbuffer_.callIDMap_.find(default_id); + iter_idset = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_idset->second->size() == 2); iter_id = iter_idset->second->find(test_id1); CPPUNIT_ASSERT(*iter_id == test_id1); iter_id = iter_idset->second->find(test_id2); CPPUNIT_ASSERT(*iter_id == test_id2); - iter_idset = mainbuffer_.callIDMap_.find(test_id1); + iter_idset = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_idset->second->size() == 1); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); - iter_idset = mainbuffer_.callIDMap_.find(test_id2); + iter_idset = mainbuffer_->callIDMap_.find(test_id2); CPPUNIT_ASSERT(iter_idset->second->size() == 1); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); - ringbuffer = mainbuffer_.getRingBuffer(default_id); + ringbuffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2); - iter_readpointer = ringbuffer->_readpointer.find(test_id1); + iter_readpointer = ringbuffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id2); + iter_readpointer = ringbuffer->readpointer_.find(test_id2); CPPUNIT_ASSERT(iter_readpointer->first == test_id2); CPPUNIT_ASSERT(iter_readpointer->second == 0); - ringbuffer = mainbuffer_.getRingBuffer(test_id1); + ringbuffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - ringbuffer = mainbuffer_.getRingBuffer(test_id2); + ringbuffer = mainbuffer_->getRingBuffer(test_id2); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); // bind test_id1 with test_id2 (both testid1 and test_id2 already created) // calling it twice not supposed to break anything - mainbuffer_.bindCallID(test_id1, test_id2); - mainbuffer_.bindCallID(test_id1, test_id2); + mainbuffer_->bindCallID(test_id1, test_id2); + mainbuffer_->bindCallID(test_id1, test_id2); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 3); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 3); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 3); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 3); - iter_buffer = mainbuffer_.ringBufferMap_.find(default_id); - CPPUNIT_ASSERT(iter_buffer->first == default_id); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(default_id)); + iter_buffer = mainbuffer_->ringBufferMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->first == MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id1); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id1); CPPUNIT_ASSERT(iter_buffer->first == test_id1); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id1)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id1)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id2); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id2); CPPUNIT_ASSERT(iter_buffer->first == test_id2); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id2)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id2)); - iter_idset = mainbuffer_.callIDMap_.find(default_id); + iter_idset = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_idset->second->size() == 2); iter_id = iter_idset->second->find(test_id1); CPPUNIT_ASSERT(*iter_id == test_id1); iter_id = iter_idset->second->find(test_id2); CPPUNIT_ASSERT(*iter_id == test_id2); - iter_idset = mainbuffer_.callIDMap_.find(test_id1); + iter_idset = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_idset->second->size() == 2); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); iter_id = iter_idset->second->find(test_id2); CPPUNIT_ASSERT(*iter_id == test_id2); - iter_idset = mainbuffer_.callIDMap_.find(test_id2); + iter_idset = mainbuffer_->callIDMap_.find(test_id2); CPPUNIT_ASSERT(iter_idset->second->size() == 2); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); iter_id = iter_idset->second->find(test_id1); CPPUNIT_ASSERT(*iter_id == test_id1); - ringbuffer = mainbuffer_.getRingBuffer(default_id); + ringbuffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2); - iter_readpointer = ringbuffer->_readpointer.find(test_id1); + iter_readpointer = ringbuffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id2); + iter_readpointer = ringbuffer->readpointer_.find(test_id2); CPPUNIT_ASSERT(iter_readpointer->first == test_id2); CPPUNIT_ASSERT(iter_readpointer->second == 0); - ringbuffer = mainbuffer_.getRingBuffer(test_id1); + ringbuffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id2); + iter_readpointer = ringbuffer->readpointer_.find(test_id2); CPPUNIT_ASSERT(iter_readpointer->first == test_id2); CPPUNIT_ASSERT(iter_readpointer->second == 0); - ringbuffer = mainbuffer_.getRingBuffer(test_id2); + ringbuffer = mainbuffer_->getRingBuffer(test_id2); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id1); + iter_readpointer = ringbuffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); // unbind test_id1 with test_id2 // calling it twice not supposed to break anything - mainbuffer_.unBindCallID(test_id1, test_id2); - mainbuffer_.unBindCallID(test_id1, test_id2); + mainbuffer_->unBindCallID(test_id1, test_id2); + mainbuffer_->unBindCallID(test_id1, test_id2); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 3); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 3); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 3); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 3); - iter_buffer = mainbuffer_.ringBufferMap_.find(default_id); - CPPUNIT_ASSERT(iter_buffer->first == default_id); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(default_id)); + iter_buffer = mainbuffer_->ringBufferMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->first == MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id1); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id1); CPPUNIT_ASSERT(iter_buffer->first == test_id1); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id1)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id1)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id2); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id2); CPPUNIT_ASSERT(iter_buffer->first == test_id2); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id2)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id2)); - iter_idset = mainbuffer_.callIDMap_.find(default_id); + iter_idset = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_idset->second->size() == 2); iter_id = iter_idset->second->find(test_id1); CPPUNIT_ASSERT(*iter_id == test_id1); iter_id = iter_idset->second->find(test_id2); CPPUNIT_ASSERT(*iter_id == test_id2); - iter_idset = mainbuffer_.callIDMap_.find(test_id1); + iter_idset = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_idset->second->size() == 1); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); - iter_idset = mainbuffer_.callIDMap_.find(test_id2); + iter_idset = mainbuffer_->callIDMap_.find(test_id2); CPPUNIT_ASSERT(iter_idset->second->size() == 1); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); - ringbuffer = mainbuffer_.getRingBuffer(default_id); + ringbuffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2); - iter_readpointer = ringbuffer->_readpointer.find(test_id1); + iter_readpointer = ringbuffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id2); + iter_readpointer = ringbuffer->readpointer_.find(test_id2); CPPUNIT_ASSERT(iter_readpointer->first == test_id2); CPPUNIT_ASSERT(iter_readpointer->second == 0); - ringbuffer = mainbuffer_.getRingBuffer(test_id1); + ringbuffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - ringbuffer = mainbuffer_.getRingBuffer(test_id2); + ringbuffer = mainbuffer_->getRingBuffer(test_id2); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); @@ -776,281 +693,249 @@ void MainBufferTest::testBindUnbindBuffer() // unbind test_id1 with test_id2 // calling it twice not supposed to break anything - mainbuffer_.unBindCallID(default_id, test_id2); - mainbuffer_.unBindCallID(default_id, test_id2); + mainbuffer_->unBindCallID(MainBuffer::DEFAULT_ID, test_id2); + mainbuffer_->unBindCallID(MainBuffer::DEFAULT_ID, test_id2); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 2); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 2); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 2); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 2); - iter_buffer = mainbuffer_.ringBufferMap_.find(default_id); - CPPUNIT_ASSERT(iter_buffer->first == default_id); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(default_id)); + iter_buffer = mainbuffer_->ringBufferMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->first == MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id1); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id1); CPPUNIT_ASSERT(iter_buffer->first == test_id1); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id1)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id1)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id2); - CPPUNIT_ASSERT(iter_buffer == mainbuffer_.ringBufferMap_.end()); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id2); + CPPUNIT_ASSERT(iter_buffer == mainbuffer_->ringBufferMap_.end()); - iter_idset = mainbuffer_.callIDMap_.find(default_id); + iter_idset = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_idset->second->size() == 1); iter_id = iter_idset->second->find(test_id1); CPPUNIT_ASSERT(*iter_id == test_id1); iter_id = iter_idset->second->find(test_id2); CPPUNIT_ASSERT(iter_id == iter_idset->second->end()); - iter_idset = mainbuffer_.callIDMap_.find(test_id1); + iter_idset = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_idset->second->size() == 1); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); - iter_idset = mainbuffer_.callIDMap_.find(test_id2); - CPPUNIT_ASSERT(iter_idset == mainbuffer_.callIDMap_.end()); + iter_idset = mainbuffer_->callIDMap_.find(test_id2); + CPPUNIT_ASSERT(iter_idset == mainbuffer_->callIDMap_.end()); - ringbuffer = mainbuffer_.getRingBuffer(default_id); + ringbuffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(test_id1); + iter_readpointer = ringbuffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id2); - CPPUNIT_ASSERT(iter_readpointer == ringbuffer->_readpointer.end()); + iter_readpointer = ringbuffer->readpointer_.find(test_id2); + CPPUNIT_ASSERT(iter_readpointer == ringbuffer->readpointer_.end()); - ringbuffer = mainbuffer_.getRingBuffer(test_id1); + ringbuffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id2); - CPPUNIT_ASSERT(iter_readpointer == ringbuffer->_readpointer.end()); + iter_readpointer = ringbuffer->readpointer_.find(test_id2); + CPPUNIT_ASSERT(iter_readpointer == ringbuffer->readpointer_.end()); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(test_id2) == NULL); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(test_id2) == NULL); - mainbuffer_.unBindCallID(default_id, test_id1); + mainbuffer_->unBindCallID(MainBuffer::DEFAULT_ID, test_id1); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 0); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 0); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 0); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 0); // test unbind all function - mainbuffer_.bindCallID(default_id, test_id1); - mainbuffer_.bindCallID(default_id, test_id2); - mainbuffer_.bindCallID(test_id1, test_id2); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 3); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 3); + mainbuffer_->bindCallID(MainBuffer::DEFAULT_ID, test_id1); + mainbuffer_->bindCallID(MainBuffer::DEFAULT_ID, test_id2); + mainbuffer_->bindCallID(test_id1, test_id2); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 3); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 3); - mainbuffer_.unBindAll(test_id2); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 2); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 2); + mainbuffer_->unBindAll(test_id2); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 2); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 2); - iter_buffer = mainbuffer_.ringBufferMap_.find(default_id); - CPPUNIT_ASSERT(iter_buffer->first == default_id); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(default_id)); + iter_buffer = mainbuffer_->ringBufferMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->first == MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id1); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id1); CPPUNIT_ASSERT(iter_buffer->first == test_id1); - CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_.getRingBuffer(test_id1)); + CPPUNIT_ASSERT(iter_buffer->second == mainbuffer_->getRingBuffer(test_id1)); - iter_buffer = mainbuffer_.ringBufferMap_.find(test_id2); - CPPUNIT_ASSERT(iter_buffer == mainbuffer_.ringBufferMap_.end()); + iter_buffer = mainbuffer_->ringBufferMap_.find(test_id2); + CPPUNIT_ASSERT(iter_buffer == mainbuffer_->ringBufferMap_.end()); - iter_idset = mainbuffer_.callIDMap_.find(default_id); + iter_idset = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_idset->second->size() == 1); iter_id = iter_idset->second->find(test_id1); CPPUNIT_ASSERT(*iter_id == test_id1); iter_id = iter_idset->second->find(test_id2); CPPUNIT_ASSERT(iter_id == iter_idset->second->end()); - iter_idset = mainbuffer_.callIDMap_.find(test_id1); + iter_idset = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_idset->second->size() == 1); - iter_id = iter_idset->second->find(default_id); - CPPUNIT_ASSERT(*iter_id == default_id); + iter_id = iter_idset->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_id == MainBuffer::DEFAULT_ID); - iter_idset = mainbuffer_.callIDMap_.find(test_id2); - CPPUNIT_ASSERT(iter_idset == mainbuffer_.callIDMap_.end()); + iter_idset = mainbuffer_->callIDMap_.find(test_id2); + CPPUNIT_ASSERT(iter_idset == mainbuffer_->callIDMap_.end()); - ringbuffer = mainbuffer_.getRingBuffer(default_id); + ringbuffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(test_id1); + iter_readpointer = ringbuffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id2); - CPPUNIT_ASSERT(iter_readpointer == ringbuffer->_readpointer.end()); + iter_readpointer = ringbuffer->readpointer_.find(test_id2); + CPPUNIT_ASSERT(iter_readpointer == ringbuffer->readpointer_.end()); - ringbuffer = mainbuffer_.getRingBuffer(test_id1); + ringbuffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(ringbuffer != NULL); CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1); - iter_readpointer = ringbuffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = ringbuffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = ringbuffer->_readpointer.find(test_id2); - CPPUNIT_ASSERT(iter_readpointer == ringbuffer->_readpointer.end()); + iter_readpointer = ringbuffer->readpointer_.find(test_id2); + CPPUNIT_ASSERT(iter_readpointer == ringbuffer->readpointer_.end()); } void MainBufferTest::testGetPutDataByID() { - DEBUG("-------------------- MainBufferTest::testGetPutDataByID --------------------\n"); - + TITLE(); std::string test_id = "getData putData"; std::string false_id = "false id"; - mainbuffer_.bindCallID(test_id); + mainbuffer_->bindCallID(test_id, MainBuffer::DEFAULT_ID); int test_input1 = 12; int test_input2 = 13; - int test_output; + int test_output = 0; - int avail_for_put_testid; - int avail_for_put_defaultid; - - // put by default_id get by test_id without preleminary put - avail_for_put_defaultid = mainbuffer_.availForPut(); - CPPUNIT_ASSERT(mainbuffer_.availForGetByID(default_id, test_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.getDataByID(&test_output, sizeof(int), default_id, test_id) == 0); - - // put by default_id, get by test_id - CPPUNIT_ASSERT(mainbuffer_.availForPut() == avail_for_put_defaultid); - CPPUNIT_ASSERT(mainbuffer_.putData(&test_input1, sizeof(int)) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForPut() == (avail_for_put_defaultid - (int) sizeof(int))); - CPPUNIT_ASSERT(mainbuffer_.availForGetByID(default_id, test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.getDataByID(&test_output, sizeof(int), 100, default_id, test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGetByID(default_id, test_id) == 0); - CPPUNIT_ASSERT(test_input1 == test_output); + // put by MainBuffer::DEFAULT_ID get by test_id without preleminary put + CPPUNIT_ASSERT(mainbuffer_->availForGetByID(MainBuffer::DEFAULT_ID, test_id) == 0); + CPPUNIT_ASSERT(mainbuffer_->getDataByID(&test_output, sizeof(int), MainBuffer::DEFAULT_ID, test_id) == 0); + + // put by MainBuffer::DEFAULT_ID, get by test_id + mainbuffer_->putData(&test_input1, sizeof(int), MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(mainbuffer_->availForGetByID(MainBuffer::DEFAULT_ID, test_id) == sizeof(int)); - // get by default_id without preliminary input - avail_for_put_testid = mainbuffer_.availForPut(test_id); - CPPUNIT_ASSERT(mainbuffer_.availForGetByID(test_id, default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.getDataByID(&test_output, sizeof(int), 100, test_id, default_id) == 0); + // get by MainBuffer::DEFAULT_ID without preliminary input + CPPUNIT_ASSERT(mainbuffer_->availForGetByID(test_id, MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(mainbuffer_->getDataByID(&test_output, 100, test_id, MainBuffer::DEFAULT_ID) == 0); // pu by test_id get by test_id - CPPUNIT_ASSERT(mainbuffer_.availForPut(test_id) == avail_for_put_defaultid); - CPPUNIT_ASSERT(mainbuffer_.putData(&test_input2, sizeof(int), test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGetByID(test_id, default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.getDataByID(&test_output, sizeof(int), 100, test_id, default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGetByID(test_id, default_id) == 0); + mainbuffer_->putData(&test_input2, sizeof(int), test_id); + CPPUNIT_ASSERT(mainbuffer_->availForGetByID(test_id, MainBuffer::DEFAULT_ID) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->getDataByID(&test_output, 100, test_id, MainBuffer::DEFAULT_ID) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGetByID(test_id, MainBuffer::DEFAULT_ID) == 0); CPPUNIT_ASSERT(test_input2 == test_output); // put/get by false id - CPPUNIT_ASSERT(mainbuffer_.putData(&test_input2, sizeof(int), false_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.getDataByID(&test_input2, sizeof(int), 100, false_id, false_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.getDataByID(&test_input2, sizeof(int), 100, default_id, false_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.getDataByID(&test_input2, sizeof(int), 100, false_id, default_id) == 0); - - mainbuffer_.unBindCallID(test_id); + mainbuffer_->putData(&test_input2, sizeof(int), false_id); + CPPUNIT_ASSERT(mainbuffer_->getDataByID(&test_input2, 100, false_id, false_id) == 0); + CPPUNIT_ASSERT(mainbuffer_->getDataByID(&test_input2, 100, MainBuffer::DEFAULT_ID, false_id) == 0); + CPPUNIT_ASSERT(mainbuffer_->getDataByID(&test_input2, 100, false_id, MainBuffer::DEFAULT_ID) == 0); + mainbuffer_->unBindCallID(test_id, MainBuffer::DEFAULT_ID); } - void MainBufferTest::testGetPutData() { - DEBUG("-------------------- MainBufferTest::testGetPutData --------------------\n"); + TITLE(); std::string test_id = "incoming rtp session"; - mainbuffer_.bindCallID(test_id); + mainbuffer_->bindCallID(test_id, MainBuffer::DEFAULT_ID); int test_input1 = 12; int test_input2 = 13; int test_output; - int avail_for_put_testid; - int avail_for_put_defaultid; - // get by test_id without preleminary put - avail_for_put_defaultid = mainbuffer_.availForPut(); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.getData(&test_output, sizeof(int), 100, test_id) == 0); - - // put by default_id, get by test_id - CPPUNIT_ASSERT(mainbuffer_.availForPut() == avail_for_put_defaultid); - CPPUNIT_ASSERT(mainbuffer_.putData(&test_input1, sizeof(int)) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForPut() == (avail_for_put_defaultid - (int) sizeof(int))); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.getData(&test_output, sizeof(int), 100, test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id) == 0); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id) == 0); + CPPUNIT_ASSERT(mainbuffer_->getData(&test_output, 100, test_id) == 0); + + // put by MainBuffer::DEFAULT_ID, get by test_id + mainbuffer_->putData(&test_input1, sizeof(int), MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->getData(&test_output, 100, test_id) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id) == 0); CPPUNIT_ASSERT(test_input1 == test_output); - // get by default_id without preleminary put - avail_for_put_testid = mainbuffer_.availForPut(test_id); - CPPUNIT_ASSERT(mainbuffer_.availForGet() == 0); - CPPUNIT_ASSERT(mainbuffer_.getData(&test_output, sizeof(int)) == 0); - - // put by test_id, get by default_id - CPPUNIT_ASSERT(mainbuffer_.availForPut(test_id) == avail_for_put_testid); - CPPUNIT_ASSERT(mainbuffer_.putData(&test_input2, sizeof(int), test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForPut(test_id) == (avail_for_put_testid - (int) sizeof(int))); - CPPUNIT_ASSERT(mainbuffer_.availForGet() == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.getData(&test_output, sizeof(int), 100) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet() == 0); + // get by MainBuffer::DEFAULT_ID without preleminary put + CPPUNIT_ASSERT(mainbuffer_->availForGet(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(mainbuffer_->getData(&test_output, sizeof(int), MainBuffer::DEFAULT_ID) == 0); + + // put by test_id, get by MainBuffer::DEFAULT_ID + mainbuffer_->putData(&test_input2, sizeof(int), test_id); + CPPUNIT_ASSERT(mainbuffer_->availForGet(MainBuffer::DEFAULT_ID) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->getData(&test_output, 100, MainBuffer::DEFAULT_ID) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGet(MainBuffer::DEFAULT_ID) == 0); CPPUNIT_ASSERT(test_input2 == test_output); - mainbuffer_.unBindCallID(test_id); + mainbuffer_->unBindCallID(test_id, MainBuffer::DEFAULT_ID); } void MainBufferTest::testDiscardFlush() { - DEBUG("-------------------- MainBufferTest::testDiscardFlush --------------------\n"); - + TITLE(); std::string test_id = "flush discard"; - // mainbuffer_.createRingBuffer(test_id); - mainbuffer_.bindCallID(test_id); + // mainbuffer_->createRingBuffer(test_id); + mainbuffer_->bindCallID(test_id, MainBuffer::DEFAULT_ID); int test_input1 = 12; // int test_output_size; // int init_size; - CPPUNIT_ASSERT(mainbuffer_.putData(&test_input1, sizeof(int), test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet() == sizeof(int)); - mainbuffer_.discard(sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet() == 0); - - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id) == 0); - mainbuffer_.discard(sizeof(int), test_id); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id) == 0); - - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(test_id)->getReadPointer(default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(test_id)->getReadPointer(test_id) == 0); + mainbuffer_->putData(&test_input1, sizeof(int), test_id); + CPPUNIT_ASSERT(mainbuffer_->availForGet(MainBuffer::DEFAULT_ID) == sizeof(int)); + mainbuffer_->discard(sizeof(int), MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(mainbuffer_->availForGet(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id) == 0); + mainbuffer_->discard(sizeof(int), test_id); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(default_id)->getReadPointer(test_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.putData(&test_input1, sizeof(int), 100) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(default_id)->getReadPointer(test_id) == 0); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(test_id)->getReadPointer(MainBuffer::DEFAULT_ID) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(test_id)->getReadPointer(test_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(default_id)->getReadPointer(test_id) == 0); - mainbuffer_.discard(sizeof(int), test_id); - CPPUNIT_ASSERT(mainbuffer_.getRingBuffer(default_id)->getReadPointer(test_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id) == 0); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)->getReadPointer(test_id) == 0); + mainbuffer_->putData(&test_input1, 100, MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)->getReadPointer(test_id) == 0); - // mainbuffer_.removeRingBuffer(test_id); - mainbuffer_.unBindCallID(test_id); + mainbuffer_->discard(sizeof(int), test_id); + CPPUNIT_ASSERT(mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID)->getReadPointer(test_id) == sizeof(int)); + mainbuffer_->unBindCallID(test_id, MainBuffer::DEFAULT_ID); } void MainBufferTest::testReadPointerInit() { - DEBUG("-------------------- MainBufferTest::testReadPointerInit --------------------\n"); - + TITLE(); std::string test_id = "test read pointer init"; - // RingBuffer* test_ring_buffer = mainbuffer_.createRingBuffer(test_id); - mainbuffer_.bindCallID(test_id); + mainbuffer_->bindCallID(test_id, MainBuffer::DEFAULT_ID); - RingBuffer* test_ring_buffer = mainbuffer_.getRingBuffer(test_id); + RingBuffer* test_ring_buffer = mainbuffer_->getRingBuffer(test_id); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0); - test_ring_buffer->storeReadPointer(30); - CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 30); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 0); + test_ring_buffer->storeReadPointer(30, MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(MainBuffer::DEFAULT_ID) == 30); test_ring_buffer->createReadPointer(test_id); CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 0); @@ -1060,17 +945,17 @@ void MainBufferTest::testReadPointerInit() CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == (int) NULL); test_ring_buffer->removeReadPointer("false id"); - // mainbuffer_.removeRingBuffer(test_id); - mainbuffer_.unBindCallID(test_id); + // mainbuffer_->removeRingBuffer(test_id); + mainbuffer_->unBindCallID(test_id, MainBuffer::DEFAULT_ID); } void MainBufferTest::testRingBufferSeveralPointers() { - DEBUG("-------------------- MainBufferTest::testRingBufferSeveralPointers --------------------\n"); + TITLE(); std::string test_id = "test multiple read pointer"; - RingBuffer* test_ring_buffer = mainbuffer_.createRingBuffer(test_id); + RingBuffer* test_ring_buffer = mainbuffer_->createRingBuffer(test_id); std::string test_pointer1 = "test pointer 1"; std::string test_pointer2 = "test pointer 2"; @@ -1085,35 +970,29 @@ void MainBufferTest::testRingBufferSeveralPointers() int testoutput; - int initPutLen = test_ring_buffer->AvailForPut(); - - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint1, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - (int) sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer1) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer2) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint2, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint2, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 2* (int) sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer1) == 2*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer2) == 2*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 2*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint3, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint3, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 3*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 3* (int) sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer1) == 3*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer2) == 3*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 3*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 3*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->Put(&testint4, sizeof(int)) == sizeof(int)); + test_ring_buffer->Put(&testint4, sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 4*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 4* (int) sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer1) == 4*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer2) == 4*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 4*sizeof(int)); @@ -1122,65 +1001,40 @@ void MainBufferTest::testRingBufferSeveralPointers() CPPUNIT_ASSERT(test_ring_buffer->Get(&testoutput, sizeof(int), test_pointer1) == sizeof(int)); CPPUNIT_ASSERT(testoutput == testint1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 4* (int) sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 3*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 4*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->Get(&testoutput, sizeof(int), test_pointer2) == sizeof(int)); CPPUNIT_ASSERT(testoutput == testint1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 3* (int) sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 3*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 3*sizeof(int)); - // AvailForPut() is ok but AvailForGet(default_id) is not ok // However, we should no be alowed to read in our own ring buffer // if we are either an AudioLayer or and RTP session - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 4*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 4*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->Get(&testoutput, sizeof(int), 100, test_pointer1) == sizeof(int)); - CPPUNIT_ASSERT(testoutput == testint2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 3* (int) sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 3*sizeof(int)); - - // AvailForPut() is ok but AvailForGet(default_id) is not ok // However, we should no be alowed to read in our own ring buffer // if we are either an AudioLayer or and RTP session - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 4*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 4*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->Get(&testoutput, sizeof(int), 100, test_pointer2) == sizeof(int)); - CPPUNIT_ASSERT(testoutput == testint2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 2* (int) sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 2*sizeof(int)); - - // AvailForPut() is ok but AvailForGet(default_id) is not ok // However, we should no be alowed to read in our own ring buffer // if we are either an AudioLayer or and RTP session - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 4*sizeof(int)); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 4*sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->Discard(sizeof(int), test_pointer1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 2* (int) sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 2*sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->Discard(sizeof(int), test_pointer2) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - (int) sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == sizeof(int)); - test_ring_buffer->removeReadPointer(test_pointer1); test_ring_buffer->removeReadPointer(test_pointer2); - mainbuffer_.removeRingBuffer(test_id); + mainbuffer_->removeRingBuffer(test_id); } void MainBufferTest::testConference() { - DEBUG("-------------------- MainBufferTest::testConference --------------------\n"); + TITLE(); std::string test_id1 = "participant A"; std::string test_id2 = "participant B"; @@ -1191,579 +1045,211 @@ void MainBufferTest::testConference() CallIDMap::iterator iter_callidmap; CallIDSet::iterator iter_callidset; - - // test initial setup // ringbuffers - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 0); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer == NULL); // callidmap - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 0); - iter_callidmap = mainbuffer_.callIDMap_.find(default_id); - CPPUNIT_ASSERT(iter_callidmap == mainbuffer_.callIDMap_.end()); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 0); + iter_callidmap = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_callidmap == mainbuffer_->callIDMap_.end()); // test bind Participant A with default - mainbuffer_.bindCallID(test_id1); + mainbuffer_->bindCallID(test_id1, MainBuffer::DEFAULT_ID); // ringbuffers - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 2); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 2); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1); - iter_readpointer = test_ring_buffer->_readpointer.find(test_id1); + iter_readpointer = test_ring_buffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1); - iter_readpointer = test_ring_buffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = test_ring_buffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); // callidmap - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 2); - iter_callidmap = mainbuffer_.callIDMap_.find(default_id); - CPPUNIT_ASSERT(iter_callidmap->first == default_id); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 2); + iter_callidmap = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_callidmap->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_callidmap->second->size() == 1); iter_callidset = iter_callidmap->second->find(test_id1); CPPUNIT_ASSERT(*iter_callidset == test_id1); - iter_callidmap = mainbuffer_.callIDMap_.find(test_id1); + iter_callidmap = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_callidmap->first == test_id1); CPPUNIT_ASSERT(iter_callidmap->second->size() == 1); - iter_callidset = iter_callidmap->second->find(default_id); - CPPUNIT_ASSERT(*iter_callidset == default_id); + iter_callidset = iter_callidmap->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_callidset == MainBuffer::DEFAULT_ID); // test bind Participant B with default - mainbuffer_.bindCallID(test_id2); + mainbuffer_->bindCallID(test_id2, MainBuffer::DEFAULT_ID); // ringbuffers - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 3); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 3); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2); - iter_readpointer = test_ring_buffer->_readpointer.find(test_id1); + iter_readpointer = test_ring_buffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = test_ring_buffer->_readpointer.find(test_id2); + iter_readpointer = test_ring_buffer->readpointer_.find(test_id2); CPPUNIT_ASSERT(iter_readpointer->first == test_id2); CPPUNIT_ASSERT(iter_readpointer->second == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1); - iter_readpointer = test_ring_buffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = test_ring_buffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id2); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1); - iter_readpointer = test_ring_buffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = test_ring_buffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); // callidmap - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 3); - iter_callidmap = mainbuffer_.callIDMap_.find(default_id); - CPPUNIT_ASSERT(iter_callidmap->first == default_id); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 3); + iter_callidmap = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_callidmap->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_callidmap->second->size() == 2); iter_callidset = iter_callidmap->second->find(test_id1); CPPUNIT_ASSERT(*iter_callidset == test_id1); iter_callidset = iter_callidmap->second->find(test_id2); CPPUNIT_ASSERT(*iter_callidset == test_id2); - iter_callidmap = mainbuffer_.callIDMap_.find(test_id1); + iter_callidmap = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_callidmap->first == test_id1); CPPUNIT_ASSERT(iter_callidmap->second->size() == 1); - iter_callidset = iter_callidmap->second->find(default_id); - CPPUNIT_ASSERT(*iter_callidset == default_id); - iter_callidmap = mainbuffer_.callIDMap_.find(test_id2); + iter_callidset = iter_callidmap->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_callidset == MainBuffer::DEFAULT_ID); + iter_callidmap = mainbuffer_->callIDMap_.find(test_id2); CPPUNIT_ASSERT(iter_callidmap->first == test_id2); CPPUNIT_ASSERT(iter_callidmap->second->size() == 1); - iter_callidset = iter_callidmap->second->find(default_id); - CPPUNIT_ASSERT(*iter_callidset == default_id); + iter_callidset = iter_callidmap->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_callidset == MainBuffer::DEFAULT_ID); // test bind Participant A with Participant B - mainbuffer_.bindCallID(test_id1, test_id2); + mainbuffer_->bindCallID(test_id1, test_id2); // ringbuffers - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 3); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + CPPUNIT_ASSERT(mainbuffer_->ringBufferMap_.size() == 3); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2); - iter_readpointer = test_ring_buffer->_readpointer.find(test_id1); + iter_readpointer = test_ring_buffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = test_ring_buffer->_readpointer.find(test_id2); + iter_readpointer = test_ring_buffer->readpointer_.find(test_id2); CPPUNIT_ASSERT(iter_readpointer->first == test_id2); CPPUNIT_ASSERT(iter_readpointer->second == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2); - iter_readpointer = test_ring_buffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = test_ring_buffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = test_ring_buffer->_readpointer.find(test_id2); + iter_readpointer = test_ring_buffer->readpointer_.find(test_id2); CPPUNIT_ASSERT(iter_readpointer->first == test_id2); CPPUNIT_ASSERT(iter_readpointer->second == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id2); CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2); - iter_readpointer = test_ring_buffer->_readpointer.find(default_id); - CPPUNIT_ASSERT(iter_readpointer->first == default_id); + iter_readpointer = test_ring_buffer->readpointer_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_readpointer->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_readpointer->second == 0); - iter_readpointer = test_ring_buffer->_readpointer.find(test_id1); + iter_readpointer = test_ring_buffer->readpointer_.find(test_id1); CPPUNIT_ASSERT(iter_readpointer->first == test_id1); CPPUNIT_ASSERT(iter_readpointer->second == 0); // callidmap - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 3); - iter_callidmap = mainbuffer_.callIDMap_.find(default_id); - CPPUNIT_ASSERT(iter_callidmap->first == default_id); + CPPUNIT_ASSERT(mainbuffer_->callIDMap_.size() == 3); + iter_callidmap = mainbuffer_->callIDMap_.find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(iter_callidmap->first == MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(iter_callidmap->second->size() == 2); iter_callidset = iter_callidmap->second->find(test_id1); CPPUNIT_ASSERT(*iter_callidset == test_id1); iter_callidset = iter_callidmap->second->find(test_id2); CPPUNIT_ASSERT(*iter_callidset == test_id2); - iter_callidmap = mainbuffer_.callIDMap_.find(test_id1); + iter_callidmap = mainbuffer_->callIDMap_.find(test_id1); CPPUNIT_ASSERT(iter_callidmap->first == test_id1); CPPUNIT_ASSERT(iter_callidmap->second->size() == 2); - iter_callidset = iter_callidmap->second->find(default_id); - CPPUNIT_ASSERT(*iter_callidset == default_id); + iter_callidset = iter_callidmap->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_callidset == MainBuffer::DEFAULT_ID); iter_callidset = iter_callidmap->second->find(test_id2); CPPUNIT_ASSERT(*iter_callidset == test_id2); - iter_callidmap = mainbuffer_.callIDMap_.find(test_id2); + iter_callidmap = mainbuffer_->callIDMap_.find(test_id2); CPPUNIT_ASSERT(iter_callidmap->first == test_id2); CPPUNIT_ASSERT(iter_callidmap->second->size() == 2); - iter_callidset = iter_callidmap->second->find(default_id); - CPPUNIT_ASSERT(*iter_callidset == default_id); + iter_callidset = iter_callidmap->second->find(MainBuffer::DEFAULT_ID); + CPPUNIT_ASSERT(*iter_callidset == MainBuffer::DEFAULT_ID); iter_callidset = iter_callidmap->second->find(test_id1); CPPUNIT_ASSERT(*iter_callidset == test_id1); // test putData default int testint = 12; - int init_put_defaultid; - int init_put_id1; - int init_put_id2; - - init_put_defaultid = mainbuffer_.getRingBuffer(default_id)->AvailForPut(); - init_put_id1 = mainbuffer_.getRingBuffer(test_id1)->AvailForPut(); - init_put_id2 = mainbuffer_.getRingBuffer(test_id2)->AvailForPut(); - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == 0); + + CPPUNIT_ASSERT(mainbuffer_->availForGet(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id1) == 0); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id2) == 0); // put data test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int)) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + mainbuffer_->putData(&testint, sizeof(int), MainBuffer::DEFAULT_ID); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 0); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id2); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 0); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); // test mainbuffer availforget (get data even if some participant missing) - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGet(MainBuffer::DEFAULT_ID) == 0); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id1) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id2) == sizeof(int)); //putdata test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int), 100, test_id1) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + mainbuffer_->putData(&testint, 100, test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id2); CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); + CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(MainBuffer::DEFAULT_ID) == 0); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget (get data even if some participant missing) - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - //putdata test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int), 100, test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + + mainbuffer_->putData(&testint, 100, test_id2); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id2); // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - - - int test_output; + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id1) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id2) == sizeof(int)); // test getData default id (audio layer) - CPPUNIT_ASSERT(mainbuffer_.getData(&test_output, sizeof(int), 100) == sizeof(int)); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id2); // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id1) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id2) == sizeof(int)); // test getData test_id1 (audio layer) - CPPUNIT_ASSERT(mainbuffer_.getData(&test_output, sizeof(int), 100, test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id2); + // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); + CPPUNIT_ASSERT(mainbuffer_->availForGet(test_id2) == sizeof(int)); // test getData test_id2 (audio layer) - CPPUNIT_ASSERT(mainbuffer_.getData(&test_output, sizeof(int), 100, test_id2) == sizeof(int)); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_defaultid); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == 0); - - - // test putData default (for discarting) - init_put_defaultid = mainbuffer_.getRingBuffer(default_id)->AvailForPut(); - init_put_id1 = mainbuffer_.getRingBuffer(test_id1)->AvailForPut(); - init_put_id2 = mainbuffer_.getRingBuffer(test_id2)->AvailForPut(); - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == 0); - // put data test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int), 100) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - //putdata test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int), 100, test_id1) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - //putdata test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int), 100, test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - - // test discardData default id (audio layer) - CPPUNIT_ASSERT(mainbuffer_.discard(sizeof(int)) == sizeof(int)); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - // test discardData test_id1 (audio layer) - CPPUNIT_ASSERT(mainbuffer_.discard(sizeof(int), test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - // test discardData test_id2 (audio layer) - CPPUNIT_ASSERT(mainbuffer_.discard(sizeof(int), test_id2) == sizeof(int)); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_defaultid); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == 0); - - - // test putData default (for flushing) - init_put_defaultid = mainbuffer_.getRingBuffer(default_id)->AvailForPut(); - init_put_id1 = mainbuffer_.getRingBuffer(test_id1)->AvailForPut(); - init_put_id2 = mainbuffer_.getRingBuffer(test_id2)->AvailForPut(); - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == 0); - // put data test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int), 100) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - //putdata test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int), 100, test_id1) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - //putdata test ring buffers - CPPUNIT_ASSERT(mainbuffer_.putData(&testint, sizeof(int), 100, test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - - // test flush default id (audio layer) - mainbuffer_.flush(); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - DEBUG("%i", test_ring_buffer->putLen()); - test_ring_buffer->debug(); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int)); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == sizeof(int)); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - // test flush test_id1 (audio layer) - mainbuffer_.flush(test_id1); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int)); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int))); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int)); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == sizeof(int)); - // test flush test_id2 (audio layer) - mainbuffer_.flush(test_id2); - CPPUNIT_ASSERT(test_output == (testint + testint)); - test_ring_buffer = mainbuffer_.getRingBuffer(default_id); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_defaultid); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id1); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0); - test_ring_buffer = mainbuffer_.getRingBuffer(test_id2); - CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0); - CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0); - // test mainbuffer availforget - CPPUNIT_ASSERT(mainbuffer_.availForGet(default_id) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id1) == 0); - CPPUNIT_ASSERT(mainbuffer_.availForGet(test_id2) == 0); - - - mainbuffer_.unBindCallID(test_id1, test_id2); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 3); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 3); - - mainbuffer_.unBindCallID(test_id1); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 2); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 2); - - mainbuffer_.unBindCallID(test_id2); - CPPUNIT_ASSERT(mainbuffer_.ringBufferMap_.size() == 0); - CPPUNIT_ASSERT(mainbuffer_.callIDMap_.size() == 0); + test_ring_buffer = mainbuffer_->getRingBuffer(MainBuffer::DEFAULT_ID); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id1); + test_ring_buffer = mainbuffer_->getRingBuffer(test_id2); } + +MainBufferTest::MainBufferTest() : CppUnit::TestCase("Audio Layer Tests"), mainbuffer_(new MainBuffer) {} diff --git a/daemon/test/mainbuffertest.h b/daemon/test/mainbuffertest.h index 316191f4964ab92f8d1c3fbc2e10f8d5eefb2e65..98139ed0d80457d4fb29ddcc4a0334397e3bf314 100644 --- a/daemon/test/mainbuffertest.h +++ b/daemon/test/mainbuffertest.h @@ -28,46 +28,23 @@ * as that of the covered work. */ +#ifndef MAINBUFFER_TEST_ +#define MAINBUFFER_TEST_ + // Cppunit import #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCaller.h> #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include <assert.h> - -#include <stdio.h> -#include <sstream> -#include <ccrtp/rtp.h> - - -// pjsip import -#include <pjsip.h> -#include <pjlib.h> -#include <pjsip_ua.h> -#include <pjlib-util.h> -#include <pjnath/stun_config.h> - -// Application import -#include "manager.h" -#include "audio/mainbuffer.h" -#include "audio/ringbuffer.h" -#include "call.h" -// #include "config/config.h" -// #include "user_cfg.h" - - +#include <tr1/memory> +class MainBuffer; /* * @file audiorecorderTest.cpp - * @brief Regroups unitary tests related to the plugin manager. + * @brief Regroups unit tests related to the main buffer. */ -#ifndef _MAINBUFFER_TEST_ -#define _MAINBUFFER_TEST_ - - - class MainBufferTest : public CppUnit::TestCase { /* @@ -92,19 +69,7 @@ class MainBufferTest : public CppUnit::TestCase { public: - MainBufferTest() : CppUnit::TestCase("Audio Layer Tests") {} - - /* - * Code factoring - Common resources can be initialized here. - * This method is called by unitcpp before each test - */ - void setUp(); - - /* - * Code factoring - Common resources can be released here. - * This method is called by unitcpp after each test - */ - void tearDown(); + MainBufferTest(); void testRingBufferCreation(); @@ -138,11 +103,11 @@ class MainBufferTest : public CppUnit::TestCase { private: - MainBuffer mainbuffer_; + std::tr1::shared_ptr<MainBuffer> mainbuffer_; }; /* Register our test module */ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(MainBufferTest, "MainBufferTest"); CPPUNIT_TEST_SUITE_REGISTRATION(MainBufferTest); -#endif +#endif // MAINBUFFER_TEST_ diff --git a/daemon/test/numbercleanertest.cpp b/daemon/test/numbercleanertest.cpp index d9642a7201aae83b6d2b95506f0d8969776c547f..7cbb28f885d9a5be2a986986b8d86db64c9ab41f 100644 --- a/daemon/test/numbercleanertest.cpp +++ b/daemon/test/numbercleanertest.cpp @@ -28,11 +28,11 @@ * as that of the covered work. */ -#include <stdio.h> +#include <cstdio> #include <sstream> #include <dlfcn.h> -#include "global.h" +#include "logger.h" #include "numbercleanertest.h" diff --git a/daemon/test/resamplertest.cpp b/daemon/test/resamplertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..810a389ea3a586f80db7c467b9ab0bc7f122ed9a --- /dev/null +++ b/daemon/test/resamplertest.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Savoir-Faire Linux Inc. + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include <iostream> +#include <iterator> +#include <algorithm> +#include <math.h> + +#include "resamplertest.h" + +ResamplerTest::ResamplerTest() : + CppUnit::TestCase("Resampler module test"), inputBuffer(), outputBuffer() +{} + +void ResamplerTest::setUp() +{ + +} + +void ResamplerTest::tearDown() +{ + +} + +namespace { + template <typename T> + void print_buffer(T &buffer) + { + std::copy(buffer.begin(), buffer.end(), + std::ostream_iterator<SFLDataFormat>(std::cout, ", ")); + std::cout << std::endl; + } +} + +void ResamplerTest::testUpsamplingRamp() +{ + // generate input samples and store them in inputBuffer + generateRamp(); + + std::cout << "Test Upsampling Ramp" << std::endl; + SamplerateConverter converter(44100); + + performUpsampling(converter); + + LowSmplrBuffer tmpInputBuffer; + HighSmplrBuffer tmpOutputBuffer; + + std::copy(inputBuffer.begin(), inputBuffer.begin() + tmpInputBuffer.size(), tmpInputBuffer.begin()); + std::cout << "Input Buffer" << std::endl; + print_buffer(tmpInputBuffer); + + std::copy(outputBuffer.begin(), outputBuffer.begin() + tmpOutputBuffer.size(), tmpOutputBuffer.begin()); + std::cout << "Output Buffer" << std::endl; + print_buffer(tmpOutputBuffer); +} + +void ResamplerTest::testDownsamplingRamp() +{ + generateRamp(); + + std::cout << "Test Downsampling Ramp" << std::endl; + SamplerateConverter converter(44100); + + performDownsampling(converter); + + HighSmplrBuffer tmpInputBuffer; + LowSmplrBuffer tmpOutputBuffer; + + std::copy(inputBuffer.begin(), inputBuffer.begin() + tmpInputBuffer.size(), tmpInputBuffer.begin()); + std::cout << "Input Buffer" << std::endl; + print_buffer(tmpInputBuffer); + + std::copy(outputBuffer.begin(), outputBuffer.begin() + tmpOutputBuffer.size(), tmpOutputBuffer.begin()); + std::cout << "Output Buffer" << std::endl; + print_buffer(tmpOutputBuffer); +} + +void ResamplerTest::testUpsamplingTriangle() +{ + generateTriangularSignal(); + + std::cout << "Test Upsampling Triangle" << std::endl; + SamplerateConverter converter(44100); + + performUpsampling(converter); + + LowSmplrBuffer tmpInputBuffer; + HighSmplrBuffer tmpOutputBuffer; + + std::copy(inputBuffer.begin(), inputBuffer.begin() + tmpInputBuffer.size(), tmpInputBuffer.begin()); + std::cout << "Input Buffer" << std::endl; + print_buffer(tmpInputBuffer); + + std::copy(outputBuffer.begin(), outputBuffer.begin() + tmpOutputBuffer.size(), tmpOutputBuffer.begin()); + std::cout << "Output Buffer" << std::endl; + print_buffer(tmpOutputBuffer); +} + +void ResamplerTest::testDownsamplingTriangle() +{ + generateTriangularSignal(); + + std::cout << "Test Downsampling Triangle" << std::endl; + SamplerateConverter converter(44100); + + performDownsampling(converter); + + HighSmplrBuffer tmpInputBuffer; + LowSmplrBuffer tmpOutputBuffer; + + std::copy(inputBuffer.begin(), inputBuffer.begin() + tmpInputBuffer.size(), tmpInputBuffer.begin()); + std::cout << "Input Buffer" << std::endl; + print_buffer(tmpInputBuffer); + + std::copy(outputBuffer.begin(), outputBuffer.begin() + tmpOutputBuffer.size(), tmpOutputBuffer.begin()); + std::cout << "Output Buffer" << std::endl; + print_buffer(tmpOutputBuffer); +} +void ResamplerTest::testUpsamplingSine() +{ + // generate input samples and store them in inputBuffer + generateSineSignal(); + + std::cout << "Test Upsampling Sine" << std::endl; + SamplerateConverter converter(44100); + + performUpsampling(converter); + + LowSmplrBuffer tmpInputBuffer; + HighSmplrBuffer tmpOutputBuffer; + + std::copy(inputBuffer.begin(), inputBuffer.begin() + tmpInputBuffer.size(), tmpInputBuffer.begin()); + std::cout << "Input Buffer" << std::endl; + print_buffer(tmpInputBuffer); + + std::copy(outputBuffer.begin(), outputBuffer.begin() + tmpOutputBuffer.size(), tmpOutputBuffer.begin()); + std::cout << "Output Buffer" << std::endl; + print_buffer(tmpOutputBuffer); +} + +void ResamplerTest::testDownsamplingSine() +{ + // generate input samples and store them in inputBuffer + generateSineSignal(); + + std::cout << "Test Downsampling Sine" << std::endl; + SamplerateConverter converter(44100); + + performDownsampling(converter); + + HighSmplrBuffer tmpInputBuffer; + LowSmplrBuffer tmpOutputBuffer; + + std::copy(inputBuffer.begin(), inputBuffer.begin() + tmpInputBuffer.size(), tmpInputBuffer.begin()); + std::cout << "Input Buffer" << std::endl; + print_buffer(tmpInputBuffer); + + std::copy(outputBuffer.begin(), outputBuffer.begin() + tmpOutputBuffer.size(), tmpOutputBuffer.begin()); + std::cout << "Output Buffer" << std::endl; + print_buffer(tmpOutputBuffer); +} + +void ResamplerTest::generateRamp() +{ + for (size_t i = 0; i < inputBuffer.size(); ++i) + inputBuffer[i] = i; +} + +void ResamplerTest::generateTriangularSignal() +{ + for (size_t i = 0; i < inputBuffer.size(); ++i) + inputBuffer[i] = i * 10; +} + +void ResamplerTest::generateSineSignal() +{ + for (size_t i = 0; i < inputBuffer.size(); ++i) + inputBuffer[i] = (SFLDataFormat) (1000.0 * sin(i)); +} + +void ResamplerTest::performUpsampling(SamplerateConverter &converter) +{ + LowSmplrBuffer tmpInputBuffer; + HighSmplrBuffer tmpOutputBuffer; + + for (size_t i = 0, j = 0; i < (inputBuffer.size() / 2); i += tmpInputBuffer.size(), j += tmpOutputBuffer.size()) { + std::copy(inputBuffer.begin() + i, inputBuffer.begin() + tmpInputBuffer.size() + i, tmpInputBuffer.begin()); + converter.resample(tmpInputBuffer.data(), tmpOutputBuffer.data(), tmpOutputBuffer.size(), 8000, 16000, tmpInputBuffer.size()); + std::copy(tmpOutputBuffer.begin(), tmpOutputBuffer.end(), outputBuffer.begin() + j); + } +} + +void ResamplerTest::performDownsampling(SamplerateConverter &converter) +{ + HighSmplrBuffer tmpInputBuffer; + LowSmplrBuffer tmpOutputBuffer; + + for (size_t i = 0, j = 0; i < inputBuffer.size(); i += tmpInputBuffer.size(), j += tmpOutputBuffer.size()) { + std::copy(inputBuffer.begin() + i, inputBuffer.begin() + tmpInputBuffer.size() + i, tmpInputBuffer.begin()); + converter.resample(tmpInputBuffer.data(), tmpOutputBuffer.data(), tmpOutputBuffer.size(), 16000, 8000, tmpInputBuffer.size()); + std::copy(tmpOutputBuffer.begin(), tmpOutputBuffer.end(), outputBuffer.begin() + j); + } +} diff --git a/daemon/test/resamplertest.h b/daemon/test/resamplertest.h new file mode 100644 index 0000000000000000000000000000000000000000..07e95dd93b79075384be2bc85c29f22028641a94 --- /dev/null +++ b/daemon/test/resamplertest.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2012 Savoir-Faire Linux Inc. + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef _RESAMPLER_TEST_ +#define _RESAMPLER_TEST_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCaller.h> +#include <cppunit/TestCase.h> +#include <cppunit/TestSuite.h> + +#include <tr1/array> + +#include "audio/samplerateconverter.h" +#include "noncopyable.h" + +#define MAX_BUFFER_LENGTH 40000 +#define TMP_LOWSMPLR_BUFFER_LENGTH 160 +#define TMP_HIGHSMPLR_BUFFER_LENGTH 320 + +typedef std::tr1::array<SFLDataFormat, TMP_LOWSMPLR_BUFFER_LENGTH> LowSmplrBuffer; +typedef std::tr1::array<SFLDataFormat, TMP_HIGHSMPLR_BUFFER_LENGTH> HighSmplrBuffer; + +class ResamplerTest : public CppUnit::TestCase { + + /** + * Use cppunit library macros to add unit test the factory + */ + CPPUNIT_TEST_SUITE(ResamplerTest); + CPPUNIT_TEST(testUpsamplingRamp); + CPPUNIT_TEST(testDownsamplingRamp); + CPPUNIT_TEST(testUpsamplingTriangle); + CPPUNIT_TEST(testDownsamplingTriangle); + CPPUNIT_TEST(testUpsamplingSine); + CPPUNIT_TEST(testDownsamplingSine); + CPPUNIT_TEST_SUITE_END(); + + public: + ResamplerTest(); + + /* + * Code factoring - Common resources can be initialized here. + * This method is called by unitcpp before each test + */ + void setUp(); + + /* + * Code factoring - Common resources can be released here. + * This method is called by unitcpp after each test + */ + void tearDown(); + + /* + * Generate a ramp and upsamples it form 8kHz to 16kHz + */ + void testUpsamplingRamp(); + + /* + * Generate a ramp and downsamples it from 16kHz to 8kHz + */ + void testDownsamplingRamp(); + + /* + * Generate a triangular signal and upsamples it from 8kHz to 16kHz + */ + void testUpsamplingTriangle(); + + /* + * Generate a triangular signal and downsamples it from 16kHz to 8kHz + */ + void testDownsamplingTriangle(); + + /* + * Generate a sine signal and upsamples it from 8kHz to 16kHz + */ + void testUpsamplingSine(); + + /* + * Generate a sine signal and downsamples it from 16kHz to 8kHz + */ + void testDownsamplingSine(); + +private: + NON_COPYABLE(ResamplerTest); + + /* + * Generate a ramp to be stored in inputBuffer + */ + void generateRamp(); + + /* + * Generate a triangular signal to be stored in inputBuffer + */ + void generateTriangularSignal(); + + /* + * Generate a sine signal to be stored in inputBuffer + */ + void generateSineSignal(); + + /* + * Perform upsampling on the whole input buffer + */ + void performUpsampling(SamplerateConverter &converter); + + /* + * Perform downsampling on the whold input buffer + */ + void performDownsampling(SamplerateConverter &converter); + + /** + * Used to store input samples + */ + std::tr1::array<SFLDataFormat, MAX_BUFFER_LENGTH> inputBuffer; + + /** + * Used to receive output samples + */ + std::tr1::array<SFLDataFormat, MAX_BUFFER_LENGTH> outputBuffer; +}; + +/* Register the test module */ +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ResamplerTest, "ResamplerTest"); +CPPUNIT_TEST_SUITE_REGISTRATION(ResamplerTest); + +#endif // _RESAMPLER_TEST_ diff --git a/daemon/test/sdesnegotiatortest.cpp b/daemon/test/sdesnegotiatortest.cpp index 2330412ff1a28b8d928b4bc26582acee8e3a56a6..26014a1a28596ca6040bf173d711f120ffdc8bf3 100644 --- a/daemon/test/sdesnegotiatortest.cpp +++ b/daemon/test/sdesnegotiatortest.cpp @@ -45,99 +45,82 @@ #include "sip/sdes_negotiator.h" #include <unistd.h> -#include "global.h" +#include "test_utils.h" +#include "logger.h" using std::cout; using std::endl; -SdesNegotiatorTest::SdesNegotiatorTest() : pattern(0), sdesnego(0), - remoteOffer(0), localCapabilities(0) -{} - void SdesNegotiatorTest::testTagPattern() { - DEBUG("-------------------- SdesNegotiatorTest::testTagPattern --------------------\n"); - + TITLE(); std::string subject = "a=crypto:4"; - pattern = new sfl::Pattern("^a=crypto:(?P<tag>[0-9]{1,9})"); - *pattern << subject; - - CPPUNIT_ASSERT(pattern->matches()); - CPPUNIT_ASSERT(pattern->group("tag").compare("4") == 0); + sfl::Pattern pattern("^a=crypto:(?P<tag>[0-9]{1,9})"); + pattern << subject; - delete pattern; - pattern = NULL; + CPPUNIT_ASSERT(pattern.matches()); + CPPUNIT_ASSERT(pattern.group("tag").compare("4") == 0); } void SdesNegotiatorTest::testCryptoSuitePattern() { - DEBUG("-------------------- SdesNegotiatorTest::testCryptoSuitePattern --------------------\n"); - + TITLE(); std::string subject = "AES_CM_128_HMAC_SHA1_80"; - pattern = new sfl::Pattern("(?P<cryptoSuite>AES_CM_128_HMAC_SHA1_80|" \ + sfl::Pattern pattern("(?P<cryptoSuite>AES_CM_128_HMAC_SHA1_80|" \ "AES_CM_128_HMAC_SHA1_32|" \ "F8_128_HMAC_SHA1_80|" \ "[A-Za-z0-9_]+)"); - *pattern << subject; - - CPPUNIT_ASSERT(pattern->matches()); - CPPUNIT_ASSERT(pattern->group("cryptoSuite").compare("AES_CM_128_HMAC_SHA1_80") == 0); + pattern << subject; - delete pattern; - pattern = NULL; + CPPUNIT_ASSERT(pattern.matches()); + CPPUNIT_ASSERT(pattern.group("cryptoSuite").compare("AES_CM_128_HMAC_SHA1_80") == 0); } void SdesNegotiatorTest::testKeyParamsPattern() { - DEBUG("-------------------- SdesNegotiatorTest::testKeyParamsPattern --------------------\n"); + TITLE(); std::string subject = "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32"; - pattern = new sfl::Pattern("(?P<srtpKeyMethod>inline|[A-Za-z0-9_]+)\\:" \ + sfl::Pattern pattern("(?P<srtpKeyMethod>inline|[A-Za-z0-9_]+)\\:" \ "(?P<srtpKeyInfo>[A-Za-z0-9\x2B\x2F\x3D]+)\\|" \ "(2\\^(?P<lifetime>[0-9]+)\\|" \ "(?P<mkiValue>[0-9]+)\\:" \ "(?P<mkiLength>[0-9]{1,3})\\;?)?", "g"); - *pattern << subject; + pattern << subject; - pattern->matches(); - CPPUNIT_ASSERT(pattern->group("srtpKeyMethod").compare("inline:")); - CPPUNIT_ASSERT(pattern->group("srtpKeyInfo").compare("d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj") + pattern.matches(); + CPPUNIT_ASSERT(pattern.group("srtpKeyMethod").compare("inline:")); + CPPUNIT_ASSERT(pattern.group("srtpKeyInfo").compare("d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj") == 0); - CPPUNIT_ASSERT(pattern->group("lifetime").compare("20") == 0); - CPPUNIT_ASSERT(pattern->group("mkiValue").compare("1") == 0); - CPPUNIT_ASSERT(pattern->group("mkiLength").compare("32") == 0); - - delete pattern; - pattern = NULL; + CPPUNIT_ASSERT(pattern.group("lifetime").compare("20") == 0); + CPPUNIT_ASSERT(pattern.group("mkiValue").compare("1") == 0); + CPPUNIT_ASSERT(pattern.group("mkiLength").compare("32") == 0); } void SdesNegotiatorTest::testKeyParamsPatternWithoutMKI() { - DEBUG("-------------------- SdesNegotiatorTest::testKeyParamsPatternWithoutMKI --------------------\n"); + TITLE(); - std::string subject = "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj"; + std::string subject("inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj"); - pattern = new sfl::Pattern("(?P<srtpKeyMethod>inline|[A-Za-z0-9_]+)\\:" \ + sfl::Pattern pattern("(?P<srtpKeyMethod>inline|[A-Za-z0-9_]+)\\:" \ "(?P<srtpKeyInfo>[A-Za-z0-9\x2B\x2F\x3D]+)" \ "(\\|2\\^(?P<lifetime>[0-9]+)\\|" \ "(?P<mkiValue>[0-9]+)\\:" \ "(?P<mkiLength>[0-9]{1,3})\\;?)?", "g"); - *pattern << subject; - pattern->matches(); - CPPUNIT_ASSERT(pattern->group("srtpKeyMethod").compare("inline:")); - CPPUNIT_ASSERT(pattern->group("srtpKeyInfo").compare("d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj") + pattern << subject; + pattern.matches(); + CPPUNIT_ASSERT(pattern.group("srtpKeyMethod").compare("inline:")); + CPPUNIT_ASSERT(pattern.group("srtpKeyInfo").compare("d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj") == 0); - - delete pattern; - pattern = NULL; } @@ -147,33 +130,22 @@ void SdesNegotiatorTest::testKeyParamsPatternWithoutMKI() */ void SdesNegotiatorTest::testNegotiation() { - DEBUG("-------------------- SdesNegotiatorTest::testNegotiation --------------------\n"); + TITLE(); // Add a new SDES crypto line to be processed. - remoteOffer = new std::vector<std::string>(); - remoteOffer->push_back(std::string("a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd|2^20|1:32")); - remoteOffer->push_back(std::string("a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32")); + std::vector<std::string> remoteOffer; + remoteOffer.push_back("a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd|2^20|1:32"); + remoteOffer.push_back("a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32"); // Register the local capabilities. - localCapabilities = new std::vector<sfl::CryptoSuiteDefinition>(); - - for (int i = 0; i < 3; i++) { - localCapabilities->push_back(sfl::CryptoSuites[i]); - } - - sdesnego = new sfl::SdesNegotiator(*localCapabilities, *remoteOffer); - - CPPUNIT_ASSERT(sdesnego->negotiate()); - // CPPUNIT_ASSERT(sdesnego->getKeyInfo().compare("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd|2^20|1:32")==0); + std::vector<sfl::CryptoSuiteDefinition> localCapabilities; - delete remoteOffer; - remoteOffer = NULL; + for (int i = 0; i < 3; ++i) + localCapabilities.push_back(sfl::CryptoSuites[i]); - delete localCapabilities; - localCapabilities = NULL; + sfl::SdesNegotiator sdesnego(localCapabilities, remoteOffer); - delete sdesnego; - sdesnego = NULL; + CPPUNIT_ASSERT(sdesnego.negotiate()); } /** @@ -181,103 +153,82 @@ void SdesNegotiatorTest::testNegotiation() */ void SdesNegotiatorTest::testComponent() { - DEBUG("-------------------- SdesNegotiatorTest::testComponent --------------------\n"); + TITLE(); // Register the local capabilities. - std::vector<sfl::CryptoSuiteDefinition> * capabilities = new std::vector<sfl::CryptoSuiteDefinition>(); + std::vector<sfl::CryptoSuiteDefinition> capabilities; - //Support all the CryptoSuites - for (int i = 0; i < 3; i++) { - capabilities->push_back(sfl::CryptoSuites[i]); - } + // Support all the CryptoSuites + for (int i = 0; i < 3; i++) + capabilities.push_back(sfl::CryptoSuites[i]); // Make sure that if a component is missing, negotiate will fail std::string cryptoLine("a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:|2^20|1:32"); - std::vector<std::string> * cryptoOffer = new std::vector<std::string>(); - cryptoOffer->push_back(cryptoLine); - - sfl::SdesNegotiator * negotiator = new sfl::SdesNegotiator(*capabilities, *cryptoOffer); + std::vector<std::string> cryptoOffer; + cryptoOffer.push_back(cryptoLine); - CPPUNIT_ASSERT(negotiator->negotiate() == false); + sfl::SdesNegotiator negotiator(capabilities, cryptoOffer); + CPPUNIT_ASSERT(!negotiator.negotiate()); } - - /** * Make sure that most simple case does not fail. */ void SdesNegotiatorTest::testMostSimpleCase() { - DEBUG("-------------------- SdesNegotiatorTest::testMostSimpleCase --------------------\n"); + TITLE(); // Register the local capabilities. - std::vector<sfl::CryptoSuiteDefinition> * capabilities = new std::vector<sfl::CryptoSuiteDefinition>(); + std::vector<sfl::CryptoSuiteDefinition> capabilities; - //Support all the CryptoSuites - for (int i = 0; i < 3; i++) { - capabilities->push_back(sfl::CryptoSuites[i]); - } + // Support all the CryptoSuites + for (int i = 0; i < 3; i++) + capabilities.push_back(sfl::CryptoSuites[i]); // Make sure taht this case works (since it's default for most application) std::string cryptoLine("a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd"); - std::vector<std::string> * cryptoOffer = new std::vector<std::string>(); - cryptoOffer->push_back(cryptoLine); + std::vector<std::string> cryptoOffer; + cryptoOffer.push_back(cryptoLine); - sfl::SdesNegotiator * negotiator = new sfl::SdesNegotiator(*capabilities, *cryptoOffer); + sfl::SdesNegotiator negotiator(capabilities, cryptoOffer); - CPPUNIT_ASSERT(negotiator->negotiate() == true); + CPPUNIT_ASSERT(negotiator.negotiate()); - CPPUNIT_ASSERT(negotiator->getCryptoSuite() == "AES_CM_128_HMAC_SHA1_80"); - CPPUNIT_ASSERT(negotiator->getKeyMethod() == "inline"); - CPPUNIT_ASSERT(negotiator->getKeyInfo() == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd"); - CPPUNIT_ASSERT(negotiator->getLifeTime() == ""); - CPPUNIT_ASSERT(negotiator->getMkiValue() == ""); - CPPUNIT_ASSERT(negotiator->getMkiLength() == ""); - CPPUNIT_ASSERT(negotiator->getAuthTagLength() == "80"); - - - delete capabilities; - capabilities = NULL; - delete cryptoOffer; - cryptoOffer = NULL; - delete negotiator; - negotiator = NULL; + CPPUNIT_ASSERT(negotiator.getCryptoSuite() == "AES_CM_128_HMAC_SHA1_80"); + CPPUNIT_ASSERT(negotiator.getKeyMethod() == "inline"); + CPPUNIT_ASSERT(negotiator.getKeyInfo() == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd"); + CPPUNIT_ASSERT(negotiator.getLifeTime().empty()); + CPPUNIT_ASSERT(negotiator.getMkiValue().empty()); + CPPUNIT_ASSERT(negotiator.getMkiLength().empty()); + CPPUNIT_ASSERT(negotiator.getAuthTagLength() == "80"); } void SdesNegotiatorTest::test32ByteKeyLength() { - DEBUG("-------------------- SdesNegotiatorTest::test32ByteKeyLength --------------------\n"); + TITLE(); // Register the local capabilities. - std::vector<sfl::CryptoSuiteDefinition> * capabilities = new std::vector<sfl::CryptoSuiteDefinition>(); + std::vector<sfl::CryptoSuiteDefinition> capabilities; //Support all the CryptoSuites - for (int i = 0; i < 3; i++) { - capabilities->push_back(sfl::CryptoSuites[i]); - } + for (int i = 0; i < 3; i++) + capabilities.push_back(sfl::CryptoSuites[i]); std::string cryptoLine("a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd"); - std::vector<std::string> * cryptoOffer = new std::vector<std::string>(); - cryptoOffer->push_back(cryptoLine); - - sfl::SdesNegotiator * negotiator = new sfl::SdesNegotiator(*capabilities, *cryptoOffer); - - CPPUNIT_ASSERT(negotiator->negotiate() == true); - - CPPUNIT_ASSERT(negotiator->getCryptoSuite() == "AES_CM_128_HMAC_SHA1_32"); - CPPUNIT_ASSERT(negotiator->getKeyMethod() == "inline"); - CPPUNIT_ASSERT(negotiator->getKeyInfo() == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd"); - CPPUNIT_ASSERT(negotiator->getLifeTime() == ""); - CPPUNIT_ASSERT(negotiator->getMkiValue() == ""); - CPPUNIT_ASSERT(negotiator->getMkiLength() == ""); - CPPUNIT_ASSERT(negotiator->getAuthTagLength() == "32"); - - delete capabilities; - capabilities = NULL; - delete cryptoOffer; - cryptoOffer = NULL; - delete negotiator; - negotiator = NULL; + std::vector<std::string> cryptoOffer; + cryptoOffer.push_back(cryptoLine); + + sfl::SdesNegotiator negotiator(capabilities, cryptoOffer); + + CPPUNIT_ASSERT(negotiator.negotiate()); + + CPPUNIT_ASSERT(negotiator.getCryptoSuite() == "AES_CM_128_HMAC_SHA1_32"); + CPPUNIT_ASSERT(negotiator.getKeyMethod() == "inline"); + CPPUNIT_ASSERT(negotiator.getKeyInfo() == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd"); + CPPUNIT_ASSERT(negotiator.getLifeTime().empty()); + CPPUNIT_ASSERT(negotiator.getMkiValue().empty()); + CPPUNIT_ASSERT(negotiator.getMkiLength().empty()); + CPPUNIT_ASSERT(negotiator.getAuthTagLength() == "32"); } diff --git a/daemon/test/sdesnegotiatortest.h b/daemon/test/sdesnegotiatortest.h index eb9bb74cde8fc360dcc456e8d70eaf0114e252c0..a634f5bde066d1c9633a5f7e7f83170fe9f777d2 100644 --- a/daemon/test/sdesnegotiatortest.h +++ b/daemon/test/sdesnegotiatortest.h @@ -80,8 +80,6 @@ class SdesNegotiatorTest : public CppUnit::TestCase { CPPUNIT_TEST_SUITE_END(); public: - - SdesNegotiatorTest(); /* * Code factoring - Common resources can be released here. * This method is called by unitcpp after each test @@ -103,14 +101,6 @@ class SdesNegotiatorTest : public CppUnit::TestCase { void testMostSimpleCase(); void test32ByteKeyLength(); - - private: - NON_COPYABLE(SdesNegotiatorTest); - - sfl::Pattern *pattern; - sfl::SdesNegotiator *sdesnego; - std::vector<std::string> *remoteOffer; - std::vector<sfl::CryptoSuiteDefinition> *localCapabilities; }; /* Register our test module */ diff --git a/daemon/test/sdptest.cpp b/daemon/test/sdptest.cpp index 046c9a219c3ed11c750723e75524271b981b5e95..d9d058b4b80a609e77d220e1261b4ca1ee2aece6 100644 --- a/daemon/test/sdptest.cpp +++ b/daemon/test/sdptest.cpp @@ -116,6 +116,12 @@ void SDPTest::tearDown() pj_pool_release(testPool_); } +void SDPTest::receiveAnswerAfterInitialOffer(const pjmedia_sdp_session* remote) +{ + assert(pjmedia_sdp_neg_get_state(session_->negotiator_) == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER); + assert(pjmedia_sdp_neg_set_remote_answer(session_->memPool_, session_->negotiator_, remote) == PJ_SUCCESS); + assert(pjmedia_sdp_neg_get_state(session_->negotiator_) == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO); +} void SDPTest::testInitialOfferFirstCodec() { @@ -141,7 +147,7 @@ void SDPTest::testInitialOfferFirstCodec() // pjmedia_sdp_parse(testPool_, test[0].offer_answer[0].sdp2, strlen(test[0].offer_answer[0].sdp2), &remoteAnswer); pjmedia_sdp_parse(testPool_, (char*)sdp_answer1, strlen(sdp_answer1), &remoteAnswer); - session_->receivingAnswerAfterInitialOffer(remoteAnswer); + receiveAnswerAfterInitialOffer(remoteAnswer); session_->startNegotiation(); session_->setMediaTransportInfoFromRemoteSdp(); @@ -213,7 +219,7 @@ void SDPTest::testInitialOfferLastCodec() // pjmedia_sdp_parse(testPool_, test[0].offer_answer[0].sdp2, strlen(test[0].offer_answer[0].sdp2), &remoteAnswer); pjmedia_sdp_parse(testPool_, (char*)sdp_answer2, strlen(sdp_answer2), &remoteAnswer); - session_->receivingAnswerAfterInitialOffer(remoteAnswer); + receiveAnswerAfterInitialOffer(remoteAnswer); session_->startNegotiation(); session_->setMediaTransportInfoFromRemoteSdp(); @@ -287,7 +293,7 @@ void SDPTest::testReinvite() // pjmedia_sdp_parse(testPool_, test[0].offer_answer[0].sdp2, strlen(test[0].offer_answer[0].sdp2), &remoteAnswer); pjmedia_sdp_parse(testPool_, (char*)sdp_answer1, strlen(sdp_answer1), &remoteAnswer); - session_->receivingAnswerAfterInitialOffer(remoteAnswer); + receiveAnswerAfterInitialOffer(remoteAnswer); session_->startNegotiation(); session_->setMediaTransportInfoFromRemoteSdp(); @@ -298,7 +304,7 @@ void SDPTest::testReinvite() CPPUNIT_ASSERT(session_->getRemoteIP() == "host.example.com"); CPPUNIT_ASSERT(session_->getSessionMedia()->getMimeSubtype() == "PCMU"); - pjmedia_sdp_parse(testPool_, (char*)sdp_reinvite, strlen(sdp_reinvite), &reinviteOffer); + pjmedia_sdp_parse(testPool_, (char*) sdp_reinvite, strlen(sdp_reinvite), &reinviteOffer); session_->receiveOffer(reinviteOffer, codecSelection); diff --git a/daemon/test/sdptest.h b/daemon/test/sdptest.h index e149f9b03aa25e434f406607b362df640a7e97b3..54b362b1f8eb0a41bdca4073f08827cc95a84fb1 100644 --- a/daemon/test/sdptest.h +++ b/daemon/test/sdptest.h @@ -118,6 +118,7 @@ class SDPTest : public CppUnit::TestCase { private: NON_COPYABLE(SDPTest); + void receiveAnswerAfterInitialOffer(const pjmedia_sdp_session* remote); Sdp *session_; pj_pool_t *testPool_; diff --git a/daemon/test/sflphoned-sample.yml b/daemon/test/sflphoned-sample.yml index 942b1541229737aa284302e7a7c0239b30c02b2f..3bac267c832a84b794e539dc90e7fa26c9550b35 100644 --- a/daemon/test/sflphoned-sample.yml +++ b/daemon/test/sflphoned-sample.yml @@ -1,5 +1,54 @@ --- accounts: +- alias: SFL test + codecs: 0/3/8/9/110/111/112/ + credential: + - Account.password: 1234 + Account.realm: + Account.username: sfltest + displayName: + dtmfType: overrtp + enable: false + hostname: localhost + id: Account:1334389473 + interface: default + mailbox: + port: 5060 + publishAddr: 0.0.0.0 + publishPort: 5060 + registrationexpire: 600 + ringtoneEnabled: true + ringtonePath: /usr/share/sflphone/ringtones/konga.ul + sameasLocal: true + serviceRoute: + srtp: + enable: false + keyExchange: + rtpFallback: false + stunEnabled: false + stunServer: stun.sflphone.org + tls: + calist: + certificate: + ciphers: + enable: false + method: TLSv1 + password: + privateKey: + requireCertif: true + server: + timeout: 2 + tlsPort: 5061 + verifyClient: true + verifyServer: true + type: SIP + updateContact: false + username: sfltest + zrtp: + displaySas: true + displaySasOnce: false + helloHashEnabled: true + notSuppWarning: true - alias: codecs: 0/ credential: diff --git a/daemon/test/siptest.cpp b/daemon/test/siptest.cpp index 06b8f7bf4dfcd0f747f8799a01da96755c4cb8dc..f11699748b47816b614d652aa9a19a0cd2a5fdd2 100644 --- a/daemon/test/siptest.cpp +++ b/daemon/test/siptest.cpp @@ -125,7 +125,7 @@ void SIPTest::testSimpleOutgoingIpCall() pthread_t thethread; // command to be executed by the thread, user agent server waiting for a call - std::string command("sipp -sn uas -i 127.0.0.1 -p 5062 -m 1 -bg"); + std::string command("sipp -sn uas -i 127.0.0.1 -p 5068 -m 1 -bg"); int rc = pthread_create(&thethread, NULL, sippThread, &command); @@ -134,7 +134,7 @@ void SIPTest::testSimpleOutgoingIpCall() std::string testaccount("IP2IP"); std::string testcallid("callid1234"); - std::string testcallnumber("sip:test@127.0.0.1:5062"); + std::string testcallnumber("sip:test@127.0.0.1:5068"); CPPUNIT_ASSERT(!Manager::instance().hasCurrentCall()); @@ -144,9 +144,6 @@ void SIPTest::testSimpleOutgoingIpCall() // must sleep here until receiving 180 and 200 message from peer sleep(2); - // call list should be empty for outgoing calls, only used for incoming calls - CPPUNIT_ASSERT(Manager::instance().getCallList().empty()); - CPPUNIT_ASSERT(Manager::instance().hasCurrentCall()); CPPUNIT_ASSERT(Manager::instance().getCurrentCallId() == testcallid); @@ -184,9 +181,6 @@ void SIPTest::testSimpleIncomingIpCall() CallMap::iterator iterCallId = siplink->callMap_.begin(); std::string testcallid = iterCallId->first; - // TODO: hmmm, should IP2IP call be stored in call list.... - CPPUNIT_ASSERT(Manager::instance().getCallList().size() == 0); - // Answer this call CPPUNIT_ASSERT(Manager::instance().answerCall(testcallid)); diff --git a/daemon/test/siptest.h b/daemon/test/siptest.h index 0e11f4415803612adc6d1718bbbca1ce9c2eddcb..3b5152bdfe24f955bff33c3d616d293daca676ba 100644 --- a/daemon/test/siptest.h +++ b/daemon/test/siptest.h @@ -34,8 +34,6 @@ #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include <assert.h> - // Application import #include "manager.h" diff --git a/daemon/test/test_utils.h b/daemon/test/test_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..0a249c40a09264a359df1627297993a8113cbfb0 --- /dev/null +++ b/daemon/test/test_utils.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef TEST_UTILS_H_ +#define TEST_UTILS_H_ + +#define TITLE() DEBUG("Starting test..."); fflush(stderr) + +#endif // TEST_UTILS_H_ diff --git a/gnome/.gitignore b/gnome/.gitignore index 062344668bf4748809802cfae31ff6e42fbc1fc3..f6e3821328b639b709f4b2e0b6c03bd6d72a355b 100644 --- a/gnome/.gitignore +++ b/gnome/.gitignore @@ -1,3 +1,5 @@ +m4 +aclocal.m4 config.* configure depcomp diff --git a/gnome/INSTALL b/gnome/INSTALL deleted file mode 100644 index 7d1c323beae76333f523f6df31c47a87f5597edb..0000000000000000000000000000000000000000 --- a/gnome/INSTALL +++ /dev/null @@ -1,365 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006, 2007, 2008, 2009 Free Software Foundation, Inc. - - Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. This file is offered as-is, -without warranty of any kind. - -Basic Installation -================== - - Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. Some packages provide this -`INSTALL' file but do not implement all of the features documented -below. The lack of an optional feature in a given package is not -necessarily a bug. More recommendations for GNU packages can be found -in *note Makefile Conventions: (standards)Makefile Conventions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - - The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package, generally using the just-built uninstalled binaries. - - 4. Type `make install' to install the programs and any data files and - documentation. When installing into a prefix owned by root, it is - recommended that the package be configured and built as a regular - user, and only the `make install' phase executed with root - privileges. - - 5. Optionally, type `make installcheck' to repeat any self-tests, but - this time using the binaries in their final installed location. - This target does not install anything. Running this target as a - regular user, particularly if the prior `make install' required - root privileges, verifies that the installation completed - correctly. - - 6. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 7. Often, you can also type `make uninstall' to remove the installed - files again. In practice, not all packages have tested that - uninstallation works correctly, even though it is required by the - GNU Coding Standards. - - 8. Some packages, particularly those that use Automake, provide `make - distcheck', which can by used by developers to test that all other - targets like `make install' and `make uninstall' work correctly. - This target is generally not run by end users. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. This -is known as a "VPATH" build. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. - -Installation Names -================== - - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX', where PREFIX must be an -absolute file name. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of `${prefix}', so that -specifying just `--prefix' will affect all of the other directory -specifications that were not explicitly provided. - - The most portable way to affect installation locations is to pass the -correct locations to `configure'; however, many packages provide one or -both of the following shortcuts of passing variable assignments to the -`make install' command line to change installation locations without -having to reconfigure or recompile. - - The first method involves providing an override variable for each -affected directory. For example, `make install -prefix=/alternate/directory' will choose an alternate location for all -directory configuration variables that were expressed in terms of -`${prefix}'. Any directories that were specified during `configure', -but not in terms of `${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. - - The second method involves providing the `DESTDIR' variable. For -example, `make install DESTDIR=/alternate/directory' will prepend -`/alternate/directory' before all installation names. The approach of -`DESTDIR' overrides is not required by the GNU Coding Standards, and -does not work on platforms that have drive letters. On the other hand, -it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of `${prefix}' -at `configure' time. - -Optional Features -================= - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - - Some packages offer the ability to configure how verbose the -execution of `make' will be. For these packages, running `./configure ---enable-silent-rules' sets the default to minimal output, which can be -overridden with `make V=1'; while running `./configure ---disable-silent-rules' sets the default to verbose, which can be -overridden with `make V=0'. - -Particular systems -================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: - - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" - -and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `<wchar.h>' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try - - ./configure CC="cc" - -and if that doesn't work, try - - ./configure CC="cc -nodtk" - - On Solaris, don't put `/usr/ucb' early in your `PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. - - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: - - ./configure --prefix=/boot/common - -Specifying the System Type -========================== - - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS - KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - - `configure' recognizes the following options to control how it -operates. - -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. - -`--help=short' -`--help=recursive' - Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - -`--no-create' -`-n' - Run the configure checks, but stop before creating any output - files. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/gnome/configure.ac b/gnome/configure.ac index 7c659e7837009b5dc6449406d3618ae770a6d963..820bdd500fa26b8b453cbe8babe1be983185e028 100644 --- a/gnome/configure.ac +++ b/gnome/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([sflphone],[1.0.2],[sflphoneteam@savoirfairelinux.com],[sflphone-client-gnome]) +AC_INIT([sflphone],[1.1.0],[sflphoneteam@savoirfairelinux.com],[sflphone-client-gnome]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE @@ -15,9 +15,7 @@ AC_PROG_INSTALL AC_HEADER_STDC LT_INIT -dnl Only need these for moving to gtk3 -MIGRATION_CFLAGS="-DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGTK_DISABLE_SINGLE_INCLUDES" -CFLAGS="$CFLAGS -g -Wall -Wextra -Wshadow $MIGRATION_CFLAGS" +CFLAGS="$CFLAGS -Wall -Wextra -Wshadow" dnl GCONF utilities AM_GCONF_SOURCE_2 @@ -32,12 +30,22 @@ if echo "$LIBNOTIFY_LIBS" | grep -q gtk+-x11-2.0; then AC_MSG_ERROR([Your libnotify is linked with GTK+2 ! Install libnotify4-dev]) exit 1 fi -PKG_CHECK_MODULES(GTK, gtk+-3.0) + +# Check for gtk+-3.0 and if found, check for webkitgtk-3.0, otherwise +# check for gtk+-2.0 and if found, check for webkitgtk-1.0. +PKG_CHECK_MODULES(GTK, gtk+-3.0, [PKG_CHECK_MODULES(WEBKIT, webkitgtk-3.0)], + [PKG_CHECK_MODULES(GTK, gtk+-2.0, + [PKG_CHECK_MODULES(WEBKIT, webkit-1.0) && PKG_CHECK_MODULES(GTHREAD, gthread-2.0)], + [AC_MSG_ERROR(gtk-2 not found)])]) + PKG_CHECK_MODULES(GCONF, gconf-2.0) PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.24) -PKG_CHECK_MODULES(WEBKIT, webkitgtk-3.0) +PKG_CHECK_MODULES(X11, x11) +PKG_CHECK_MODULES(JAVASCRIPT_CORE_GTK, javascriptcoregtk-3.0, , + AC_MSG_RESULT(javascriptcoregtk not installed)) -PKG_CHECK_MODULES([CHECK], [check >= 0.9.4]) +PKG_CHECK_MODULES([CHECK], [check >= 0.9.4],, + AC_MSG_RESULT([check not installed])) AC_CONFIG_FILES([ Makefile diff --git a/gnome/src/Makefile.am b/gnome/src/Makefile.am index 3e673bfde457f4c7e9c3e8d994d6b346abc26040..4c0107eab596d368f56c63488a53b0de51b8ad9b 100644 --- a/gnome/src/Makefile.am +++ b/gnome/src/Makefile.am @@ -5,10 +5,10 @@ bin_PROGRAMS = sflphone-client-gnome SUBDIRS = config contacts dbus widget icons NOFIFY_LIBS = -lnotify -X11_LIBS = -lX11 LD_LIBS = -ldl -SFLPHONEGTK_LIBS=./contacts/libcontacts.la ./config/libconfig.la ./dbus/libdbus.la ./widget/libwidget.la ./icons/libicons.la +SFLPHONEGTK_LIBS=./contacts/libcontacts.la ./config/libconfig.la \ + ./dbus/libdbus.la ./widget/libwidget.la ./icons/libicons.la sflphone_client_gnome_SOURCES = \ main.c \ @@ -27,18 +27,27 @@ sflphone_client_gnome_SOURCES = \ codeclist.c \ reqaccount.c \ eel-gconf-extensions.c \ - shortcuts.c + shortcuts.c \ + str_utils.c \ + gtk2_wrappers.c noinst_HEADERS = actions.h sflnotify.h mainwindow.h dialpad.h codeclist.h \ - reqaccount.h sflphone_const.h uimanager.h \ - accountlist.h sliders.h statusicon.h callable_obj.h conference_obj.h \ - shortcuts.h eel-gconf-extensions.h logger.h imwindow.h unused.h - -sflphone_client_gnome_LDADD = $(DBUSGLIB_LIBS) $(LIBNOTIFY_LIBS) $(NOTIFY_LIBS) $(SFLPHONEGTK_LIBS) $(X11_LIBS) \ - $(GTK_LIBS) $(GLIB_LIBS) $(WEBKIT_LIBS) $(LD_LIBS) $(GCONF_LIBS) - -sflphone_client_gnome_CFLAGS = $(DBUSGLIB_CFLAGS) $(LIBNOTIFY_CFLAGS) $(NOTIFY_CFLAGS) $(GTK_CFLAGS) $(X11_CFLAGS) \ - $(GLIB_CFLAGS) $(WEBKIT_CFLAGS) $(GCONF_CFLAGS) + reqaccount.h sflphone_const.h uimanager.h accountlist.h \ + sliders.h statusicon.h callable_obj.h conference_obj.h \ + shortcuts.h eel-gconf-extensions.h logger.h imwindow.h \ + unused.h str_utils.h gtk2_wrappers.h + +sflphone_client_gnome_LDADD = $(DBUSGLIB_LIBS) $(LIBNOTIFY_LIBS) \ + $(NOTIFY_LIBS) $(SFLPHONEGTK_LIBS) $(X11_LIBS) \ + $(GTK_LIBS) $(GLIB_LIBS) $(WEBKIT_LIBS) \ + $(LD_LIBS) $(GCONF_LIBS) \ + $(JAVASCRIPT_CORE_GTK_LIBS) $(GTHREAD_LIBS) + +sflphone_client_gnome_CFLAGS = $(DBUSGLIB_CFLAGS) $(LIBNOTIFY_CFLAGS) \ + $(NOTIFY_CFLAGS) $(GTK_CFLAGS) $(X11_CFLAGS) \ + $(GLIB_CFLAGS) $(WEBKIT_CFLAGS) \ + $(GCONF_CFLAGS) $(JAVASCRIPT_CORE_GTK_CFLAGS) \ + $(GTHREAD_CFLAGS) # add symbolic link install-exec-local: diff --git a/gnome/src/accountlist.c b/gnome/src/accountlist.c index 662c7bc8729bbfb53cf32df66501c91944844eaf..c0356736d1789172af495ae1548b39201a97eae7 100644 --- a/gnome/src/accountlist.c +++ b/gnome/src/accountlist.c @@ -29,7 +29,11 @@ * as that of the covered work. */ +#include <glib/gi18n.h> +#include "str_utils.h" +#include "dbus.h" #include "accountlist.h" +#include "logger.h" #include "actions.h" #include "unused.h" @@ -42,7 +46,7 @@ static guint account_list_get_position(account_t *account) for (guint i = 0; i < size; i++) { account_t *tmp = account_list_get_nth(i); - if (g_strcasecmp(tmp->accountID, account->accountID) == 0) + if (utf8_case_equal(tmp->accountID, account->accountID)) return i; } @@ -50,7 +54,6 @@ static guint account_list_get_position(account_t *account) return -1; } - /* GCompareFunc to compare a accountID (gchar* and a account_t) */ static gint is_accountID_struct(gconstpointer a, gconstpointer b) { @@ -73,6 +76,7 @@ static gint get_state_struct(gconstpointer a, gconstpointer b) void account_list_init() { + account_list_free(); accountQueue = g_queue_new(); } @@ -96,6 +100,7 @@ account_list_get_by_state(account_state_t state) account_t * account_list_get_by_id(const gchar * const accountID) { + g_assert(accountID); GList * c = g_queue_find_custom(accountQueue, accountID, is_accountID_struct); if (c) @@ -123,9 +128,7 @@ account_list_get_current() // if we are here, it means that we have at least one registered account in the list // So we get the first one - account_t *current = account_list_get_by_state(ACCOUNT_STATE_REGISTERED); - - return current; + return account_list_get_by_state(ACCOUNT_STATE_REGISTERED); } void account_list_set_current(account_t *current) @@ -144,58 +147,47 @@ void account_list_set_current(account_t *current) const gchar * account_state_name(account_state_t s) { - gchar * state; - switch (s) { case ACCOUNT_STATE_REGISTERED: - state = _("Registered"); - break; + return _("Registered"); case ACCOUNT_STATE_UNREGISTERED: - state = _("Not Registered"); - break; + return _("Not Registered"); case ACCOUNT_STATE_TRYING: - state = _("Trying..."); - break; + return _("Trying..."); case ACCOUNT_STATE_ERROR: - state = _("Error"); - break; + return _("Error"); case ACCOUNT_STATE_ERROR_AUTH: - state = _("Authentication Failed"); - break; + return _("Authentication Failed"); case ACCOUNT_STATE_ERROR_NETWORK: - state = _("Network unreachable"); - break; + return _("Network unreachable"); case ACCOUNT_STATE_ERROR_HOST: - state = _("Host unreachable"); - break; - case ACCOUNT_STATE_ERROR_CONF_STUN: - state = _("Stun configuration error"); - break; + return _("Host unreachable"); + case ACCOUNT_STATE_ERROR_NOT_ACCEPTABLE: + return _("Not acceptable"); case ACCOUNT_STATE_ERROR_EXIST_STUN: - state = _("Stun server invalid"); - break; - case IP2IP_PROFILE_STATUS: - state = _("Ready"); - break; + return _("Stun server invalid"); + case ACCOUNT_STATE_IP2IP_READY: + return _("Ready"); default: - state = _("Invalid"); - break; + return _("Invalid"); } - - return state; } void account_list_free_elm(gpointer elm, gpointer data UNUSED) { account_t *a = elm; g_free(a->accountID); + a->accountID = NULL; g_free(a); } void account_list_free() { - g_queue_foreach(accountQueue, account_list_free_elm, NULL); - g_queue_free(accountQueue); + if (accountQueue) { + g_queue_foreach(accountQueue, account_list_free_elm, NULL); + g_queue_free(accountQueue); + accountQueue = NULL; + } } void @@ -222,20 +214,34 @@ account_list_get_registered_accounts(void) guint res = 0; for (guint i = 0; i < account_list_get_size(); i++) - if (account_list_get_nth(i) -> state == (ACCOUNT_STATE_REGISTERED)) + if (account_list_get_nth(i)->state == (ACCOUNT_STATE_REGISTERED)) res++; return res; } -gchar* account_list_get_current_id(void) +const gchar* account_list_get_current_id(void) { account_t *current = account_list_get_current(); if (current) return current->accountID; else - return ""; + return NULL; +} + +void account_list_remove(const gchar *accountID) +{ + account_t *target = account_list_get_by_id(accountID); + if (target) { +#if GLIB_CHECK_VERSION(2, 30, 0) + if (!g_queue_remove(accountQueue, target)) + ERROR("Could not remove account with ID %s", accountID); +#else + g_queue_remove(accountQueue, target); +#endif + } + } gchar * account_list_get_ordered_list(void) @@ -243,10 +249,8 @@ gchar * account_list_get_ordered_list(void) gchar *order = strdup(""); for (guint i = 0; i < account_list_get_size(); i++) { - account_t * account = NULL; - account = account_list_get_nth(i); - - if (account != NULL) { + account_t * account = account_list_get_nth(i); + if (account) { gchar *new_order = g_strconcat(order, account->accountID, "/", NULL); g_free(order); order = new_order; @@ -263,9 +267,9 @@ gboolean current_account_has_mailbox(void) account_t *current = account_list_get_current(); if (current) { - gchar * account_mailbox = g_hash_table_lookup(current->properties, ACCOUNT_MAILBOX); + gchar * account_mailbox = account_lookup(current, ACCOUNT_MAILBOX); - if (account_mailbox && g_strcasecmp(account_mailbox, "") != 0) + if (account_mailbox && !utf8_case_equal(account_mailbox, "")) return TRUE; } @@ -275,7 +279,6 @@ gboolean current_account_has_mailbox(void) void current_account_set_message_number(guint nb) { account_t *current = account_list_get_current(); - if (current) current->_messages_number = nb; } @@ -283,7 +286,6 @@ void current_account_set_message_number(guint nb) guint current_account_get_message_number(void) { account_t *current = account_list_get_current(); - if (current) return current->_messages_number; else @@ -293,9 +295,77 @@ guint current_account_get_message_number(void) gboolean current_account_has_new_message(void) { account_t *current = account_list_get_current(); + return current && current->_messages_number > 0; +} - if (current) - return (current->_messages_number > 0); +gboolean account_is_IP2IP(const account_t *account) +{ + g_assert(account); + return g_strcmp0(account->accountID, IP2IP_PROFILE) == 0; +} - return FALSE; +static gboolean is_type(const account_t *account, const gchar *type) +{ + const gchar *account_type = account_lookup(account, ACCOUNT_TYPE); + return g_strcmp0(account_type, type) == 0; +} + +gboolean account_is_SIP(const account_t *account) +{ + return is_type(account, "SIP"); +} + +gboolean account_is_IAX(const account_t *account) +{ + return is_type(account, "IAX"); +} + +account_t *create_default_account() +{ + account_t *account = g_new0(account_t, 1); + account->accountID = g_strdup("new"); // FIXME: maybe replace with NULL? + account->properties = dbus_get_account_details(""); + sflphone_fill_codec_list_per_account(account); + initialize_credential_information(account); + return account; +} + +account_t *create_account_with_ID(const gchar *ID) +{ + account_t *account = g_new0(account_t, 1); + account->accountID = g_strdup(ID); + account->properties = dbus_get_account_details(ID); + sflphone_fill_codec_list_per_account(account); + initialize_credential_information(account); + return account; +} + +void initialize_credential_information(account_t *account) +{ + if (!account->credential_information) { + account->credential_information = g_ptr_array_sized_new(1); + GHashTable * new_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + g_hash_table_insert(new_table, g_strdup(ACCOUNT_REALM), g_strdup("*")); + g_hash_table_insert(new_table, g_strdup(ACCOUNT_USERNAME), g_strdup("")); + g_hash_table_insert(new_table, g_strdup(ACCOUNT_PASSWORD), g_strdup("")); + g_ptr_array_add(account->credential_information, new_table); + } +} + +void account_replace(account_t *account, const gchar *key, const gchar *value) +{ + g_assert(account && account->properties); + g_hash_table_replace(account->properties, g_strdup(key), g_strdup(value)); +} + +void account_insert(account_t *account, const gchar *key, const gchar *value) +{ + g_assert(account && account->properties); + g_hash_table_insert(account->properties, g_strdup(key), g_strdup(value)); +} + +gpointer account_lookup(const account_t *account, gconstpointer key) +{ + g_assert(account && account->properties); + return g_hash_table_lookup(account->properties, key); } diff --git a/gnome/src/accountlist.h b/gnome/src/accountlist.h index 559bb4a030dd625489b1b9194f39f4cc63fb3476..59b0fb32eb780edf75cbca7e97158c8385b6674c 100644 --- a/gnome/src/accountlist.h +++ b/gnome/src/accountlist.h @@ -29,8 +29,8 @@ * as that of the covered work. */ -#ifndef __ACCOUNTLIST_H__ -#define __ACCOUNTLIST_H__ +#ifndef ACCOUNTLIST_H_ +#define ACCOUNTLIST_H_ #include <gtk/gtk.h> /** @file accountlist.h @@ -41,14 +41,12 @@ * This enum have all the states an account can take. */ typedef enum { - /** Invalid state */ - ACCOUNT_STATE_INVALID = 0, - /** The account is registered */ - ACCOUNT_STATE_REGISTERED, /** The account is not registered */ ACCOUNT_STATE_UNREGISTERED, /** The account is trying to register */ ACCOUNT_STATE_TRYING, + /** The account is registered */ + ACCOUNT_STATE_REGISTERED, /** Error state. The account is not registered */ ACCOUNT_STATE_ERROR, /** An authentification error occured. Wrong password or wrong username. The account is not registered */ @@ -57,12 +55,14 @@ typedef enum { ACCOUNT_STATE_ERROR_NETWORK, /** Host is unreachable. The account is not registered */ ACCOUNT_STATE_ERROR_HOST, - /** Stun server configuration error. The account is not registered */ - ACCOUNT_STATE_ERROR_CONF_STUN, /** Stun server is not existing. The account is not registered */ ACCOUNT_STATE_ERROR_EXIST_STUN, - /** IP profile status **/ - IP2IP_PROFILE_STATUS + /** Stun server configuration error. The account is not registered */ + ACCOUNT_STATE_ERROR_NOT_ACCEPTABLE, + /** IP2IP Account is always ready */ + ACCOUNT_STATE_IP2IP_READY, + /** Invalid state */ + ACCOUNT_STATE_INVALID } account_state_t; /** @struct account_t @@ -91,20 +91,20 @@ typedef struct { /** * This function initialize the account list. */ -void account_list_init (); +void account_list_init(); /** * This function append an account to list. * @param a The account you want to add */ -void account_list_add (account_t * a); +void account_list_add(account_t * a); /** * Return the first account that corresponds to the state * @param state The state * @return account_t* An account or NULL */ -account_t * account_list_get_by_state (account_state_t state); +account_t * account_list_get_by_state(account_state_t state); /** * @return guint The number of registered accounts in the list @@ -115,14 +115,14 @@ guint account_list_get_registered_accounts(); * Return the number of accounts in the list * @return guint The number of accounts in the list */ -guint account_list_get_size (); +guint account_list_get_size(); /** * Return the account at the nth position in the list * @param n The position of the account you want * @return An account or NULL */ -account_t * account_list_get_nth (guint n); +account_t * account_list_get_nth(guint n); /** * Return the current account struct @@ -134,53 +134,67 @@ account_t * account_list_get_current(); * This function sets an account as the current one * @param current the account you want to set as current */ -void account_list_set_current (account_t *current); +void account_list_set_current(account_t *current); /** * This function maps account_state_t enums to a description. * @param s The state * @return The full text description of the state */ -const gchar * account_state_name (account_state_t s); +const gchar * account_state_name(account_state_t s); /** * This function frees the list */ -void account_list_free (); +void account_list_free(); /** * Return the account associated with an ID * @param accountID The ID of the account * @return An account or NULL */ -account_t * account_list_get_by_id (const gchar * const accountID); +account_t * account_list_get_by_id(const gchar * const accountID); /** * Move the account from an unit up in the account_list * @param index The current index in the list */ -void account_list_move_up (guint index); +void account_list_move_up(guint index); /** * Move the account from an unit down in the account_list * @param index The current index in the list */ -void account_list_move_down (guint index); +void account_list_move_down(guint index); /** * Return the ID of the current default account * @return gchar* The id */ -gchar* account_list_get_current_id (void); +const gchar* account_list_get_current_id(void); + +gchar * account_list_get_ordered_list(void); + +gboolean current_account_has_mailbox(void); + +guint current_account_get_message_number(void); + +void current_account_set_message_number(guint nb); -gchar * account_list_get_ordered_list (void); +gboolean current_account_has_new_message(void); -gboolean current_account_has_mailbox (void); +gboolean account_is_IP2IP(const account_t *account); +gboolean account_is_SIP(const account_t *account); +gboolean account_is_IAX(const account_t *account); -guint current_account_get_message_number (void); +account_t *create_default_account(); +account_t *create_account_with_ID(const gchar *ID); -void current_account_set_message_number (guint nb); +void initialize_credential_information(account_t *account); -gboolean current_account_has_new_message (void); +void account_replace(account_t *account, const gchar *key, const gchar *value); +void account_insert(account_t *account, const gchar *key, const gchar *value); +gpointer account_lookup(const account_t *account, gconstpointer key); +void account_list_remove(const gchar *accountID); -#endif +#endif // ACCOUNTLIST_H_ diff --git a/gnome/src/actions.c b/gnome/src/actions.c index 17233fba91206a1e3c1b802e78915f93a834dbf7..d3bee67268bdb927cfc0558d55b5256fd69d1615 100644 --- a/gnome/src/actions.c +++ b/gnome/src/actions.c @@ -29,6 +29,7 @@ * as that of the covered work. */ +#include <glib/gi18n.h> #include <gtk/gtk.h> /* Backward compatibility for gtk < 2.22.0 */ #if GTK_CHECK_VERSION(2,22,0) @@ -36,7 +37,9 @@ #else #include <gdk/gdkkeysyms.h> #endif -#include <glib/gprintf.h> + +#include "str_utils.h" +#include <glib.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> @@ -62,6 +65,7 @@ #include "statusicon.h" #include "unused.h" #include "widget/imwidget.h" +#include "sliders.h" static GHashTable * ip2ip_profile; @@ -74,7 +78,8 @@ sflphone_notify_voice_mail(const gchar* accountID , guint count) DEBUG("sflphone_notify_voice_mail begin"); - if (g_ascii_strcasecmp(id, current_id) != 0 || account_list_get_size() == 0) + if (g_ascii_strcasecmp(id, current_id) != 0 || + account_list_get_size() == 0) return; // Set the number of voice messages for the current account @@ -99,7 +104,7 @@ sflphone_notify_voice_mail(const gchar* accountID , guint count) static gboolean is_direct_call(callable_obj_t * c) { - if (g_strcasecmp(c->_accountID, "empty") == 0) { + if (utf8_case_equal(c->_accountID, "empty")) { if (!g_str_has_prefix(c->_peer_number, "sip:")) { gchar * new_number = g_strconcat("sip:", c->_peer_number, NULL); g_free(c->_peer_number); @@ -117,18 +122,17 @@ static gboolean is_direct_call(callable_obj_t * c) void status_bar_display_account() { - gchar* msg; - statusbar_pop_message(__MSG_ACCOUNT_DEFAULT); account_t *acc = account_list_get_current(); status_tray_icon_online(acc != NULL); + gchar* msg; if (acc) { msg = g_markup_printf_escaped("%s %s (%s)" , _("Using account"), - (gchar*) g_hash_table_lookup(acc->properties, ACCOUNT_ALIAS), - (gchar*) g_hash_table_lookup(acc->properties, ACCOUNT_TYPE)); + (gchar*) account_lookup(acc, ACCOUNT_ALIAS), + (gchar*) account_lookup(acc, ACCOUNT_TYPE)); } else { msg = g_markup_printf_escaped(_("No registered accounts")); } @@ -148,9 +152,6 @@ sflphone_quit() calllist_clean(current_calls_tab); calllist_clean(contacts_tab); calllist_clean(history_tab); - gtk_tree_store_clear(history_tab->store); - gtk_tree_store_clear(current_calls_tab->store); - gtk_tree_store_clear(contacts_tab->store); gtk_main_quit(); } } @@ -174,19 +175,14 @@ sflphone_ringing(callable_obj_t * c) void sflphone_hung_up(callable_obj_t * c) { - DEBUG("SFLphone: Hung up"); + DEBUG("%s", __PRETTY_FUNCTION__); calllist_remove_call(current_calls_tab, c->_callID); - calltree_remove_call(current_calls_tab, c); + calltree_remove_call(current_calls_tab, c->_callID); c->_state = CALL_STATE_DIALING; call_remove_all_errors(c); update_actions(); - if (c->_confID) { - g_free(c->_confID); - c->_confID = NULL; - } - // test whether the widget contains text, if not remove it if ((im_window_get_nb_tabs() > 1) && c->_im_widget && !(IM_WIDGET(c->_im_widget)->containText)) im_window_remove_tab(c->_im_widget); @@ -198,85 +194,56 @@ sflphone_hung_up(callable_obj_t * c) statusbar_update_clock(""); } -/** Internal to actions: Fill account list */ void sflphone_fill_account_list(void) { - int count = current_account_get_message_number(); - - account_list_free(); account_list_init(); - gchar **array = dbus_account_list(); - if (array) { - for (gchar **accountID = array; accountID && *accountID; accountID++) { - account_t * a = g_new0(account_t, 1); - a->accountID = g_strdup(*accountID); - a->credential_information = NULL; - account_list_add(a); - } - - g_strfreev(array); - } - - for (unsigned i = 0; i < account_list_get_size(); i++) { - account_t * a = account_list_get_nth(i); - - if (a == NULL) { - ERROR("SFLphone: Error: Could not find account %d in list", i); - break; - } - - GHashTable * details = (GHashTable *) dbus_get_account_details(a->accountID); - - if (details == NULL) { - ERROR("SFLphone: Error: Could not fetch detais for account %s", a->accountID); + for (gchar **accountID = array; accountID && *accountID; ++accountID) { + account_t *acc = create_account_with_ID(*accountID); + if (acc->properties == NULL) { + ERROR("SFLphone: Error: Could not fetch details for account %s", + accountID); break; } - - a->properties = details; - + account_list_add(acc); /* Fill the actual array of credentials */ - dbus_get_credentials(a); - - gchar * status = g_hash_table_lookup(details, REGISTRATION_STATUS); + dbus_get_credentials(acc); + gchar * status = account_lookup(acc, ACCOUNT_REGISTRATION_STATUS); if (g_strcmp0(status, "REGISTERED") == 0) - a->state = ACCOUNT_STATE_REGISTERED; + acc->state = ACCOUNT_STATE_REGISTERED; else if (g_strcmp0(status, "UNREGISTERED") == 0) - a->state = ACCOUNT_STATE_UNREGISTERED; + acc->state = ACCOUNT_STATE_UNREGISTERED; else if (g_strcmp0(status, "TRYING") == 0) - a->state = ACCOUNT_STATE_TRYING; + acc->state = ACCOUNT_STATE_TRYING; else if (g_strcmp0(status, "ERROR") == 0) - a->state = ACCOUNT_STATE_ERROR; - else if (g_strcmp0(status , "ERROR_AUTH") == 0) - a->state = ACCOUNT_STATE_ERROR_AUTH; - else if (g_strcmp0(status , "ERROR_NETWORK") == 0) - a->state = ACCOUNT_STATE_ERROR_NETWORK; - else if (g_strcmp0(status , "ERROR_HOST") == 0) - a->state = ACCOUNT_STATE_ERROR_HOST; - else if (g_strcmp0(status , "ERROR_CONF_STUN") == 0) - a->state = ACCOUNT_STATE_ERROR_CONF_STUN; - else if (g_strcmp0(status , "ERROR_EXIST_STUN") == 0) - a->state = ACCOUNT_STATE_ERROR_EXIST_STUN; - else if (g_strcmp0(status, "READY") == 0) - a->state = IP2IP_PROFILE_STATUS; + acc->state = ACCOUNT_STATE_ERROR; + else if (g_strcmp0(status, "ERROR_AUTH") == 0) + acc->state = ACCOUNT_STATE_ERROR_AUTH; + else if (g_strcmp0(status, "ERROR_NETWORK") == 0) + acc->state = ACCOUNT_STATE_ERROR_NETWORK; + else if (g_strcmp0(status, "ERROR_HOST") == 0) + acc->state = ACCOUNT_STATE_ERROR_HOST; + else if (g_strcmp0(status, "ERROR_NOT_ACCEPTABLE") == 0) + acc->state = ACCOUNT_STATE_ERROR_NOT_ACCEPTABLE; + else if (g_strcmp0(status, "ERROR_EXIST_STUN") == 0) + acc->state = ACCOUNT_STATE_ERROR_EXIST_STUN; + else if (g_strcmp0(status, "ACCOUNT_STATE_IP2IP_READY") == 0) + acc->state = ACCOUNT_STATE_IP2IP_READY; else - a->state = ACCOUNT_STATE_INVALID; - - gchar * code = g_hash_table_lookup(details, REGISTRATION_STATE_CODE); + acc->state = ACCOUNT_STATE_INVALID; + gchar * code = account_lookup(acc, ACCOUNT_REGISTRATION_STATE_CODE); if (code != NULL) - a->protocol_state_code = atoi(code); - - g_free(a->protocol_state_description); - a->protocol_state_description = g_hash_table_lookup(details, REGISTRATION_STATE_DESCRIPTION); + acc->protocol_state_code = atoi(code); + acc->protocol_state_description = account_lookup(acc, ACCOUNT_REGISTRATION_STATE_DESC); } - // Set the current account message number - current_account_set_message_number(count); + g_strfreev(array); - sflphone_fill_codec_list(); + // Set the current account message number + current_account_set_message_number(current_account_get_message_number()); } gboolean sflphone_init(GError **error) @@ -293,7 +260,6 @@ gboolean sflphone_init(GError **error) contacts_tab = calltab_init(TRUE, CONTACTS); history_tab = calltab_init(TRUE, HISTORY); - account_list_init(); codec_capabilities_load(); conferencelist_init(current_calls_tab); @@ -303,9 +269,6 @@ gboolean sflphone_init(GError **error) // Fetch the ip2ip profile sflphone_fill_ip2ip_profile(); - // Fetch the conference list - sflphone_fill_conference_list(); - return TRUE; } @@ -325,7 +288,7 @@ sflphone_hang_up() callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab); conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab); - DEBUG("SFLphone: Hang up"); + DEBUG("%s", __PRETTY_FUNCTION__); if (selectedConf) { im_widget_update_state(IM_WIDGET(selectedConf->_im_widget), FALSE); @@ -378,6 +341,11 @@ sflphone_hang_up() calltree_update_call(history_tab, selectedCall); statusbar_update_clock(""); + + // Allow screen saver to start + guint nbcall = calllist_get_size(current_calls_tab); + if(nbcall == 1) + dbus_screensaver_uninhibit(); } void @@ -385,6 +353,11 @@ sflphone_pick_up() { callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab); + // Disable screensaver if the list is empty call + guint nbcall = calllist_get_size(current_calls_tab); + if(nbcall == 0) + dbus_screensaver_inhibit(); + if (!selectedCall) { sflphone_new_call(); return; @@ -414,7 +387,8 @@ sflphone_pick_up() case CALL_STATE_TRANSFER: dbus_transfer(selectedCall); time(&selectedCall->_time_stop); - calltree_remove_call(current_calls_tab, selectedCall); + calltree_remove_call(current_calls_tab, selectedCall->_callID); + update_actions(); calllist_remove_call(current_calls_tab, selectedCall->_callID); break; case CALL_STATE_CURRENT: @@ -452,7 +426,7 @@ sflphone_on_hold() void sflphone_off_hold() { - DEBUG("sflphone_off_hold"); + DEBUG("%s", __PRETTY_FUNCTION__); callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab); conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab); @@ -627,10 +601,19 @@ process_dialing(callable_obj_t *c, guint keyval, gchar *key) callable_obj_t * sflphone_new_call() { + // Disable screensaver if the list is empty call + guint nbcall = calllist_get_size(current_calls_tab); + if(nbcall == 0) + dbus_screensaver_inhibit(); + callable_obj_t *current_selected_call = calltab_get_selected_call(current_calls_tab); - if ((current_selected_call != NULL) && (current_selected_call->_confID == NULL)) - sflphone_on_hold(); + if (current_selected_call != NULL) { + gchar *confID = dbus_get_conference_id(current_selected_call->_callID); + if(g_strcmp0(confID, "") != 0) { + sflphone_on_hold(); + } + } // Play a tone when creating a new call if (calllist_get_size(current_calls_tab) == 0) @@ -708,7 +691,8 @@ sflphone_keypad(guint keyval, gchar * key) case GDK_KP_Enter: dbus_transfer(c); time(&c->_time_stop); - calltree_remove_call(current_calls_tab, c); + calltree_remove_call(current_calls_tab, c->_callID); + update_actions(); break; case GDK_Escape: sflphone_unset_transfer(); @@ -755,90 +739,67 @@ sflphone_keypad(guint keyval, gchar * key) sflphone_new_call(); } -static void place_direct_call(const callable_obj_t * c) -{ - g_assert(c->_state == CALL_STATE_DIALING); - dbus_place_call(c); -} - -static int place_registered_call(callable_obj_t * c) +int +sflphone_place_call(callable_obj_t * c) { - account_t * current = NULL; + account_t * account = NULL; - if (c->_state != CALL_STATE_DIALING) + if (c == NULL) { + ERROR("Callable object is NULL while making new call"); return -1; + } - if (!*c->_peer_number) - return -1; + DEBUG("Placing call from %s to %s using account %s", c->_display_name, c->_peer_number, c->_accountID); - if (account_list_get_size() == 0) { - notify_no_accounts(); - sflphone_fail(c); + if (c->_state != CALL_STATE_DIALING) { + ERROR("Call not in state dialing, cannot place call"); return -1; } - if (account_list_get_by_state(ACCOUNT_STATE_REGISTERED) == NULL) { - DEBUG("Actions: No registered account, cannot make a call"); - notify_no_registered_accounts(); - sflphone_fail(c); + if (!c->_peer_number || strlen(c->_peer_number) == 0) { + ERROR("No peer number set for this call"); return -1; } - DEBUG("Actions: Get account for this call"); - + // Get the account for this call if (strlen(c->_accountID) != 0) { - DEBUG("Actions: Account %s already set for this call", c->_accountID); - current = account_list_get_by_id(c->_accountID); + DEBUG("Account %s already set for this call", c->_accountID); + account = account_list_get_by_id(c->_accountID); } else { - DEBUG("Actions: No account set for this call, use first of the list"); - current = account_list_get_current(); + DEBUG("No account set for this call, use first of the list"); + account = account_list_get_current(); } - if (current == NULL) { - DEBUG("Actions: Unexpected condition: account_t is NULL in %s at %d for accountID %s", __FILE__, __LINE__, c->_accountID); - return -1; + // Make sure the previously found account is registered, take first one registered elsewhere + if (account) { + gpointer status = g_hash_table_lookup(account->properties, "Status"); + if (!utf8_case_equal(status, "REGISTERED")) { + // Place the call with the first registered account + account = account_list_get_by_state(ACCOUNT_STATE_REGISTERED); + } } - if (g_strcasecmp(g_hash_table_lookup(current->properties, "Status"), "REGISTERED") ==0) { - /* The call is made with the current account */ - // free memory for previous account id and get a new one - g_free(c->_accountID); - c->_accountID = g_strdup(current->accountID); - dbus_place_call(c); - } else { - /* Place the call with the first registered account - * and switch the current account. - * If we are here, we can be sure that there is at least one. - */ - current = account_list_get_by_state(ACCOUNT_STATE_REGISTERED); - g_free(c->_accountID); - c->_accountID = g_strdup(current->accountID); - dbus_place_call(c); - notify_current_account(current); + // If there is no account specified or found, fallback on IP2IP call + if(account == NULL) { + DEBUG("Could not find an account for this call, making ip to ip call"); + account = account_list_get_by_id("IP2IP"); + if (account == NULL) { + ERROR("Actions: Could not determine any account for this call"); + return -1; + } } + // free memory for previous account id and use the new one in case it changed + g_free(c->_accountID); + c->_accountID = g_strdup(account->accountID); + dbus_place_call(c); + notify_current_account(account); + c->_history_state = g_strdup(OUTGOING_STRING); return 0; } -void -sflphone_place_call(callable_obj_t * c) -{ - DEBUG("Actions: Placing call with %s @ %s and accountid %s", c->_display_name, c->_peer_number, c->_accountID); - - if (is_direct_call(c)) { - gchar *msg = g_markup_printf_escaped(_("Direct SIP call")); - statusbar_pop_message(__MSG_ACCOUNT_DEFAULT); - statusbar_push_message(msg , NULL, __MSG_ACCOUNT_DEFAULT); - g_free(msg); - - place_direct_call(c); - } else if (place_registered_call(c) < 0) - DEBUG("An error occured while placing registered call in %s at %d", __FILE__, __LINE__); -} - - void sflphone_detach_participant(const gchar* callID) { @@ -849,15 +810,10 @@ sflphone_detach_participant(const gchar* callID) else selectedCall = calllist_get_call(current_calls_tab, callID); - DEBUG("Action: Detach participant %s", selectedCall->_callID); - - if (selectedCall->_confID) { - g_free(selectedCall->_confID); - selectedCall->_confID = NULL; - } + DEBUG("Detach participant %s", selectedCall->_callID); im_widget_update_state(IM_WIDGET(selectedCall->_im_widget), TRUE); - calltree_remove_call(current_calls_tab, selectedCall); + calltree_remove_call(current_calls_tab, selectedCall->_callID); calltree_add_call(current_calls_tab, selectedCall, NULL); dbus_detach_participant(selectedCall->_callID); } @@ -865,12 +821,12 @@ sflphone_detach_participant(const gchar* callID) void sflphone_add_participant(const gchar* callID, const gchar* confID) { - DEBUG(">SFLphone: Add participant %s to conference %s", callID, confID); + DEBUG("Add participant %s to conference %s", callID, confID); callable_obj_t *call = calllist_get_call(current_calls_tab, callID); if (call == NULL) { - ERROR("SFLphone: Error: Could not find call"); + ERROR("Could not find call"); return; } @@ -880,7 +836,7 @@ sflphone_add_participant(const gchar* callID, const gchar* confID) void sflphone_add_main_participant(const conference_obj_t * c) { - DEBUG("sflphone add main participant"); + DEBUG("%s", __PRETTY_FUNCTION__); dbus_add_main_participant(c->_confID); } @@ -891,7 +847,7 @@ sflphone_rec_call() conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab); if (selectedCall) { - DEBUG("SFLphone: Set record for selected call"); + DEBUG("Set record for selected call"); dbus_set_record(selectedCall->_callID); switch (selectedCall->_state) { @@ -908,7 +864,7 @@ sflphone_rec_call() calltree_update_call(current_calls_tab, selectedCall); } else if (selectedConf) { - DEBUG("SFLphone: Set record for selected conf"); + DEBUG("Set record for selected conf"); dbus_set_record(selectedConf->_confID); switch (selectedConf->_state) { @@ -929,7 +885,7 @@ sflphone_rec_call() break; } - DEBUG("Actions: Remove and add conference %s", selectedConf->_confID); + DEBUG("Remove and add conference %s", selectedConf->_confID); calltree_remove_conference(current_calls_tab, selectedConf); calltree_add_conference_to_current_calls(selectedConf); } @@ -937,22 +893,17 @@ sflphone_rec_call() update_actions(); } -void sflphone_fill_codec_list() +void +sflphone_mute_call() { - guint account_list_size = account_list_get_size(); - - for (guint i = 0; i < account_list_size; i++) { - account_t *current = account_list_get_nth(i); + DEBUG("%s", __PRETTY_FUNCTION__); - if (current) - sflphone_fill_codec_list_per_account(current); - } + toggle_slider_mute_microphone(); } void sflphone_fill_codec_list_per_account(account_t *account) { GArray *order = dbus_get_active_audio_codec_list(account->accountID); - GQueue *codeclist = account->codecs; // First clean the list @@ -989,18 +940,23 @@ void sflphone_fill_codec_list_per_account(account_t *account) void sflphone_fill_call_list(void) { - gchar **list = dbus_get_call_list(); - - for (gchar **calls = list; calls && *calls; ++calls) { - gchar *callID = *calls; - callable_obj_t *c = create_new_call_from_details(*calls, dbus_get_call_details(*calls)); - g_free(callID); - c->_zrtp_confirmed = FALSE; - calllist_add_call(current_calls_tab, c); - calltree_add_call(current_calls_tab, c, NULL); + gchar **call_list = dbus_get_call_list(); + + for (gchar **callp = call_list; callp && *callp; ++callp) { + gchar *callID = *callp; + if (!calllist_get_call(current_calls_tab, callID)) { + callable_obj_t *call = create_new_call_from_details(*callp, dbus_get_call_details(*callp)); + call->_zrtp_confirmed = FALSE; + calllist_add_call(current_calls_tab, call); + + // add in treeview only if does not participate to a conference + gchar *confID = dbus_get_conference_id(call->_callID); + if(g_strcmp0(confID, "") == 0) + calltree_add_call(current_calls_tab, call, NULL); + } } - g_strfreev(list); + g_strfreev(call_list); } @@ -1038,10 +994,9 @@ static void fill_treeview_with_calls(void) guint n = calllist_get_size(history_tab); for (guint i = 0; i < n; ++i) { - QueueElement *element = calllist_get_nth(history_tab, i); - - if (element->type == HIST_CALL) - calltree_add_history_entry(element->elem.call); + callable_obj_t *call = calllist_get_nth(history_tab, i); + if (call) + calltree_add_history_entry(call); } } @@ -1112,7 +1067,7 @@ sflphone_request_go_clear(void) void sflphone_call_state_changed(callable_obj_t * c, const gchar * description, const guint code) { - DEBUG("SFLPhone: Call State changed %s", description); + DEBUG("Call State changed %s", description); if (c == NULL) { ERROR("SFLphone: Error: callable obj is NULL in %s at %d", __FILE__, __LINE__); diff --git a/gnome/src/actions.h b/gnome/src/actions.h index efb2fe2f93b86f3ba830fcec044dfea94339de4e..6349c4cb8be4d410f2b833d0a173496906fb1b49 100644 --- a/gnome/src/actions.h +++ b/gnome/src/actions.h @@ -52,27 +52,27 @@ * Initialize lists and configurations * @return TRUE if succeeded, FALSE otherwise */ -gboolean sflphone_init () ; +gboolean sflphone_init(GError **error); /** * Steps when closing the application. Will ask for confirmation if a call is in progress. */ -void sflphone_quit () ; +void sflphone_quit(); /** * Hang up / refuse the current call */ -void sflphone_hang_up (); +void sflphone_hang_up(); /** * Put the selected call on hold */ -void sflphone_on_hold (); +void sflphone_on_hold(); /** * Put the selected call off hold */ -void sflphone_off_hold (); +void sflphone_off_hold(); /** * Open a new call @@ -85,7 +85,7 @@ callable_obj_t * sflphone_new_call(); * @param accountID The account the voice mails are for * @param count The number of voice mails */ -void sflphone_notify_voice_mail (const gchar* accountID , guint count); +void sflphone_notify_voice_mail(const gchar* accountID, guint count); /** * Prepare SFLphone to transfer a call and wait for the user to dial the number to transfer to @@ -101,49 +101,49 @@ void sflphone_unset_transfer(); /** * Accept / dial the current call */ -void sflphone_pick_up (); +void sflphone_pick_up(); /** * Put the call on hold state * @param c The current call */ -void sflphone_hold (callable_obj_t * c); +void sflphone_hold(callable_obj_t * c); /** * Put the call in Ringing state * @param c* The current call */ -void sflphone_ringing (callable_obj_t * c); +void sflphone_ringing(callable_obj_t * c); /** * Put the call in Busy state * @param c* The current call */ -void sflphone_busy (callable_obj_t * c); +void sflphone_busy(callable_obj_t * c); /** * Put the call in Failure state * @param c* The current call */ -void sflphone_fail (callable_obj_t * c); +void sflphone_fail(callable_obj_t * c); /** * Put the call in Current state * @param c The current call */ -void sflphone_current (callable_obj_t * c); +void sflphone_current(callable_obj_t * c); /** * The callee has hung up * @param c The current call */ -void sflphone_hung_up (callable_obj_t * c); +void sflphone_hung_up(callable_obj_t * c); /** * Incoming call * @param c The incoming call */ -void sflphone_incoming_call (callable_obj_t * c); +void sflphone_incoming_call(callable_obj_t * c); /** * Dial the number @@ -151,19 +151,19 @@ void sflphone_incoming_call (callable_obj_t * c); * @param keyval The unique int representing the key * @param key The char value of the key */ -void sflphone_keypad (guint keyval, gchar * key); +void sflphone_keypad(guint keyval, gchar * key); /** * Place a call with a filled callable_obj_t.to * @param c A call in CALL_STATE_DIALING state */ -void sflphone_place_call (callable_obj_t * c); +int sflphone_place_call(callable_obj_t * c); /** * Fetch the ip2ip profile through dbus and fill * the internal hash table. */ -void sflphone_fill_ip2ip_profile (void); +void sflphone_fill_ip2ip_profile(void); /** * @return The internal hash table representing @@ -172,51 +172,52 @@ void sflphone_fill_ip2ip_profile (void); GHashTable *sflphone_get_ip2ip_properties(void); /** - * Initialize the accounts data structure + * Get a list of accounts from the daemon and load them into account_t + * structures. */ -void sflphone_fill_account_list (); +void sflphone_fill_account_list(); -void sflphone_fill_call_list (void); +void sflphone_fill_call_list(void); /** * Set an account as current. The current account is to one used to place calls with by default - * The current account is the first in the account list ( index 0 ) + * The current account is the first in the account list( index 0 ) */ void sflphone_set_current_account(); /** * Initialialize the codecs data structure */ -void sflphone_fill_codec_list (); - -void sflphone_fill_codec_list_per_account (account_t *); +void sflphone_fill_codec_list_per_account(account_t *); void sflphone_add_participant(); -void sflphone_record (callable_obj_t *c); +void sflphone_record(callable_obj_t *c); + +void sflphone_rec_call(void); -void sflphone_rec_call (void); +void sflphone_mute_call(void); -void status_bar_display_account (); +void status_bar_display_account(); -void sflphone_fill_history (void); +void sflphone_fill_history(void); /** * Action called when a new participant is dragged in */ -void sflphone_add_participant (const gchar* callID, const gchar* confID); +void sflphone_add_participant(const gchar* callID, const gchar* confID); /** * Action called when a conference participant is draged out */ -void sflphone_detach_participant (const gchar* callID); +void sflphone_detach_participant(const gchar* callID); /** * Nofity that the communication is * now secured using SRTP/SDES. * @param c* The current call */ -void sflphone_srtp_sdes_on (callable_obj_t * c); +void sflphone_srtp_sdes_on(callable_obj_t * c); /** * Notify that the SRTP/SDES session @@ -228,14 +229,14 @@ void sflphone_srtp_sdes_on (callable_obj_t * c); * now secured using ZRTP. * @param c* The current call */ -void sflphone_srtp_zrtp_on (callable_obj_t * c); +void sflphone_srtp_zrtp_on(callable_obj_t * c); /** * Called when the ZRTP session goes * unsecured. * @param c* The current call */ -void sflphone_srtp_zrtp_off (callable_obj_t * c); +void sflphone_srtp_zrtp_off(callable_obj_t * c); /** * Called when the sas has been computed @@ -244,13 +245,14 @@ void sflphone_srtp_zrtp_off (callable_obj_t * c); * @param sas* The Short Authentication String * @param verified* Weather the SAS was confirmed or not. */ -void sflphone_srtp_zrtp_show_sas (callable_obj_t * c, const gchar* sas, const gboolean verified); +void sflphone_srtp_zrtp_show_sas(callable_obj_t * c, const gchar* sas, const gboolean verified); /** * Called when user wants to clear. * @param c* The call on which to go clear */ -void sflphone_request_go_clear (void); + +void sflphone_request_go_clear(void); /** * Called when the UI needs to be refreshed to @@ -260,12 +262,12 @@ void sflphone_request_go_clear (void); * @param description A textual description of the code * @param code The status code as in SIP or IAX */ -void sflphone_call_state_changed (callable_obj_t * c, const gchar * description, const guint code); +void sflphone_call_state_changed(callable_obj_t * c, const gchar * description, const guint code); -void sflphone_add_main_participant (const conference_obj_t * c); +void sflphone_add_main_participant(const conference_obj_t * c); -void sflphone_srtp_sdes_off (callable_obj_t * c); +void sflphone_srtp_sdes_off(callable_obj_t * c); -void sflphone_fill_conference_list (void); +void sflphone_fill_conference_list(void); #endif diff --git a/gnome/src/callable_obj.c b/gnome/src/callable_obj.c index 83449c6490f80acef63bfe5b9e11b4534a996f82..c64d042a4d33f954c0ab7d97b4157500d4813fe9 100644 --- a/gnome/src/callable_obj.c +++ b/gnome/src/callable_obj.c @@ -29,15 +29,17 @@ */ #include "callable_obj.h" +#include "str_utils.h" #include "codeclist.h" #include "sflphone_const.h" #include <time.h> +#include <glib/gi18n.h> #include "contacts/calltab.h" #include "contacts/calltree.h" +#include "logger.h" #include "dbus.h" #include <unistd.h> - gint get_state_callstruct(gconstpointer a, gconstpointer b) { callable_obj_t * c = (callable_obj_t*) a; @@ -145,15 +147,15 @@ callable_obj_t *create_new_call_from_details(const gchar *call_id, GHashTable *d const gchar * const display_name = g_hash_table_lookup(details, "DISPLAY_NAME"); const gchar * const state_str = g_hash_table_lookup(details, "CALL_STATE"); - if (g_strcasecmp(state_str, "CURRENT") == 0) + if (utf8_case_equal(state_str, "CURRENT")) state = CALL_STATE_CURRENT; - else if (g_strcasecmp(state_str, "RINGING") == 0) + else if (utf8_case_equal(state_str, "RINGING")) state = CALL_STATE_RINGING; - else if (g_strcasecmp(state_str, "INCOMING") == 0) + else if (utf8_case_equal(state_str, "INCOMING")) state = CALL_STATE_INCOMING; - else if (g_strcasecmp(state_str, "HOLD") == 0) + else if (utf8_case_equal(state_str, "HOLD")) state = CALL_STATE_HOLD; - else if (g_strcasecmp(state_str, "BUSY") == 0) + else if (utf8_case_equal(state_str, "BUSY")) state = CALL_STATE_BUSY; else state = CALL_STATE_FAILURE; @@ -195,8 +197,7 @@ callable_obj_t *create_history_entry_from_hashtable(GHashTable *entry) value = g_hash_table_lookup(entry, TIMESTAMP_STOP_KEY); new_call->_time_stop = value ? atoi(value) : 0; new_call->_recordfile = g_strdup(g_hash_table_lookup(entry, RECORDING_PATH_KEY)); - new_call->_confID = g_strdup(g_hash_table_lookup(entry, CONFID_KEY)); - new_call->_historyConfID = g_strdup(new_call->_confID); + new_call->_historyConfID = g_strdup(g_hash_table_lookup(entry, CONFID_KEY)); new_call->_record_is_playing = FALSE; return new_call; @@ -205,7 +206,6 @@ callable_obj_t *create_history_entry_from_hashtable(GHashTable *entry) void free_callable_obj_t (callable_obj_t *c) { g_free(c->_callID); - g_free(c->_confID); g_free(c->_historyConfID); g_free(c->_accountID); g_free(c->_srtp_cipher); @@ -305,3 +305,22 @@ gboolean call_was_outgoing(callable_obj_t * obj) { return g_strcmp0(obj->_history_state, OUTGOING_STRING) == 0; } + +void restore_call(const gchar *id) +{ + DEBUG("Restoring call %s", id); + // We fetch the details associated to the specified call + GHashTable *call_details = dbus_get_call_details(id); + if (!call_details) { + ERROR("Invalid call ID"); + return; + } + callable_obj_t *new_call = create_new_call_from_details(id, call_details); + + if (utf8_case_equal(g_hash_table_lookup(call_details, "CALL_TYPE"), INCOMING_STRING)) + new_call->_history_state = g_strdup(INCOMING_STRING); + else + new_call->_history_state = g_strdup(OUTGOING_STRING); + + calllist_add_call(current_calls_tab, new_call); +} diff --git a/gnome/src/callable_obj.h b/gnome/src/callable_obj.h index b2437962e6d4dc72df1d1bc5d1870c310ac60f61..7f6c0aca7acee320763cb2de9e72f05b443b8bea 100644 --- a/gnome/src/callable_obj.h +++ b/gnome/src/callable_obj.h @@ -96,8 +96,7 @@ typedef struct { int _state_code; // The numeric state code as defined in SIP or IAX gchar* _state_code_description; // A textual description of _state_code gchar* _callID; // The call ID - gchar* _confID; // The conference ID (NULL if don't participate to a conference) - gchar* _historyConfID; // Persistent conf id to be stored in history + gchar* _historyConfID; // Persistent conf id to be stored in history gchar* _accountID; // The account the call is made with time_t _time_start; // The timestamp the call was initiating time_t _time_stop; // The timestamp the call was over @@ -204,4 +203,6 @@ gchar* call_get_audio_codec(callable_obj_t *obj); gboolean call_was_outgoing(callable_obj_t * obj); +void restore_call(const gchar *id); + #endif diff --git a/gnome/src/codeclist.c b/gnome/src/codeclist.c index 25b69d9c7f985cb326529a2bfe554ff0a3c7d850..1c54577a9a2017de333dabd5a76ea0f9c829184f 100644 --- a/gnome/src/codeclist.c +++ b/gnome/src/codeclist.c @@ -176,7 +176,7 @@ void codec_set_prefered_order(guint codec_index, GQueue *q) void codec_list_move_codec_up(guint codec_index, GQueue **q) { - DEBUG("Codec list Size: %i \n", codec_list_get_size()); + DEBUG("Codec list size: %i \n", codec_list_get_size()); GQueue *tmp = *q; @@ -190,8 +190,7 @@ void codec_list_move_codec_up(guint codec_index, GQueue **q) void codec_list_move_codec_down(guint codec_index, GQueue **q) { - - DEBUG("Codec list Size: %i \n", codec_list_get_size()); + DEBUG("Codec list size: %i \n", codec_list_get_size()); GQueue *tmp = *q; @@ -204,7 +203,7 @@ void codec_list_move_codec_down(guint codec_index, GQueue **q) } -void codec_list_update_to_daemon(account_t *acc) +void codec_list_update_to_daemon(const account_t *acc) { // Length of the codec list int length = g_queue_get_length(acc->codecs); @@ -217,7 +216,7 @@ void codec_list_update_to_daemon(account_t *acc) int c = 0; int i; - for (i = 0; i < length; i++) { + for (i = 0; i < length; ++i) { codec_t* currentCodec = codec_list_get_nth(i, acc->codecs); if (currentCodec) { @@ -240,14 +239,14 @@ void codec_list_update_to_daemon(account_t *acc) // Allocate NULL array at the end for Dbus codecList = (void*) g_realloc(codecList, (c + 1) * sizeof(void*)); - *(codecList+c) = NULL; + *(codecList + c) = NULL; // call dbus function with array of strings dbus_set_active_audio_codec_list(codecList, acc->accountID); // Delete memory for (i = 0; i < c; i++) - g_free((gchar*) *(codecList+i)); + g_free((gchar*) *(codecList + i) ); g_free(codecList); } diff --git a/gnome/src/codeclist.h b/gnome/src/codeclist.h index 242fd6eac553e909a190151f578b5c22d98bf074..bdbf95cd7e625c231e5deda4c52a828d400d991b 100644 --- a/gnome/src/codeclist.h +++ b/gnome/src/codeclist.h @@ -127,7 +127,7 @@ void codec_list_move_codec_down (guint index, GQueue **q); /** * Notify modifications on codecs to the server */ -void codec_list_update_to_daemon (account_t *acc); +void codec_list_update_to_daemon (const account_t *acc); codec_t* codec_list_get_by_payload (gconstpointer payload, GQueue *q); diff --git a/gnome/src/conference_obj.c b/gnome/src/conference_obj.c index f2bda66b51a3310be1f614408da839091b3e0221..91e4c6d41aeb34a33a75af15e5ffc412eddc2966 100644 --- a/gnome/src/conference_obj.c +++ b/gnome/src/conference_obj.c @@ -31,29 +31,26 @@ #include <time.h> #include "callable_obj.h" +#include "str_utils.h" #include "dbus.h" #include "sflphone_const.h" #include "logger.h" #include "calltab.h" #include "calllist.h" -conference_obj_t *create_new_conference(conference_state_t state, const gchar* const confID) +conference_obj_t * +create_new_conference(conference_state_t state, const gchar* const confID) { if (confID == NULL) { - ERROR("Conference: Error: Conference ID is NULL while creating new conference"); + ERROR("Conference ID is NULL while creating new conference"); return NULL; } - DEBUG("Conference: Create new conference %s", confID); + DEBUG("Create new conference %s", confID); // Allocate memory conference_obj_t *new_conf = g_new0(conference_obj_t, 1); - if (!new_conf) { - ERROR("Conference: Error: Could not allocate data "); - return NULL; - } - // Set state field new_conf->_state = state; @@ -80,17 +77,17 @@ conference_obj_t *create_new_conference_from_details(const gchar *conf_id, GHash gchar *state_str = g_hash_table_lookup(details, "CONF_STATE"); - if (g_strcasecmp(state_str, "ACTIVE_ATTACHED") == 0) + if (utf8_case_equal(state_str, "ACTIVE_ATTACHED")) new_conf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED; - else if (g_strcasecmp(state_str, "ACTIVE_ATTACHED_REC") == 0) + else if (utf8_case_equal(state_str, "ACTIVE_ATTACHED_REC")) new_conf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD; - else if (g_strcasecmp(state_str, "ACTIVE_DETACHED") == 0) + else if (utf8_case_equal(state_str, "ACTIVE_DETACHED")) new_conf->_state = CONFERENCE_STATE_ACTIVE_DETACHED; - else if (g_strcasecmp(state_str, "ACTIVE_DETACHED_REC") == 0) + else if (utf8_case_equal(state_str, "ACTIVE_DETACHED_REC")) new_conf->_state = CONFERENCE_STATE_ACTIVE_DETACHED_RECORD; - else if (g_strcasecmp(state_str, "HOLD") == 0) + else if (utf8_case_equal(state_str, "HOLD")) new_conf->_state = CONFERENCE_STATE_HOLD; - else if (g_strcasecmp(state_str, "HOLD_REC") == 0) + else if (utf8_case_equal(state_str, "HOLD_REC")) new_conf->_state = CONFERENCE_STATE_HOLD_RECORD; return new_conf; @@ -113,7 +110,7 @@ void conference_add_participant_number(const gchar *call_id, conference_obj_t *c callable_obj_t *call = calllist_get_call(current_calls_tab, call_id); if (!call) { - ERROR("Conference: Error: Could not find %s", call_id); + ERROR("Could not find %s", call_id); return; } @@ -123,7 +120,7 @@ void conference_add_participant_number(const gchar *call_id, conference_obj_t *c void conference_add_participant(const gchar* call_id, conference_obj_t* conf) { - DEBUG("Conference: Conference %s, adding participant %s", conf->_confID, call_id); + DEBUG("Conference %s, adding participant %s", conf->_confID, call_id); // store the new participant list after appending participant id conf->participant_list = g_slist_append(conf->participant_list, (gpointer) g_strdup(call_id)); @@ -141,23 +138,11 @@ void conference_remove_participant(const gchar* call_id, conference_obj_t* conf) void conference_participant_list_update(gchar** participants, conference_obj_t* conf) { - DEBUG("Conference: Participant list update"); - if (!conf) { - ERROR("Conference: Error: Conference is NULL"); + ERROR("Conference is NULL"); return; } - for (gchar **part = participants; part && *part; ++part) { - gchar *call_id = (gchar *) (*part); - callable_obj_t *call = calllist_get_call(current_calls_tab, call_id); - - if (call->_confID != NULL) { - g_free(call->_confID); - call->_confID = NULL; - } - } - if (conf->participant_list) { g_slist_free(conf->participant_list); conf->participant_list = NULL; @@ -166,7 +151,10 @@ void conference_participant_list_update(gchar** participants, conference_obj_t* for (gchar **part = participants; part && *part; ++part) { gchar *call_id = (gchar *) (*part); callable_obj_t *call = calllist_get_call(current_calls_tab, call_id); - call->_confID = g_strdup(conf->_confID); + if (!call) { + restore_call(call_id); + call = calllist_get_call(current_calls_tab, call_id); + } conference_add_participant(call_id, conf); } } diff --git a/gnome/src/conference_obj.h b/gnome/src/conference_obj.h index e7f0e3a57cb6c92257a702c24da0ee3ac68876c4..0e17bada2addb8a6bf1384b71354ffd5fb54b743 100644 --- a/gnome/src/conference_obj.h +++ b/gnome/src/conference_obj.h @@ -32,7 +32,7 @@ #define __CONFERENCE_OBJ_H__ #include <gtk/gtk.h> -#include <glib/gprintf.h> +#include <glib.h> #include <stdlib.h> #include <time.h> diff --git a/gnome/src/config/accountconfigdialog.c b/gnome/src/config/accountconfigdialog.c index ef55ea27cdb81afe93b780576a42d3f60aeb9af0..1127993b622b0f879f31e67cd82cd6f4977ac335 100644 --- a/gnome/src/config/accountconfigdialog.c +++ b/gnome/src/config/accountconfigdialog.c @@ -31,6 +31,7 @@ * as that of the covered work. */ +#include <glib/gi18n.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> @@ -39,6 +40,8 @@ #include <gtk/gtk.h> #include "config.h" +#include "gtk2_wrappers.h" +#include "str_utils.h" #include "logger.h" #include "actions.h" #include "mainwindow.h" @@ -57,42 +60,38 @@ * in a private structure. * Local variables */ -static GtkWidget * entryAlias; -static GtkWidget * protocolComboBox; -static GtkWidget * entryUsername; -static GtkWidget * entryRouteSet; -static GtkWidget * entryHostname; -static GtkWidget * entryPassword; -static GtkWidget * entryMailbox; -static GtkWidget * entryUseragent; -static GtkWidget * entryResolveNameOnlyOnce; -static GtkWidget * expireSpinBox; -static GtkListStore * credentialStore; -static GtkWidget * deleteCredButton; -static GtkWidget * treeViewCredential; -static GtkWidget * advancedZrtpButton; -static GtkWidget * keyExchangeCombo; -static GtkWidget * useSipTlsCheckBox; - -static GtkWidget * localAddressEntry; -static GtkWidget * publishedAddressEntry; -static GtkWidget * localAddressCombo; -static GtkWidget * useStunCheckBox; -static GtkWidget * sameAsLocalRadioButton; -static GtkWidget * publishedAddrRadioButton; -static GtkWidget * publishedPortSpinBox; -static GtkWidget * localPortSpinBox; -static GtkWidget * publishedAddressLabel; -static GtkWidget * publishedPortLabel; -static GtkWidget * stunServerLabel; -static GtkWidget * stunServerEntry; -static GtkWidget * enableTone; -static GtkWidget * fileChooser; - -static GtkWidget * security_tab; -static GtkWidget * advanced_tab; - -static GtkWidget * overrtp; +static GtkWidget *entry_alias; +static GtkWidget *protocol_combo; +static GtkWidget *entry_username; +static GtkWidget *entry_route_set; +static GtkWidget *entry_hostname; +static GtkWidget *entry_password; +static GtkWidget *entry_mailbox; +static GtkWidget *entry_user_agent; +static GtkWidget *expire_spin_box; +static GtkListStore *credential_store; +static GtkWidget *delete_cred_button; +static GtkWidget *treeview_credential; +static GtkWidget *zrtp_button; +static GtkWidget *key_exchange_combo; +static GtkWidget *use_sip_tls_check_box; +static GtkWidget *local_address_entry; +static GtkWidget *published_address_entry; +static GtkWidget *local_address_combo; +static GtkWidget *use_stun_check_box; +static GtkWidget *same_as_local_radio_button; +static GtkWidget *published_addr_radio_button; +static GtkWidget *published_port_spin_box; +static GtkWidget *local_port_spin_box; +static GtkWidget *published_address_label; +static GtkWidget *published_port_label; +static GtkWidget *stun_server_label; +static GtkWidget *stun_server_entry; +static GtkWidget *enable_tone; +static GtkWidget *file_chooser; +static GtkWidget *security_tab; +static GtkWidget *advanced_tab; +static GtkWidget *overrtp; // Credentials enum { @@ -109,13 +108,13 @@ enum { */ static void reset() { - entryAlias = NULL; - protocolComboBox = NULL; - entryHostname = NULL; - entryUsername = NULL; - entryPassword = NULL; - entryUseragent = NULL; - entryMailbox = NULL; + entry_alias = NULL; + protocol_combo = NULL; + entry_hostname = NULL; + entry_username = NULL; + entry_password = NULL; + entry_user_agent = NULL; + entry_mailbox = NULL; } /* @@ -126,14 +125,14 @@ static void show_password_cb(GtkWidget *widget UNUSED, gpointer data) gtk_entry_set_visibility(GTK_ENTRY(data), !gtk_entry_get_visibility(GTK_ENTRY(data))); } -/* Signal to protocolComboBox 'changed' */ -void change_protocol_cb(account_t *currentAccount UNUSED) +/* Signal to protocol_combo 'changed' */ +void change_protocol_cb() { - gchar *protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocolComboBox)); + gchar *protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocol_combo)); // Only if tabs are not NULL if (security_tab && advanced_tab) { - if (g_strcasecmp(protocol, "IAX") == 0) { + if (utf8_case_equal(protocol, "IAX")) { gtk_widget_hide(security_tab); gtk_widget_hide(advanced_tab); } else { @@ -154,22 +153,20 @@ select_dtmf_type(void) DEBUG("Selected DTMF over SIP"); } -static GPtrArray* getNewCredential(void) +static GPtrArray* get_new_credential(void) { - GtkTreeIter iter; gint row_count = 0; GPtrArray *credential_array = g_ptr_array_new(); - gboolean valid; - - for (valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(credentialStore), &iter) ; - valid; - valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(credentialStore), &iter)) { + GtkTreeIter iter; + for (gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(credential_store), &iter); + valid; + valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(credential_store), &iter)) { gchar *username; gchar *realm; gchar *password; - gtk_tree_model_get(GTK_TREE_MODEL(credentialStore), &iter, + gtk_tree_model_get(GTK_TREE_MODEL(credential_store), &iter, COLUMN_CREDENTIAL_REALM, &realm, COLUMN_CREDENTIAL_USERNAME, &username, COLUMN_CREDENTIAL_PASSWORD, &password, @@ -177,7 +174,8 @@ static GPtrArray* getNewCredential(void) DEBUG("Row %d: %s %s %s", row_count++, username, password, realm); - GHashTable * new_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + GHashTable * new_table = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); g_hash_table_insert(new_table, g_strdup(ACCOUNT_REALM), realm); g_hash_table_insert(new_table, g_strdup(ACCOUNT_USERNAME), username); g_hash_table_insert(new_table, g_strdup(ACCOUNT_PASSWORD), password); @@ -192,53 +190,36 @@ static void update_credential_cb(GtkWidget *widget, gpointer data UNUSED) { GtkTreeIter iter; - if (credentialStore && gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(credentialStore), &iter, "0")) { + if (credential_store && gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(credential_store), &iter, "0")) { gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "column")); - gtk_list_store_set(GTK_LIST_STORE(credentialStore), &iter, column,(gchar *) gtk_entry_get_text(GTK_ENTRY(widget)), -1); + gtk_list_store_set(GTK_LIST_STORE(credential_store), &iter, column, gtk_entry_get_text(GTK_ENTRY(widget)), -1); } } -static GtkWidget* create_basic_tab(account_t *currentAccount) +static GtkWidget* create_basic_tab(const account_t *account) { - g_assert(currentAccount); - - // Load from SIP/IAX/Unknown ? - gchar *curAccountType = g_hash_table_lookup(currentAccount->properties, ACCOUNT_TYPE); - gchar *curAlias = g_hash_table_lookup(currentAccount->properties, ACCOUNT_ALIAS); - gchar *curHostname = g_hash_table_lookup(currentAccount->properties, ACCOUNT_HOSTNAME); - gchar *curPassword; - gchar *curUsername; - gchar *curUseragent; - gchar *curRouteSet; - gchar *curMailbox; - - if (g_strcmp0(curAccountType, "SIP") == 0) { + g_assert(account); + gchar *password = NULL; + if (account_is_SIP(account)) { /* get password from credentials list */ - if (currentAccount->credential_information) { - GHashTable * element = g_ptr_array_index(currentAccount->credential_information, 0); - curPassword = g_hash_table_lookup(element, ACCOUNT_PASSWORD); - } else - curPassword = ""; + if (account->credential_information) { + GHashTable * element = g_ptr_array_index(account->credential_information, 0); + password = g_hash_table_lookup(element, ACCOUNT_PASSWORD); + } } else - curPassword = g_hash_table_lookup(currentAccount->properties, ACCOUNT_PASSWORD); - - curUsername = g_hash_table_lookup(currentAccount->properties, ACCOUNT_USERNAME); - curRouteSet = g_hash_table_lookup(currentAccount->properties, ACCOUNT_ROUTE); - curMailbox = g_hash_table_lookup(currentAccount->properties, ACCOUNT_MAILBOX); - curMailbox = curMailbox != NULL ? curMailbox : ""; - curUseragent = g_hash_table_lookup(currentAccount->properties, ACCOUNT_USERAGENT); + password = account_lookup(account, ACCOUNT_PASSWORD); GtkWidget *frame = gnome_main_section_new(_("Account Parameters")); gtk_widget_show(frame); - GtkWidget * table = NULL; + GtkWidget *table = NULL; - if (g_strcmp0(curAccountType, "SIP") == 0) - table = gtk_table_new(9, 2, FALSE/* homogeneous */); - else if (g_strcmp0(curAccountType, "IAX") == 0) + if (account_is_SIP(account)) + table = gtk_table_new(9, 2, FALSE /* homogeneous */); + else if (account_is_IAX(account)) table = gtk_table_new(8, 2, FALSE); else { - ERROR("Unknown account type \"%s\"", curAccountType); + ERROR("Unknown account type"); return NULL; } @@ -249,113 +230,137 @@ static GtkWidget* create_basic_tab(account_t *currentAccount) GtkWidget *label = gtk_label_new_with_mnemonic(_("_Alias")); gint row = 0; - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryAlias = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryAlias); - gtk_entry_set_text(GTK_ENTRY(entryAlias), curAlias); - gtk_table_attach(GTK_TABLE(table), entryAlias, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_alias = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_alias); + gchar *alias = account_lookup(account, ACCOUNT_ALIAS); + gtk_entry_set_text(GTK_ENTRY(entry_alias), alias); + gtk_table_attach(GTK_TABLE(table), entry_alias, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Protocol")); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - protocolComboBox = gtk_combo_box_text_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), protocolComboBox); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocolComboBox), "SIP"); + protocol_combo = gtk_combo_box_text_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), protocol_combo); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocol_combo), "SIP"); if (dbus_is_iax2_enabled()) - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocolComboBox), "IAX"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocol_combo), "IAX"); - if (g_strcmp0(curAccountType, "SIP") == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(protocolComboBox),0); - else if (g_strcmp0(curAccountType, "IAX") == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(protocolComboBox),1); + if (account_is_SIP(account)) + gtk_combo_box_set_active(GTK_COMBO_BOX(protocol_combo), 0); + else if (account_is_IAX(account)) + gtk_combo_box_set_active(GTK_COMBO_BOX(protocol_combo), 1); else { - DEBUG("Config: Error: Account protocol not valid"); + ERROR("Account protocol not valid"); /* Should never come here, add debug message. */ - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocolComboBox), _("Unknown")); - gtk_combo_box_set_active(GTK_COMBO_BOX(protocolComboBox), 2); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocol_combo), _("Unknown")); + gtk_combo_box_set_active(GTK_COMBO_BOX(protocol_combo), 2); } - gtk_table_attach(GTK_TABLE(table), protocolComboBox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), protocol_combo, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); /* Link signal 'changed' */ - g_signal_connect(G_OBJECT(GTK_COMBO_BOX(protocolComboBox)), "changed", - G_CALLBACK(change_protocol_cb), - currentAccount); + g_signal_connect(G_OBJECT(GTK_COMBO_BOX(protocol_combo)), "changed", + G_CALLBACK(change_protocol_cb), NULL); row++; label = gtk_label_new_with_mnemonic(_("_Host name")); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryHostname = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryHostname); - gtk_entry_set_text(GTK_ENTRY(entryHostname), curHostname); - gtk_table_attach(GTK_TABLE(table), entryHostname, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_hostname = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_hostname); + const gchar *hostname = account_lookup(account, ACCOUNT_HOSTNAME); + gtk_entry_set_text(GTK_ENTRY(entry_hostname), hostname); + gtk_table_attach(GTK_TABLE(table), entry_hostname, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_User name")); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryUsername = gtk_entry_new(); - gtk_entry_set_icon_from_pixbuf(GTK_ENTRY(entryUsername), GTK_ENTRY_ICON_PRIMARY, gdk_pixbuf_new_from_file(ICONS_DIR "/stock_person.svg", NULL)); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryUsername); - gtk_entry_set_text(GTK_ENTRY(entryUsername), curUsername); - gtk_table_attach(GTK_TABLE(table), entryUsername, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - if (g_strcmp0(curAccountType, "SIP") == 0) { - g_signal_connect(G_OBJECT(entryUsername), "changed", G_CALLBACK(update_credential_cb), NULL); - g_object_set_data(G_OBJECT(entryUsername), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_USERNAME)); + entry_username = gtk_entry_new(); + const gchar *PERSON_IMG = ICONS_DIR "/stock_person.svg"; + gtk_entry_set_icon_from_pixbuf(GTK_ENTRY(entry_username), + GTK_ENTRY_ICON_PRIMARY, + gdk_pixbuf_new_from_file(PERSON_IMG, NULL)); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_username); + gchar *username = account_lookup(account, ACCOUNT_USERNAME); + gtk_entry_set_text(GTK_ENTRY(entry_username), username); + gtk_table_attach(GTK_TABLE(table), entry_username, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + + if (account_is_SIP(account)) { + g_signal_connect(G_OBJECT(entry_username), "changed", + G_CALLBACK(update_credential_cb), NULL); + g_object_set_data(G_OBJECT(entry_username), "column", + GINT_TO_POINTER(COLUMN_CREDENTIAL_USERNAME)); } row++; label = gtk_label_new_with_mnemonic(_("_Password")); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryPassword = gtk_entry_new(); - gtk_entry_set_icon_from_stock(GTK_ENTRY(entryPassword), GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_DIALOG_AUTHENTICATION); - gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryPassword); - gtk_entry_set_text(GTK_ENTRY(entryPassword), curPassword); - gtk_table_attach(GTK_TABLE(table), entryPassword, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - if (g_strcmp0(curAccountType, "SIP") == 0) { - g_signal_connect(G_OBJECT(entryPassword), "changed", G_CALLBACK(update_credential_cb), NULL); - g_object_set_data(G_OBJECT(entryPassword), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_PASSWORD)); + entry_password = gtk_entry_new(); + gtk_entry_set_icon_from_stock(GTK_ENTRY(entry_password), + GTK_ENTRY_ICON_PRIMARY, + GTK_STOCK_DIALOG_AUTHENTICATION); + gtk_entry_set_visibility(GTK_ENTRY(entry_password), FALSE); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_password); + password = password ? password : ""; + gtk_entry_set_text(GTK_ENTRY(entry_password), password); + gtk_table_attach(GTK_TABLE(table), entry_password, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + + if (account_is_SIP(account)) { + g_signal_connect(G_OBJECT(entry_password), "changed", G_CALLBACK(update_credential_cb), NULL); + g_object_set_data(G_OBJECT(entry_password), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_PASSWORD)); } row++; - GtkWidget *clearTextCheckbox = gtk_check_button_new_with_mnemonic(_("Show password")); - g_signal_connect(clearTextCheckbox, "toggled", G_CALLBACK(show_password_cb), entryPassword); - gtk_table_attach(GTK_TABLE(table), clearTextCheckbox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + GtkWidget *clearTextcheck_box = gtk_check_button_new_with_mnemonic(_("Show password")); + g_signal_connect(clearTextcheck_box, "toggled", G_CALLBACK(show_password_cb), entry_password); + gtk_table_attach(GTK_TABLE(table), clearTextcheck_box, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Proxy")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryRouteSet = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryRouteSet); - gtk_entry_set_text(GTK_ENTRY(entryRouteSet), curRouteSet); - gtk_table_attach(GTK_TABLE(table), entryRouteSet, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_route_set = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_route_set); + gchar *route_set = account_lookup(account, ACCOUNT_ROUTE); + gtk_entry_set_text(GTK_ENTRY(entry_route_set), route_set); + gtk_table_attach(GTK_TABLE(table), entry_route_set, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Voicemail number")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryMailbox = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryMailbox); - gtk_entry_set_text(GTK_ENTRY(entryMailbox), curMailbox); - gtk_table_attach(GTK_TABLE(table), entryMailbox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_mailbox = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_mailbox); + gchar *mailbox = account_lookup(account, ACCOUNT_MAILBOX); + mailbox = mailbox ? mailbox : ""; + gtk_entry_set_text(GTK_ENTRY(entry_mailbox), mailbox); + gtk_table_attach(GTK_TABLE(table), entry_mailbox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_User-agent")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryUseragent = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryUseragent); - gtk_entry_set_text(GTK_ENTRY(entryUseragent), curUseragent); - gtk_table_attach(GTK_TABLE(table), entryUseragent, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_user_agent = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_user_agent); + gchar *user_agent = account_lookup(account, ACCOUNT_USERAGENT); + gtk_entry_set_text(GTK_ENTRY(entry_user_agent), user_agent); + gtk_table_attach(GTK_TABLE(table), entry_user_agent, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show_all(table); gtk_container_set_border_width(GTK_CONTAINER(table), 10); @@ -363,25 +368,15 @@ static GtkWidget* create_basic_tab(account_t *currentAccount) return frame; } -static void fill_treeview_with_credential(account_t * account) +static void fill_treeview_with_credential(const account_t * account) { GtkTreeIter iter; - gtk_list_store_clear(credentialStore); - - if (!account->credential_information) { - account->credential_information = g_ptr_array_sized_new(1); - GHashTable * new_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_insert(new_table, g_strdup(ACCOUNT_REALM), g_strdup("*")); - g_hash_table_insert(new_table, g_strdup(ACCOUNT_USERNAME), g_strdup("")); - g_hash_table_insert(new_table, g_strdup(ACCOUNT_PASSWORD), g_strdup("")); - g_ptr_array_add(account->credential_information, new_table); - } + gtk_list_store_clear(credential_store); for (unsigned i = 0; i < account->credential_information->len; i++) { GHashTable * element = g_ptr_array_index(account->credential_information, i); - gtk_list_store_append(credentialStore, &iter); - gtk_list_store_set(credentialStore, &iter, - COLUMN_CREDENTIAL_REALM, g_hash_table_lookup(element, ACCOUNT_REALM), + gtk_list_store_append(credential_store, &iter); + gtk_list_store_set(credential_store, &iter, COLUMN_CREDENTIAL_REALM, g_hash_table_lookup(element, ACCOUNT_REALM), COLUMN_CREDENTIAL_USERNAME, g_hash_table_lookup(element, ACCOUNT_USERNAME), COLUMN_CREDENTIAL_PASSWORD, g_hash_table_lookup(element, ACCOUNT_PASSWORD), COLUMN_CREDENTIAL_DATA, element, -1); @@ -391,22 +386,19 @@ static void fill_treeview_with_credential(account_t * account) static void select_credential_cb(GtkTreeSelection *selection, GtkTreeModel *model) { GtkTreeIter iter; - if (gtk_tree_selection_get_selected(selection, NULL, &iter)) { GtkTreePath *path = gtk_tree_model_get_path(model, &iter); - if (gtk_tree_path_get_indices(path)[0] == 0) - gtk_widget_set_sensitive(deleteCredButton, FALSE); - else - gtk_widget_set_sensitive(deleteCredButton, TRUE); + const gboolean sensitive = gtk_tree_path_get_indices(path)[0] != 0; + gtk_widget_set_sensitive(delete_cred_button, sensitive); } } static void add_credential_cb(GtkWidget *button UNUSED, gpointer data) { - GtkTreeIter iter; - GtkTreeModel *model =(GtkTreeModel *) data; + GtkTreeModel *model = (GtkTreeModel *) data; + GtkTreeIter iter; gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_CREDENTIAL_REALM, "*", @@ -414,10 +406,11 @@ static void add_credential_cb(GtkWidget *button UNUSED, gpointer data) COLUMN_CREDENTIAL_PASSWORD, _("Secret"), -1); } -static void delete_credential_cb(GtkWidget *button UNUSED, gpointer data) +static void +delete_credential_cb(GtkWidget *button UNUSED, gpointer data) { GtkTreeIter iter; - GtkTreeView *treeview =(GtkTreeView *) data; + GtkTreeView *treeview = (GtkTreeView *) data; GtkTreeModel *model = gtk_tree_view_get_model(treeview); GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); @@ -425,23 +418,25 @@ static void delete_credential_cb(GtkWidget *button UNUSED, gpointer data) GtkTreePath *path; path = gtk_tree_model_get_path(model, &iter); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); - gtk_tree_path_free(path); } - } -static void cell_edited_cb(GtkCellRendererText *renderer, gchar *path_desc, gchar *text, gpointer data) +static void +cell_edited_cb(GtkCellRendererText *renderer, gchar *path_desc, gchar *text, + gpointer data) { GtkTreeModel *model =(GtkTreeModel *) data; GtkTreePath *path = gtk_tree_path_new_from_string(path_desc); gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(renderer), "column")); - DEBUG("path desc in cell_edited_cb: %s\n", text); + DEBUG("path desc: %s\n", text); - if ((g_strcasecmp(path_desc, "0") == 0) && - g_strcasecmp(text, gtk_entry_get_text(GTK_ENTRY(entryUsername))) != 0) - g_signal_handlers_disconnect_by_func(G_OBJECT(entryUsername), G_CALLBACK(update_credential_cb), NULL); + if ((utf8_case_equal(path_desc, "0")) && + !utf8_case_equal(text, gtk_entry_get_text(GTK_ENTRY(entry_username)))) + g_signal_handlers_disconnect_by_func(G_OBJECT(entry_username), + G_CALLBACK(update_credential_cb), + NULL); GtkTreeIter iter; gtk_tree_model_get_iter(model, &iter, path); @@ -449,88 +444,87 @@ static void cell_edited_cb(GtkCellRendererText *renderer, gchar *path_desc, gcha gtk_tree_path_free(path); } -static void editing_started_cb(GtkCellRenderer *cell UNUSED, GtkCellEditable * editable, const gchar * path, gpointer data UNUSED) +static void +editing_started_cb(GtkCellRenderer *cell UNUSED, GtkCellEditable * editable, + const gchar * path, gpointer data UNUSED) { - DEBUG("Editing started"); - DEBUG("path desc in editing_started_cb: %s\n", path); + DEBUG("path desc: %s\n", path); // If we are dealing the first row - if (g_strcasecmp(path, "0") == 0) - gtk_entry_set_text(GTK_ENTRY(editable), gtk_entry_get_text(GTK_ENTRY(entryPassword))); + if (utf8_case_equal(path, "0")) + gtk_entry_set_text(GTK_ENTRY(editable), gtk_entry_get_text(GTK_ENTRY(entry_password))); } static void show_advanced_zrtp_options_cb(GtkWidget *widget UNUSED, gpointer data) { - gchar *proto = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo)); + account_t *account = (account_t *) data; + gchar *proto = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(key_exchange_combo)); - if (g_strcasecmp(proto, "ZRTP") == 0) - show_advanced_zrtp_options((GHashTable *) data); + if (utf8_case_equal(proto, "ZRTP")) + show_advanced_zrtp_options(account); else - show_advanced_sdes_options((GHashTable *) data); + show_advanced_sdes_options(account); g_free(proto); } -static void show_advanced_tls_options_cb(GtkWidget *widget UNUSED, gpointer data) +static void +show_advanced_tls_options_cb(GtkWidget *widget UNUSED, gpointer data) { - show_advanced_tls_options((GHashTable *) data); + account_t *account = (account_t *) data; + show_advanced_tls_options(account); } -static void key_exchange_changed_cb(GtkWidget *widget UNUSED, gpointer data UNUSED) +static void +key_exchange_changed_cb(GtkWidget *widget UNUSED, gpointer data UNUSED) { - gchar *active_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo)); + gchar *active_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(key_exchange_combo)); DEBUG("Key exchange changed %s", active_text); - gboolean set_sensitive = FALSE; - set_sensitive |= g_strcasecmp(active_text, "SDES") == 0; - set_sensitive |= g_strcasecmp(active_text, "ZRTP") == 0; + gboolean sensitive = FALSE; + sensitive |= utf8_case_equal(active_text, "SDES"); + sensitive |= utf8_case_equal(active_text, "ZRTP"); g_free(active_text); - - if (set_sensitive) - gtk_widget_set_sensitive(advancedZrtpButton, TRUE); - else - gtk_widget_set_sensitive(advancedZrtpButton, FALSE); + gtk_widget_set_sensitive(zrtp_button, sensitive); } - static void use_sip_tls_cb(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { DEBUG("Using sips"); gtk_widget_set_sensitive(data, TRUE); // Uncheck stun - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(useStunCheckBox), FALSE); - gtk_widget_set_sensitive(useStunCheckBox, FALSE); - gtk_widget_set_sensitive(sameAsLocalRadioButton, TRUE); - gtk_widget_set_sensitive(publishedAddrRadioButton, TRUE); - gtk_widget_hide(stunServerLabel); - gtk_widget_hide(stunServerEntry); - - if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton))) { - gtk_widget_show(publishedAddressEntry); - gtk_widget_show(publishedPortSpinBox); - gtk_widget_show(publishedAddressLabel); - gtk_widget_show(publishedPortLabel); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_stun_check_box), FALSE); + gtk_widget_set_sensitive(use_stun_check_box, FALSE); + gtk_widget_set_sensitive(same_as_local_radio_button, TRUE); + gtk_widget_set_sensitive(published_addr_radio_button, TRUE); + gtk_widget_set_sensitive(stun_server_entry, FALSE); + + if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button))) { + gtk_widget_show(published_address_entry); + gtk_widget_show(published_port_spin_box); + gtk_widget_show(published_address_label); + gtk_widget_show(published_port_label); } } else { gtk_widget_set_sensitive(data, FALSE); - gtk_widget_set_sensitive(useStunCheckBox, TRUE); - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(useStunCheckBox))) { - gtk_widget_set_sensitive(sameAsLocalRadioButton, FALSE); - gtk_widget_set_sensitive(publishedAddrRadioButton, FALSE); - gtk_widget_show(stunServerLabel); - gtk_widget_show(stunServerEntry); - gtk_widget_hide(publishedAddressEntry); - gtk_widget_hide(publishedPortSpinBox); - gtk_widget_hide(publishedAddressLabel); - gtk_widget_hide(publishedPortLabel); + gtk_widget_set_sensitive(use_stun_check_box, TRUE); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_stun_check_box))) { + gtk_widget_set_sensitive(same_as_local_radio_button, FALSE); + gtk_widget_set_sensitive(published_addr_radio_button, FALSE); + gtk_widget_show(stun_server_label); + gtk_widget_show(stun_server_entry); + gtk_widget_set_sensitive(stun_server_entry, TRUE); + gtk_widget_hide(published_address_entry); + gtk_widget_hide(published_port_spin_box); + gtk_widget_hide(published_address_label); + gtk_widget_hide(published_port_label); } else { - gtk_widget_set_sensitive(sameAsLocalRadioButton, TRUE); - gtk_widget_set_sensitive(publishedAddrRadioButton, TRUE); - gtk_widget_hide(stunServerLabel); - gtk_widget_hide(stunServerEntry); + gtk_widget_set_sensitive(same_as_local_radio_button, TRUE); + gtk_widget_set_sensitive(published_addr_radio_button, TRUE); + gtk_widget_set_sensitive(stun_server_entry, FALSE); } } } @@ -538,7 +532,8 @@ static void use_sip_tls_cb(GtkWidget *widget, gpointer data) static gchar * get_interface_addr_from_name(const gchar * const iface_name) { -#define UC(b) (((int)b)&0xff) + g_assert(iface_name); +#define UC(b) (((int)b)&0xff) int fd; @@ -570,12 +565,16 @@ get_interface_addr_from_name(const gchar * const iface_name) static void local_interface_changed_cb(GtkWidget * widget UNUSED, gpointer data UNUSED) { - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton))) { - gchar *local_iface_name = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo)); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button))) { + gchar *local_iface_name = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); + if (!local_iface_name) { + ERROR("Could not get local interface name"); + return; + } gchar *local_iface_addr = get_interface_addr_from_name(local_iface_name); - gtk_entry_set_text(GTK_ENTRY(localAddressEntry), local_iface_addr); - gtk_entry_set_text(GTK_ENTRY(publishedAddressEntry), local_iface_addr); + gtk_entry_set_text(GTK_ENTRY(local_address_entry), local_iface_addr); + gtk_entry_set_text(GTK_ENTRY(published_address_entry), local_iface_addr); g_free(local_iface_addr); g_free(local_iface_name); } @@ -584,222 +583,221 @@ static void local_interface_changed_cb(GtkWidget * widget UNUSED, gpointer data static void set_published_addr_manually_cb(GtkWidget * widget, gpointer data UNUSED) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { - DEBUG("Config: Showing manual publishing options"); - gtk_widget_show(publishedPortLabel); - gtk_widget_show(publishedPortSpinBox); - gtk_widget_show(publishedAddressLabel); - gtk_widget_show(publishedAddressEntry); + DEBUG("Showing manual publishing options"); + gtk_widget_show(published_port_label); + gtk_widget_show(published_port_spin_box); + gtk_widget_show(published_address_label); + gtk_widget_show(published_address_entry); } else { - DEBUG("Config: Hiding manual publishing options"); - gtk_widget_hide(publishedPortLabel); - gtk_widget_hide(publishedPortSpinBox); - gtk_widget_hide(publishedAddressLabel); - gtk_widget_hide(publishedAddressEntry); + DEBUG("Hiding manual publishing options"); + gtk_widget_hide(published_port_label); + gtk_widget_hide(published_port_spin_box); + gtk_widget_hide(published_address_label); + gtk_widget_hide(published_address_entry); } } static void use_stun_cb(GtkWidget *widget, gpointer data UNUSED) { + /* Widgets have not been created yet */ + if (!stun_server_label) + return; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { - DEBUG("Config: Showing stun options, hiding Local/Published info"); - gtk_widget_show(stunServerLabel); - gtk_widget_show(stunServerEntry); - gtk_widget_set_sensitive(sameAsLocalRadioButton, FALSE); - gtk_widget_set_sensitive(publishedAddrRadioButton, FALSE); - - gtk_widget_hide(publishedAddressLabel); - gtk_widget_hide(publishedPortLabel); - gtk_widget_hide(publishedAddressEntry); - gtk_widget_hide(publishedPortSpinBox); + DEBUG("Showing stun options, hiding Local/Published info"); + gtk_widget_show(stun_server_label); + gtk_widget_show(stun_server_entry); + gtk_widget_set_sensitive(stun_server_entry, TRUE); + gtk_widget_set_sensitive(same_as_local_radio_button, FALSE); + gtk_widget_set_sensitive(published_addr_radio_button, FALSE); + + gtk_widget_hide(published_address_label); + gtk_widget_hide(published_port_label); + gtk_widget_hide(published_address_entry); + gtk_widget_hide(published_port_spin_box); } else { - DEBUG("Config: hiding stun options, showing Local/Published info"); - gtk_widget_hide(stunServerLabel); - gtk_widget_hide(stunServerEntry); - gtk_widget_set_sensitive(sameAsLocalRadioButton, TRUE); - gtk_widget_set_sensitive(publishedAddrRadioButton, TRUE); - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(publishedAddrRadioButton))) { - gtk_widget_show(publishedAddressLabel); - gtk_widget_show(publishedPortLabel); - gtk_widget_show(publishedAddressEntry); - gtk_widget_show(publishedPortSpinBox); + DEBUG("disabling stun options, showing Local/Published info"); + gtk_widget_set_sensitive(stun_server_entry, FALSE); + gtk_widget_set_sensitive(same_as_local_radio_button, TRUE); + gtk_widget_set_sensitive(published_addr_radio_button, TRUE); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(published_addr_radio_button))) { + gtk_widget_show(published_address_label); + gtk_widget_show(published_port_label); + gtk_widget_show(published_address_entry); + gtk_widget_show(published_port_spin_box); } } - - DEBUG("DONE"); } static void same_as_local_cb(GtkWidget * widget, gpointer data UNUSED) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { - gchar *local_interface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo)); + gchar *local_interface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); gchar *local_address = dbus_get_address_from_interface_name(local_interface); - gtk_entry_set_text(GTK_ENTRY(publishedAddressEntry), local_address); + gtk_entry_set_text(GTK_ENTRY(published_address_entry), local_address); - const gchar * local_port = gtk_entry_get_text(GTK_ENTRY(localPortSpinBox)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(publishedPortSpinBox), g_ascii_strtod(local_port, NULL)); + const gchar * local_port = gtk_entry_get_text(GTK_ENTRY(local_port_spin_box)); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(published_port_spin_box), g_ascii_strtod(local_port, NULL)); g_free(local_interface); } } -GtkWidget* create_credential_widget(account_t *a) +static GtkWidget* create_credential_widget(const account_t *account) { - - GtkWidget *frame, *table, *scrolledWindowCredential, *addButton; - GtkCellRenderer * renderer; - GtkTreeViewColumn * treeViewColumn; - GtkTreeSelection * treeSelection; - /* Credentials tree view */ + GtkWidget *frame, *table; gnome_main_section_new_with_table(_("Credential"), &frame, &table, 1, 1); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 10); - scrolledWindowCredential = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindowCredential), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledWindowCredential), GTK_SHADOW_IN); - gtk_table_attach_defaults(GTK_TABLE(table), scrolledWindowCredential, 0, 1, 0, 1); + GtkWidget *scrolled_window_credential = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window_credential), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window_credential), GTK_SHADOW_IN); + gtk_table_attach_defaults(GTK_TABLE(table), scrolled_window_credential, 0, 1, 0, 1); - credentialStore = gtk_list_store_new(COLUMN_CREDENTIAL_COUNT, + credential_store = gtk_list_store_new(COLUMN_CREDENTIAL_COUNT, G_TYPE_STRING, // Realm G_TYPE_STRING, // Username G_TYPE_STRING, // Password G_TYPE_POINTER // Pointer to the Objectc - ); + ); - treeViewCredential = gtk_tree_view_new_with_model(GTK_TREE_MODEL(credentialStore)); - treeSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeViewCredential)); - g_signal_connect(G_OBJECT(treeSelection), "changed", G_CALLBACK(select_credential_cb), credentialStore); + treeview_credential = gtk_tree_view_new_with_model(GTK_TREE_MODEL(credential_store)); + GtkTreeSelection * tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_credential)); + g_signal_connect(G_OBJECT(tree_selection), "changed", G_CALLBACK(select_credential_cb), credential_store); - renderer = gtk_cell_renderer_text_new(); + GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); g_object_set(renderer, "editable", TRUE, "editable-set", TRUE, NULL); - g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credentialStore); + g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credential_store); g_object_set_data(G_OBJECT(renderer), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_REALM)); - treeViewColumn = gtk_tree_view_column_new_with_attributes("Realm", - renderer, - "markup", COLUMN_CREDENTIAL_REALM, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeViewCredential), treeViewColumn); + + GtkTreeViewColumn *tree_view_column = gtk_tree_view_column_new_with_attributes("Realm", renderer, "markup", COLUMN_CREDENTIAL_REALM, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_credential), tree_view_column); renderer = gtk_cell_renderer_text_new(); g_object_set(renderer, "editable", TRUE, "editable-set", TRUE, NULL); - g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credentialStore); + g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credential_store); g_object_set_data(G_OBJECT(renderer), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_USERNAME)); - treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Authentication name"), + tree_view_column = gtk_tree_view_column_new_with_attributes(_("Authentication name"), renderer, "markup", COLUMN_CREDENTIAL_USERNAME, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeViewCredential), treeViewColumn); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_credential), tree_view_column); renderer = gtk_cell_renderer_text_new(); g_object_set(renderer, "editable", TRUE, "editable-set", TRUE, NULL); - g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credentialStore); + g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credential_store); g_signal_connect(renderer, "editing-started", G_CALLBACK(editing_started_cb), NULL); g_object_set_data(G_OBJECT(renderer), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_PASSWORD)); - treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Password"), - renderer, - "markup", COLUMN_CREDENTIAL_PASSWORD, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeViewCredential), treeViewColumn); + tree_view_column = gtk_tree_view_column_new_with_attributes(_("Password"), + renderer, "markup", COLUMN_CREDENTIAL_PASSWORD, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_credential), tree_view_column); - gtk_container_add(GTK_CONTAINER(scrolledWindowCredential), treeViewCredential); + gtk_container_add(GTK_CONTAINER(scrolled_window_credential), treeview_credential); - fill_treeview_with_credential(a); + fill_treeview_with_credential(account); /* Credential Buttons */ GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 3, 1, 2); - addButton = gtk_button_new_from_stock(GTK_STOCK_ADD); - g_signal_connect(addButton, "clicked", G_CALLBACK(add_credential_cb), credentialStore); + GtkWidget *addButton = gtk_button_new_from_stock(GTK_STOCK_ADD); + g_signal_connect(addButton, "clicked", G_CALLBACK(add_credential_cb), credential_store); gtk_box_pack_start(GTK_BOX(hbox), addButton, FALSE, FALSE, 0); - deleteCredButton = gtk_button_new_from_stock(GTK_STOCK_REMOVE); - g_signal_connect(deleteCredButton, "clicked", G_CALLBACK(delete_credential_cb), treeViewCredential); - gtk_box_pack_start(GTK_BOX(hbox), deleteCredButton, FALSE, FALSE, 0); + delete_cred_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + g_signal_connect(delete_cred_button, "clicked", G_CALLBACK(delete_credential_cb), treeview_credential); + gtk_box_pack_start(GTK_BOX(hbox), delete_cred_button, FALSE, FALSE, 0); /* Dynamically resize the window to fit the scrolled window */ - gtk_widget_set_size_request(scrolledWindowCredential, 400, 120); + gtk_widget_set_size_request(scrolled_window_credential, 400, 120); return frame; } -GtkWidget* create_security_widget(account_t *a) +static GtkWidget* +create_security_widget(const account_t *account) { - - GtkWidget *frame, *table, *sipTlsAdvancedButton, *label; - gchar *curSRTPEnabled = NULL, *curKeyExchange = NULL, *curTLSEnabled = NULL; + gchar *curSRTPEnabled = NULL, *curKeyExchange = NULL, + *curTLSEnabled = NULL; // Load from SIP/IAX/Unknown ? - if (a) { - curKeyExchange = g_hash_table_lookup(a->properties, ACCOUNT_KEY_EXCHANGE); - + if (account && account->properties) { + curKeyExchange = account_lookup(account, ACCOUNT_KEY_EXCHANGE); if (curKeyExchange == NULL) curKeyExchange = "none"; - curSRTPEnabled = g_hash_table_lookup(a->properties, ACCOUNT_SRTP_ENABLED); + curSRTPEnabled = account_lookup(account, ACCOUNT_SRTP_ENABLED); if (curSRTPEnabled == NULL) curSRTPEnabled = "false"; - curTLSEnabled = g_hash_table_lookup(a->properties, TLS_ENABLE); + curTLSEnabled = account_lookup(account, TLS_ENABLE); if (curTLSEnabled == NULL) curTLSEnabled = "false"; } + GtkWidget *frame, *table; gnome_main_section_new_with_table(_("Security"), &frame, &table, 2, 3); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); /* TLS subsection */ - sipTlsAdvancedButton = gtk_button_new_from_stock(GTK_STOCK_EDIT); - gtk_table_attach_defaults(GTK_TABLE(table), sipTlsAdvancedButton, 2, 3, 0, 1); - gtk_widget_set_sensitive(sipTlsAdvancedButton, FALSE); - g_signal_connect(G_OBJECT(sipTlsAdvancedButton), "clicked", G_CALLBACK(show_advanced_tls_options_cb),a->properties); - - useSipTlsCheckBox = gtk_check_button_new_with_mnemonic(_("Use TLS transport(sips)")); - g_signal_connect(useSipTlsCheckBox, "toggled", G_CALLBACK(use_sip_tls_cb), sipTlsAdvancedButton); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(useSipTlsCheckBox),(g_strcmp0(curTLSEnabled, "true") == 0) ? TRUE:FALSE); - gtk_table_attach_defaults(GTK_TABLE(table), useSipTlsCheckBox, 0, 2, 0, 1); + GtkWidget *sip_tls_advanced_button = gtk_button_new_from_stock(GTK_STOCK_EDIT); + gtk_table_attach_defaults(GTK_TABLE(table), sip_tls_advanced_button, 2, 3, 0, 1); + gtk_widget_set_sensitive(sip_tls_advanced_button, FALSE); + g_signal_connect(G_OBJECT(sip_tls_advanced_button), "clicked", + G_CALLBACK(show_advanced_tls_options_cb), + (gpointer) account); + + use_sip_tls_check_box = gtk_check_button_new_with_mnemonic(_("Use TLS transport(sips)")); + g_signal_connect(use_sip_tls_check_box, "toggled", G_CALLBACK(use_sip_tls_cb), sip_tls_advanced_button); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_sip_tls_check_box), + g_strcmp0(curTLSEnabled, "true") == 0); + gtk_table_attach_defaults(GTK_TABLE(table), use_sip_tls_check_box, 0, 2, 0, 1); /* ZRTP subsection */ - label = gtk_label_new_with_mnemonic(_("SRTP key exchange")); + GtkWidget *label = gtk_label_new_with_mnemonic(_("SRTP key exchange")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - keyExchangeCombo = gtk_combo_box_text_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), keyExchangeCombo); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo), "ZRTP"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo), "SDES"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo), _("Disabled")); + key_exchange_combo = gtk_combo_box_text_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), key_exchange_combo); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(key_exchange_combo), "ZRTP"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(key_exchange_combo), "SDES"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(key_exchange_combo), _("Disabled")); - advancedZrtpButton = gtk_button_new_from_stock(GTK_STOCK_PREFERENCES); - g_signal_connect(G_OBJECT(advancedZrtpButton), "clicked", G_CALLBACK(show_advanced_zrtp_options_cb),a->properties); + zrtp_button = gtk_button_new_from_stock(GTK_STOCK_PREFERENCES); + g_signal_connect(G_OBJECT(zrtp_button), "clicked", + G_CALLBACK(show_advanced_zrtp_options_cb), + (gpointer) account); if (g_strcmp0(curSRTPEnabled, "false") == 0) { - gtk_combo_box_set_active(GTK_COMBO_BOX(keyExchangeCombo), 2); - gtk_widget_set_sensitive(advancedZrtpButton, FALSE); + gtk_combo_box_set_active(GTK_COMBO_BOX(key_exchange_combo), 2); + gtk_widget_set_sensitive(zrtp_button, FALSE); } else { if (g_strcmp0(curKeyExchange, ZRTP) == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(keyExchangeCombo),0); + gtk_combo_box_set_active(GTK_COMBO_BOX(key_exchange_combo),0); else if (g_strcmp0(curKeyExchange, SDES) == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(keyExchangeCombo),1); + gtk_combo_box_set_active(GTK_COMBO_BOX(key_exchange_combo),1); else { - gtk_combo_box_set_active(GTK_COMBO_BOX(keyExchangeCombo), 2); - gtk_widget_set_sensitive(advancedZrtpButton, FALSE); + gtk_combo_box_set_active(GTK_COMBO_BOX(key_exchange_combo), 2); + gtk_widget_set_sensitive(zrtp_button, FALSE); } } - g_signal_connect(G_OBJECT(GTK_COMBO_BOX(keyExchangeCombo)), "changed", G_CALLBACK(key_exchange_changed_cb), a); + g_signal_connect(G_OBJECT(GTK_COMBO_BOX(key_exchange_combo)), "changed", + G_CALLBACK(key_exchange_changed_cb), NULL); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); - gtk_table_attach_defaults(GTK_TABLE(table), keyExchangeCombo, 1, 2, 1, 2); - gtk_table_attach_defaults(GTK_TABLE(table), advancedZrtpButton, 2, 3, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(table), key_exchange_combo, 1, 2, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(table), zrtp_button, 2, 3, 1, 2); gtk_widget_show_all(table); @@ -807,20 +805,17 @@ GtkWidget* create_security_widget(account_t *a) } -GtkWidget * create_security_tab(account_t *a) +static GtkWidget * create_security_tab(const account_t *account) { - GtkWidget * frame; - GtkWidget * ret; - - ret = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); + GtkWidget * ret = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_set_border_width(GTK_CONTAINER(ret), 10); // Credentials frame - frame = create_credential_widget(a); + GtkWidget * frame = create_credential_widget(account); gtk_box_pack_start(GTK_BOX(ret), frame, FALSE, FALSE, 0); // Security frame - frame = create_security_widget(a); + frame = create_security_widget(account); gtk_box_pack_start(GTK_BOX(ret), frame, FALSE, FALSE, 0); gtk_widget_show_all(ret); @@ -828,63 +823,55 @@ GtkWidget * create_security_tab(account_t *a) return ret; } -static GtkWidget* create_registration_expire(account_t *a) +static GtkWidget* create_registration_expire(const account_t *account) { + gchar *account_expire = NULL; + void *orig_key = NULL; + if (account && account->properties) + if (!g_hash_table_lookup_extended(account->properties, ACCOUNT_REGISTRATION_EXPIRE, + &orig_key, (gpointer) &account_expire)) + ERROR("Could not retrieve %s from account properties", + ACCOUNT_REGISTRATION_EXPIRE); - GtkWidget *table, *frame, *label; - - gchar *resolve_once=NULL, *account_expire=NULL; - - if (a) { - resolve_once = g_hash_table_lookup(a->properties, ACCOUNT_RESOLVE_ONCE); - account_expire = g_hash_table_lookup(a->properties, ACCOUNT_REGISTRATION_EXPIRE); - } - + GtkWidget *table, *frame; gnome_main_section_new_with_table(_("Registration"), &frame, &table, 2, 3); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 5); - label = gtk_label_new_with_mnemonic(_("Registration expire")); + GtkWidget *label = gtk_label_new_with_mnemonic(_("Registration expire")); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - expireSpinBox = gtk_spin_button_new_with_range(1, 65535, 1); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), expireSpinBox); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(expireSpinBox), g_ascii_strtod(account_expire, NULL)); - gtk_table_attach_defaults(GTK_TABLE(table), expireSpinBox, 1, 2, 0, 1); - - - entryResolveNameOnlyOnce = gtk_check_button_new_with_mnemonic(_("_Comply with RFC 3263")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(entryResolveNameOnlyOnce), - g_strcasecmp(resolve_once,"false") == 0 ? TRUE: FALSE); - gtk_table_attach_defaults(GTK_TABLE(table), entryResolveNameOnlyOnce, 0, 2, 1, 2); - gtk_widget_set_sensitive(entryResolveNameOnlyOnce , TRUE); + expire_spin_box = gtk_spin_button_new_with_range(1, 65535, 1); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), expire_spin_box); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(expire_spin_box), g_ascii_strtod(account_expire, NULL)); + gtk_table_attach_defaults(GTK_TABLE(table), expire_spin_box, 1, 2, 0, 1); return frame; } -GtkWidget* create_network(account_t *a) +static GtkWidget* +create_network(const account_t *account) { - GtkWidget *table, *frame, *label; gchar *local_interface = NULL; gchar *local_port = NULL; - if (a) { - local_interface = g_hash_table_lookup(a->properties, LOCAL_INTERFACE); - local_port = g_hash_table_lookup(a->properties, LOCAL_PORT); + if (account) { + local_interface = account_lookup(account, LOCAL_INTERFACE); + local_port = account_lookup(account, LOCAL_PORT); } + GtkWidget *table, *frame; gnome_main_section_new_with_table(_("Network Interface"), &frame, &table, 2, 3); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 5); /** - * Retreive the list of IP interface from the + * Retrieve the list of IP interface from the * the daemon and build the combo box. */ - localAddressCombo = gtk_combo_box_text_new(); - + local_address_combo = gtk_combo_box_text_new(); - label = gtk_label_new_with_mnemonic(_("Local address")); + GtkWidget *label = gtk_label_new_with_mnemonic(_("Local address")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); @@ -892,46 +879,47 @@ GtkWidget* create_network(account_t *a) int idx = 0; for (gchar **iface = iface_list; iface && *iface; iface++, idx++) { - - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(localAddressCombo), NULL, *iface); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(local_address_combo), *iface); if (g_strcmp0(*iface, local_interface) == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(localAddressCombo), idx); + gtk_combo_box_set_active(GTK_COMBO_BOX(local_address_combo), idx); } if (!local_interface) - gtk_combo_box_set_active(GTK_COMBO_BOX(localAddressCombo), 0); - + gtk_combo_box_set_active(GTK_COMBO_BOX(local_address_combo), 0); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), localAddressCombo); - gtk_table_attach(GTK_TABLE(table), localAddressCombo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), local_address_combo); + gtk_table_attach(GTK_TABLE(table), local_address_combo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); // Fill the text entry with the ip address of local interface selected - localAddressEntry = gtk_entry_new(); - gchar *local_iface_name = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo)); + local_address_entry = gtk_entry_new(); + gchar *local_iface_name = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); + if (!local_iface_name) { + ERROR("Could not get local interface name"); + return frame; + } gchar *local_iface_addr = get_interface_addr_from_name(local_iface_name); g_free(local_iface_name); - gtk_entry_set_text(GTK_ENTRY(localAddressEntry), local_iface_addr); + gtk_entry_set_text(GTK_ENTRY(local_address_entry), local_iface_addr); g_free(local_iface_addr); - gtk_widget_set_sensitive(localAddressEntry, FALSE); - gtk_table_attach(GTK_TABLE(table), localAddressEntry, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_set_sensitive(local_address_entry, FALSE); + gtk_table_attach(GTK_TABLE(table), local_address_entry, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); // Local port widget label = gtk_label_new_with_mnemonic(_("Local port")); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - localPortSpinBox = gtk_spin_button_new_with_range(1, 65535, 1); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), localPortSpinBox); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(localPortSpinBox), g_ascii_strtod(local_port, NULL)); + local_port_spin_box = gtk_spin_button_new_with_range(1, 65535, 1); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), local_port_spin_box); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(local_port_spin_box), g_ascii_strtod(local_port, NULL)); - gtk_table_attach_defaults(GTK_TABLE(table), localPortSpinBox, 1, 2, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(table), local_port_spin_box, 1, 2, 1, 2); return frame; } -GtkWidget* create_published_address(account_t *a) +GtkWidget* create_published_address(const account_t *account) { - GtkWidget *table, *frame; - gchar *use_tls =NULL; + gchar *use_tls = NULL; gchar *published_address = NULL; gchar *published_port = NULL; gchar *stun_enable = NULL; @@ -939,132 +927,126 @@ GtkWidget* create_published_address(account_t *a) gchar *published_sameas_local = NULL; // Get the user configuration - if (a) { - - use_tls = g_hash_table_lookup(a->properties, TLS_ENABLE); - published_sameas_local = g_hash_table_lookup(a->properties, PUBLISHED_SAMEAS_LOCAL); + if (account) { + use_tls = account_lookup(account, TLS_ENABLE); + published_sameas_local = account_lookup(account, PUBLISHED_SAMEAS_LOCAL); - if (g_strcasecmp(published_sameas_local, "true") == 0) { - published_address = dbus_get_address_from_interface_name(g_hash_table_lookup(a->properties, LOCAL_INTERFACE)); - published_port = g_hash_table_lookup(a->properties, LOCAL_PORT); + if (utf8_case_equal(published_sameas_local, "true")) { + published_address = dbus_get_address_from_interface_name(account_lookup(account, LOCAL_INTERFACE)); + published_port = account_lookup(account, LOCAL_PORT); } else { - published_address = g_hash_table_lookup(a->properties, PUBLISHED_ADDRESS); - published_port = g_hash_table_lookup(a->properties, PUBLISHED_PORT); + published_address = account_lookup(account, PUBLISHED_ADDRESS); + published_port = account_lookup(account, PUBLISHED_PORT); } - stun_enable = g_hash_table_lookup(a->properties, ACCOUNT_SIP_STUN_ENABLED); - stun_server = g_hash_table_lookup(a->properties, ACCOUNT_SIP_STUN_SERVER); - published_sameas_local = g_hash_table_lookup(a->properties, PUBLISHED_SAMEAS_LOCAL); + stun_enable = account_lookup(account, ACCOUNT_SIP_STUN_ENABLED); + stun_server = account_lookup(account, ACCOUNT_SIP_STUN_SERVER); + published_sameas_local = account_lookup(account, PUBLISHED_SAMEAS_LOCAL); } gnome_main_section_new_with_table(_("Published address"), &frame, &table, 2, 3); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 5); - useStunCheckBox = gtk_check_button_new_with_mnemonic(_("Using STUN")); - gtk_table_attach_defaults(GTK_TABLE(table), useStunCheckBox, 0, 1, 0, 1); - g_signal_connect(useStunCheckBox, "toggled", G_CALLBACK(use_stun_cb), a); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(useStunCheckBox), - g_strcasecmp(stun_enable, "true") == 0 ? TRUE: FALSE); - gtk_widget_set_sensitive(useStunCheckBox, - g_strcasecmp(use_tls, "true") == 0 ? FALSE: TRUE); - - stunServerLabel = gtk_label_new_with_mnemonic(_("STUN server URL")); - gtk_table_attach_defaults(GTK_TABLE(table), stunServerLabel, 0, 1, 1, 2); - gtk_misc_set_alignment(GTK_MISC(stunServerLabel), 0, 0.5); - stunServerEntry = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(stunServerLabel), stunServerEntry); - gtk_entry_set_text(GTK_ENTRY(stunServerEntry), stun_server); - gtk_table_attach_defaults(GTK_TABLE(table), stunServerEntry, 1, 2, 1, 2); - - sameAsLocalRadioButton = gtk_radio_button_new_with_mnemonic_from_widget(NULL, _("Same as local parameters")); - gtk_table_attach_defaults(GTK_TABLE(table), sameAsLocalRadioButton, 0, 2, 3, 4); - - publishedAddrRadioButton = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(sameAsLocalRadioButton), _("Set published address and port:")); - gtk_table_attach_defaults(GTK_TABLE(table), publishedAddrRadioButton, 0, 2, 4, 5); - - if (g_strcasecmp(published_sameas_local, "true") == 0) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton), TRUE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(publishedAddrRadioButton), FALSE); + use_stun_check_box = gtk_check_button_new_with_mnemonic(_("Using STUN")); + gtk_table_attach_defaults(GTK_TABLE(table), use_stun_check_box, 0, 1, 0, 1); + g_signal_connect(use_stun_check_box, "toggled", G_CALLBACK(use_stun_cb), NULL); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_stun_check_box), + utf8_case_equal(stun_enable, "true")); + gtk_widget_set_sensitive(use_stun_check_box, !utf8_case_equal(use_tls, "true")); + + stun_server_label = gtk_label_new_with_mnemonic(_("STUN server URL")); + gtk_table_attach_defaults(GTK_TABLE(table), stun_server_label, 0, 1, 1, 2); + gtk_misc_set_alignment(GTK_MISC(stun_server_label), 0, 0.5); + stun_server_entry = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(stun_server_label), stun_server_entry); + gtk_entry_set_text(GTK_ENTRY(stun_server_entry), stun_server); + gtk_table_attach_defaults(GTK_TABLE(table), stun_server_entry, 1, 2, 1, 2); + + same_as_local_radio_button = gtk_radio_button_new_with_mnemonic_from_widget(NULL, _("Same as local parameters")); + gtk_table_attach_defaults(GTK_TABLE(table), same_as_local_radio_button, 0, 2, 3, 4); + + published_addr_radio_button = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(same_as_local_radio_button), _("Set published address and port:")); + gtk_table_attach_defaults(GTK_TABLE(table), published_addr_radio_button, 0, 2, 4, 5); + + if (utf8_case_equal(published_sameas_local, "true")) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button), TRUE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(published_addr_radio_button), FALSE); } else { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton), FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(publishedAddrRadioButton), TRUE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(published_addr_radio_button), TRUE); } - publishedAddressLabel = gtk_label_new_with_mnemonic(_("Published address")); - gtk_table_attach_defaults(GTK_TABLE(table), publishedAddressLabel, 0, 1, 5, 6); - gtk_misc_set_alignment(GTK_MISC(publishedAddressLabel), 0, 0.5); - publishedAddressEntry = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(publishedAddressLabel), publishedAddressEntry); + published_address_label = gtk_label_new_with_mnemonic(_("Published address")); + gtk_table_attach_defaults(GTK_TABLE(table), published_address_label, 0, 1, 5, 6); + gtk_misc_set_alignment(GTK_MISC(published_address_label), 0, 0.5); + published_address_entry = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(published_address_label), published_address_entry); - gtk_entry_set_text(GTK_ENTRY(publishedAddressEntry), published_address); - gtk_table_attach_defaults(GTK_TABLE(table), publishedAddressEntry, 1, 2, 5, 6); + gtk_entry_set_text(GTK_ENTRY(published_address_entry), published_address); + gtk_table_attach_defaults(GTK_TABLE(table), published_address_entry, 1, 2, 5, 6); - publishedPortLabel = gtk_label_new_with_mnemonic(_("Published port")); - gtk_table_attach_defaults(GTK_TABLE(table), publishedPortLabel, 0, 1, 6, 7); - gtk_misc_set_alignment(GTK_MISC(publishedPortLabel), 0, 0.5); - publishedPortSpinBox = gtk_spin_button_new_with_range(1, 65535, 1); - gtk_label_set_mnemonic_widget(GTK_LABEL(publishedPortLabel), publishedPortSpinBox); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(publishedPortSpinBox), g_ascii_strtod(published_port, NULL)); + published_port_label = gtk_label_new_with_mnemonic(_("Published port")); + gtk_table_attach_defaults(GTK_TABLE(table), published_port_label, 0, 1, 6, 7); + gtk_misc_set_alignment(GTK_MISC(published_port_label), 0, 0.5); + published_port_spin_box = gtk_spin_button_new_with_range(1, 65535, 1); + gtk_label_set_mnemonic_widget(GTK_LABEL(published_port_label), published_port_spin_box); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(published_port_spin_box), g_ascii_strtod(published_port, NULL)); - gtk_table_attach_defaults(GTK_TABLE(table), publishedPortSpinBox, 1, 2, 6, 7); + gtk_table_attach_defaults(GTK_TABLE(table), published_port_spin_box, 1, 2, 6, 7); // This will trigger a signal, and the above two // widgets need to be instanciated before that. - g_signal_connect(localAddressCombo, "changed", G_CALLBACK(local_interface_changed_cb), localAddressCombo); + g_signal_connect(local_address_combo, "changed", G_CALLBACK(local_interface_changed_cb), local_address_combo); + g_signal_connect(same_as_local_radio_button, "toggled", G_CALLBACK(same_as_local_cb), same_as_local_radio_button); + g_signal_connect(published_addr_radio_button, "toggled", G_CALLBACK(set_published_addr_manually_cb), published_addr_radio_button); - - g_signal_connect(sameAsLocalRadioButton, "toggled", G_CALLBACK(same_as_local_cb), sameAsLocalRadioButton); - g_signal_connect(publishedAddrRadioButton, "toggled", G_CALLBACK(set_published_addr_manually_cb), publishedAddrRadioButton); - - set_published_addr_manually_cb(publishedAddrRadioButton, NULL); + set_published_addr_manually_cb(published_addr_radio_button, NULL); return frame; } -GtkWidget* create_advanced_tab(account_t *a) +GtkWidget* create_advanced_tab(const account_t *account) { - // Build the advanced tab, to appear on the account configuration panel - DEBUG("Config: Build advanced tab"); + DEBUG("Build advanced tab"); - GtkWidget *vbox, *frame; - - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); + GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); - frame = create_registration_expire(a); + GtkWidget *frame = create_registration_expire(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - frame = create_network(a); + frame = create_network(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - frame = create_published_address(a); + frame = create_published_address(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); gtk_widget_show_all(vbox); - use_stun_cb(useStunCheckBox, NULL); + use_stun_cb(use_stun_check_box, NULL); - set_published_addr_manually_cb(publishedAddrRadioButton, NULL); + set_published_addr_manually_cb(published_addr_radio_button, NULL); return vbox; } -void ringtone_enabled(GtkWidget *widget UNUSED, gpointer data, const gchar *accountID UNUSED) +static void ringtone_enabled_cb(GtkWidget *widget UNUSED, gpointer data, const gchar *accountID UNUSED) { /* toggle sensitivity */ gtk_widget_set_sensitive(data, !gtk_widget_is_sensitive(data)); } -static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) +static GtkWidget* +create_audiocodecs_configuration(const account_t *account) { GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); - GtkWidget *box = audiocodecs_box(currentAccount); + GtkWidget *box = audiocodecs_box(account); // Box for the audiocodecs GtkWidget *audiocodecs = gnome_main_section_new(_("Audio")); @@ -1074,25 +1056,18 @@ static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) gtk_container_add(GTK_CONTAINER(audiocodecs), box); // Add DTMF type selection for SIP account only - gpointer p = g_hash_table_lookup(currentAccount->properties, ACCOUNT_TYPE); - GtkWidget *table; - if (g_strcmp0(p, "SIP") == 0) { + if (account_is_SIP(account)) { // Box for dtmf GtkWidget *dtmf; gnome_main_section_new_with_table(_("DTMF"), &dtmf, &table, 1, 2); gtk_box_pack_start(GTK_BOX(vbox), dtmf, FALSE, FALSE, 0); gtk_widget_show(dtmf); - const gchar * const currentDtmfType = g_hash_table_lookup(currentAccount->properties, ACCOUNT_DTMF_TYPE); - - gboolean dtmf_are_rtp = TRUE; - - if (g_strcasecmp(currentDtmfType, OVERRTP) != 0) - dtmf_are_rtp = FALSE; - overrtp = gtk_radio_button_new_with_label(NULL, _("RTP")); + const gchar * const dtmf_type = account_lookup(account, ACCOUNT_DTMF_TYPE); + const gboolean dtmf_are_rtp = utf8_case_equal(dtmf_type, OVERRTP); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(overrtp), dtmf_are_rtp); gtk_table_attach(GTK_TABLE(table), overrtp, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); @@ -1107,21 +1082,20 @@ static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) gnome_main_section_new_with_table(_("Ringtones"), &frame, &table, 1, 2); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - fileChooser = gtk_file_chooser_button_new(_("Choose a ringtone"), GTK_FILE_CHOOSER_ACTION_OPEN); + file_chooser = gtk_file_chooser_button_new(_("Choose a ringtone"), GTK_FILE_CHOOSER_ACTION_OPEN); - p = g_hash_table_lookup(currentAccount->properties, CONFIG_RINGTONE_ENABLED); - gboolean ringtoneEnabled =(g_strcmp0(p, "true") == 0) ? TRUE : FALSE; - - enableTone = gtk_check_button_new_with_mnemonic(_("_Enable ringtones")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableTone), ringtoneEnabled); - g_signal_connect(G_OBJECT(enableTone) , "clicked" , G_CALLBACK(ringtone_enabled), fileChooser); - gtk_table_attach(GTK_TABLE(table), enableTone, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gpointer ptr = account_lookup(account, CONFIG_RINGTONE_ENABLED); + enable_tone = gtk_check_button_new_with_mnemonic(_("_Enable ringtones")); + const gboolean ringtone_enabled = g_strcmp0(ptr, "true") == 0; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_tone), ringtone_enabled); + g_signal_connect(G_OBJECT(enable_tone) , "clicked", G_CALLBACK(ringtone_enabled_cb), file_chooser); + gtk_table_attach(GTK_TABLE(table), enable_tone, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); // file chooser button - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser) , g_get_home_dir()); - p = g_hash_table_lookup(currentAccount->properties, CONFIG_RINGTONE_PATH); - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser) , p); - gtk_widget_set_sensitive(fileChooser, ringtoneEnabled); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser) , g_get_home_dir()); + ptr = account_lookup(account, CONFIG_RINGTONE_PATH); + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(file_chooser) , ptr); + gtk_widget_set_sensitive(file_chooser, ringtone_enabled); GtkFileFilter *filter = gtk_file_filter_new(); gtk_file_filter_set_name(filter, _("Audio Files")); @@ -1129,15 +1103,16 @@ static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) gtk_file_filter_add_pattern(filter, "*.ul"); gtk_file_filter_add_pattern(filter, "*.au"); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser) , filter); - gtk_table_attach(GTK_TABLE(table), fileChooser, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter); + gtk_table_attach(GTK_TABLE(table), file_chooser, 0, 1, 1, 2, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show_all(vbox); return vbox; } -GtkWidget* create_direct_ip_calls_tab(account_t *a) +static GtkWidget* create_direct_ip_calls_tab(const account_t *account) { GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); @@ -1155,30 +1130,156 @@ GtkWidget* create_direct_ip_calls_tab(account_t *a) gtk_widget_set_size_request(label, 350, -1); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); - GtkWidget *frame = create_network(a); - gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - - frame = create_security_widget(a); + GtkWidget *frame = create_network(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); gtk_widget_show_all(vbox); return vbox; } -void show_account_window(account_t * currentAccount) +static const gchar *bool_to_string(gboolean v) { - // Firstly we reset - reset(); + return v ? "true" : "false"; +} + +static void update_account_from_basic_tab(account_t *account) +{ + // Update protocol in case it changed + gchar *proto; + if (protocol_combo) + proto = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocol_combo)); + else + proto = g_strdup("SIP"); - if (currentAccount == NULL) { - DEBUG("Config: Fetching default values for new account"); - currentAccount = g_new0(account_t, 1); - currentAccount->properties = dbus_get_account_details(NULL); - currentAccount->accountID = g_strdup("new"); //FIXME : replace with NULL for new accounts - currentAccount->credential_information = NULL; - sflphone_fill_codec_list_per_account(currentAccount); + if (g_strcmp0(proto, "SIP") == 0) { + if (!account_is_IP2IP(account)) { + account_replace(account, ACCOUNT_REGISTRATION_EXPIRE, + gtk_entry_get_text(GTK_ENTRY(expire_spin_box))); + + account_replace(account, ACCOUNT_ROUTE, + gtk_entry_get_text(GTK_ENTRY(entry_route_set))); + + account_replace(account, ACCOUNT_USERAGENT, + gtk_entry_get_text(GTK_ENTRY(entry_user_agent))); + + gboolean v = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_stun_check_box)); + account_replace(account, ACCOUNT_SIP_STUN_ENABLED, + bool_to_string(v)); + + account_replace(account, ACCOUNT_SIP_STUN_SERVER, + gtk_entry_get_text(GTK_ENTRY(stun_server_entry))); + + v = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button)); + account_replace(account, PUBLISHED_SAMEAS_LOCAL, bool_to_string(v)); + + if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button))) { + account_replace(account, PUBLISHED_PORT, + gtk_entry_get_text(GTK_ENTRY(published_port_spin_box))); + + account_replace(account, PUBLISHED_ADDRESS, + gtk_entry_get_text(GTK_ENTRY(published_address_entry))); + } else { + account_replace(account, PUBLISHED_PORT, + gtk_entry_get_text(GTK_ENTRY(local_port_spin_box))); + gchar *local_interface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); + + gchar *published_address = dbus_get_address_from_interface_name(local_interface); + g_free(local_interface); + + account_replace(account, PUBLISHED_ADDRESS, published_address); + } + } + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overrtp))) { + DEBUG("Set dtmf over rtp"); + account_replace(account, ACCOUNT_DTMF_TYPE, OVERRTP); + } else { + DEBUG("Set dtmf over sip"); + account_replace(account, ACCOUNT_DTMF_TYPE, SIPINFO); + } + + gchar* key_exchange = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(key_exchange_combo)); + + if (utf8_case_equal(key_exchange, "ZRTP")) { + account_replace(account, ACCOUNT_SRTP_ENABLED, "true"); + account_replace(account, ACCOUNT_KEY_EXCHANGE, ZRTP); + } else if (utf8_case_equal(key_exchange, "SDES")) { + account_replace(account, ACCOUNT_SRTP_ENABLED, "true"); + account_replace(account, ACCOUNT_KEY_EXCHANGE, SDES); + } else { + account_replace(account, ACCOUNT_SRTP_ENABLED, "false"); + account_replace(account, ACCOUNT_KEY_EXCHANGE, ""); + } + + g_free(key_exchange); + const gboolean tls_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_sip_tls_check_box)); + account_replace(account, TLS_ENABLE, bool_to_string(tls_enabled)); + + const gboolean tone_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enable_tone)); + account_replace(account, CONFIG_RINGTONE_ENABLED, bool_to_string(tone_enabled)); + + account_replace(account, CONFIG_RINGTONE_PATH, + gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser))); + + gchar *address_combo_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); + account_replace(account, LOCAL_INTERFACE, address_combo_text); + g_free(address_combo_text); + + account_replace(account, LOCAL_PORT, + gtk_entry_get_text(GTK_ENTRY(local_port_spin_box))); } + account_replace(account, ACCOUNT_ALIAS, gtk_entry_get_text(GTK_ENTRY(entry_alias))); + account_replace(account, ACCOUNT_TYPE, proto); + account_replace(account, ACCOUNT_HOSTNAME, gtk_entry_get_text(GTK_ENTRY(entry_hostname))); + account_replace(account, ACCOUNT_USERNAME, gtk_entry_get_text(GTK_ENTRY(entry_username))); + account_replace(account, ACCOUNT_PASSWORD, gtk_entry_get_text(GTK_ENTRY(entry_password))); + account_replace(account, ACCOUNT_MAILBOX, gtk_entry_get_text(GTK_ENTRY(entry_mailbox))); + g_free(proto); +} + +void update_account_from_dialog(GtkWidget *dialog, account_t *account) +{ + if (!dialog) + return; + + const gboolean IS_IP2IP = account_is_IP2IP(account); + if (!IS_IP2IP) + update_account_from_basic_tab(account); + + // Get current protocol for this account + gchar *current_protocol; + if (protocol_combo) + current_protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocol_combo)); + else + current_protocol = g_strdup("SIP"); + + if (!IS_IP2IP && g_strcmp0(current_protocol, "SIP") == 0) + account->credential_information = get_new_credential(); + + /** @todo Verify if it's the best condition to check */ + if (g_strcmp0(account->accountID, "new") == 0) { + dbus_add_account(account); + if (account->credential_information) + dbus_set_credentials(account); + } else { + if (account->credential_information) + dbus_set_credentials(account); + dbus_set_account_details(account); + } + + // propagate changes to the daemon + codec_list_update_to_daemon(account); + + g_free(current_protocol); + gtk_widget_destroy(dialog); +} + +GtkWidget *show_account_window(const account_t *account) +{ + // First we reset + reset(); + GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Account settings"), GTK_WINDOW(get_main_window()), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, @@ -1194,219 +1295,54 @@ void show_account_window(account_t * currentAccount) gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), notebook, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(notebook), 10); gtk_widget_show(notebook); + const gboolean IS_IP2IP = account_is_IP2IP(account); // We do not need the global settings for the IP2IP account - if (g_strcasecmp(currentAccount->accountID, IP2IP) != 0) { + if (!IS_IP2IP) { /* General Settings */ - GtkWidget *basic_tab = create_basic_tab(currentAccount); + GtkWidget *basic_tab = create_basic_tab(account); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), basic_tab, gtk_label_new(_("Basic"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), basic_tab); } /* Audio Codecs */ - GtkWidget *audiocodecs_tab = create_audiocodecs_configuration(currentAccount); + GtkWidget *audiocodecs_tab = create_audiocodecs_configuration(account); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), audiocodecs_tab, gtk_label_new(_("Audio"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), audiocodecs_tab); - // Get current protocol for this account protocol - gchar *currentProtocol; - - if (protocolComboBox) - currentProtocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocolComboBox)); - else - currentProtocol = g_strdup("SIP"); - // Do not need advanced or security one for the IP2IP account - if (g_strcasecmp(currentAccount->accountID, IP2IP) != 0) { - + if (!IS_IP2IP) { /* Advanced */ - advanced_tab = create_advanced_tab(currentAccount); + advanced_tab = create_advanced_tab(account); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), advanced_tab, gtk_label_new(_("Advanced"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), advanced_tab); /* Security */ - security_tab = create_security_tab(currentAccount); + security_tab = create_security_tab(account); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), security_tab, gtk_label_new(_("Security"))); - gtk_notebook_page_num(GTK_NOTEBOOK(notebook),security_tab); - + gtk_notebook_page_num(GTK_NOTEBOOK(notebook), security_tab); } else { /* Custom tab for the IP to IP profile */ - GtkWidget *ip_tab = create_direct_ip_calls_tab(currentAccount); + GtkWidget *ip_tab = create_direct_ip_calls_tab(account); gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), ip_tab, gtk_label_new(_("Network"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), ip_tab); } // Emit signal to hide advanced and security tabs in case of IAX - if (protocolComboBox) - g_signal_emit_by_name(protocolComboBox, "changed", NULL); + if (protocol_combo) + g_signal_emit_by_name(protocol_combo, "changed", NULL); - gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook) , 0); + gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0); - /**************/ - /* Run dialog */ - /**************/ + /* Run dialog, this blocks */ gint response = gtk_dialog_run(GTK_DIALOG(dialog)); - // Update protocol in case it changed - gchar *proto; - - if (protocolComboBox) - proto = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocolComboBox)); - else - proto = g_strdup("SIP"); - - // If cancel button is pressed - if (response == GTK_RESPONSE_CANCEL) { + // If anything but "Apply" button is pressed + if (response != GTK_RESPONSE_ACCEPT) { gtk_widget_destroy(dialog); - g_free(proto); - return; - } - - // If accept button is - if (g_strcasecmp(currentAccount->accountID, IP2IP) != 0) { - - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_ALIAS), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryAlias)))); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_TYPE), - g_strdup(proto)); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_HOSTNAME), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryHostname)))); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_USERNAME), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryUsername)))); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_PASSWORD), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryPassword)))); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_MAILBOX), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryMailbox)))); - } - - if (g_strcmp0(proto, "SIP") == 0) { - if (g_strcasecmp(currentAccount->accountID, IP2IP) != 0) { - - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_RESOLVE_ONCE), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(entryResolveNameOnlyOnce)) ? "false": "true")); - - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_REGISTRATION_EXPIRE), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(expireSpinBox)))); - - - // TODO: uncomment this code and implement route - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_ROUTE), - g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(entryRouteSet)))); - - - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_USERAGENT), - g_strdup(gtk_entry_get_text(GTK_ENTRY(entryUseragent)))); - - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SIP_STUN_ENABLED), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(useStunCheckBox)) ? "true":"false")); - - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SIP_STUN_SERVER), - g_strdup(gtk_entry_get_text(GTK_ENTRY(stunServerEntry)))); - - g_hash_table_replace(currentAccount->properties, g_strdup(PUBLISHED_SAMEAS_LOCAL), g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton)) ? "true":"false")); - - if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton))) { - g_hash_table_replace(currentAccount->properties, - g_strdup(PUBLISHED_PORT), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(publishedPortSpinBox)))); - - g_hash_table_replace(currentAccount->properties, - g_strdup(PUBLISHED_ADDRESS), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(publishedAddressEntry)))); - } else { - g_hash_table_replace(currentAccount->properties, - g_strdup(PUBLISHED_PORT), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(localPortSpinBox)))); - gchar *local_interface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo)); - - gchar *published_address = dbus_get_address_from_interface_name(local_interface); - g_free(local_interface); - - g_hash_table_replace(currentAccount->properties, - g_strdup(PUBLISHED_ADDRESS), - published_address); - } - } - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overrtp))) { - DEBUG("Config: Set dtmf over rtp"); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_DTMF_TYPE), g_strdup(OVERRTP)); - } else { - DEBUG("Config: Set dtmf over sip"); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_DTMF_TYPE), g_strdup(SIPINFO)); - } - - gchar* keyExchange = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo)); - - if (g_strcasecmp(keyExchange, "ZRTP") == 0) { - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SRTP_ENABLED), g_strdup("true")); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_KEY_EXCHANGE), g_strdup(ZRTP)); - } else if (g_strcasecmp(keyExchange, "SDES") == 0) { - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SRTP_ENABLED), g_strdup("true")); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_KEY_EXCHANGE), g_strdup(SDES)); - } else { - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SRTP_ENABLED), g_strdup("false")); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_KEY_EXCHANGE), g_strdup("")); - } - - g_free(keyExchange); - - g_hash_table_replace(currentAccount->properties, g_strdup(TLS_ENABLE), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(useSipTlsCheckBox)) ? "true":"false")); - - gboolean toneEnabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableTone)); - g_hash_table_replace(currentAccount->properties, - g_strdup(CONFIG_RINGTONE_ENABLED), - g_strdup(toneEnabled ? "true" : "false")); - - g_hash_table_replace(currentAccount->properties, - g_strdup(CONFIG_RINGTONE_PATH), - g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileChooser)))); - - g_hash_table_replace(currentAccount->properties, - g_strdup(LOCAL_INTERFACE), - gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo))); - - g_hash_table_replace(currentAccount->properties, - g_strdup(LOCAL_PORT), - g_strdup(gtk_entry_get_text(GTK_ENTRY(localPortSpinBox)))); - - } - - /** @todo Verify if it's the best condition to check */ - if (g_strcasecmp(currentAccount->accountID, "new") == 0) - dbus_add_account(currentAccount); - else - dbus_set_account_details(currentAccount); - - if (g_strcmp0(currentProtocol, "SIP") == 0) { - /* Set new credentials if any */ - DEBUG("Config: Setting credentials"); - - if (g_strcasecmp(currentAccount->accountID, IP2IP) != 0) { - DEBUG("Config: Get new credentials"); - currentAccount->credential_information = getNewCredential(); - - if (currentAccount->credential_information) - dbus_set_credentials(currentAccount); - } + return NULL; + } else { + return dialog; } - - // propagate changes to the daemon - codec_list_update_to_daemon(currentAccount); - - gtk_widget_destroy(dialog); - g_free(currentProtocol); - g_free(proto); } diff --git a/gnome/src/config/accountconfigdialog.h b/gnome/src/config/accountconfigdialog.h index fb91376cc1326f87ba050ca5ef38fa68757e6fa5..1b72a153cf7b973a6dfd8170f74e399185b7b0fa 100644 --- a/gnome/src/config/accountconfigdialog.h +++ b/gnome/src/config/accountconfigdialog.h @@ -39,8 +39,15 @@ /** * Display the main account widget - * @param a The account you want to edit or null for a new account + * @param a The account you want to display + * @return The dialog with the pertinent account information */ -void show_account_window (account_t *a); +GtkWidget *show_account_window(const account_t *a); + +/* + * @param dialog The dialog the account will be update from + * @param a The account you want to display + */ +void update_account_from_dialog(GtkWidget *dialog, account_t *a); #endif diff --git a/gnome/src/config/accountlistconfigdialog.c b/gnome/src/config/accountlistconfigdialog.c index aa8db7a8dbbfae7c7d47a54b409815ec621e454a..28aa48cb2af3531c493501c5f1d19884213c23ea 100644 --- a/gnome/src/config/accountlistconfigdialog.c +++ b/gnome/src/config/accountlistconfigdialog.c @@ -29,134 +29,174 @@ * as that of the covered work. */ - #include "accountlistconfigdialog.h" +#include "str_utils.h" #include "dbus/dbus.h" #include "accountconfigdialog.h" +#include "accountlist.h" #include "actions.h" #include "mainwindow.h" #include "utils.h" #include "unused.h" #include "logger.h" +#include "gtk2_wrappers.h" +#include <glib/gi18n.h> #include <string.h> static const int CONTEXT_ID_REGISTRATION = 0; -static GtkWidget *addButton; -static GtkWidget *editButton; -static GtkWidget *deleteButton; -static GtkWidget *accountMoveDownButton; -static GtkWidget *accountMoveUpButton; -static GtkWidget * status_bar; -static GtkListStore * accountStore; - -static GtkDialog * accountListDialog = NULL; +static GtkWidget *edit_button; +static GtkWidget *delete_button; +static GtkWidget *move_down_button; +static GtkWidget *move_up_button; +static GtkWidget *account_list_status_bar; +static GtkListStore *account_store; +static GtkDialog *account_list_dialog; -static account_t * selectedAccount = NULL; // Account properties enum { COLUMN_ACCOUNT_ALIAS, COLUMN_ACCOUNT_TYPE, COLUMN_ACCOUNT_STATUS, COLUMN_ACCOUNT_ACTIVE, - COLUMN_ACCOUNT_DATA, + COLUMN_ACCOUNT_ID, COLUMN_ACCOUNT_COUNT }; -/** - * Delete an account - */ -static void delete_account_cb(void) +/* Get selected account ID from treeview + * @return copied selected_accountID, must be freed by caller */ +static gchar * +get_selected_accountID(GtkTreeView *tree_view) { - if (selectedAccount == NULL) { - ERROR("Config: Error: No selected account in delete action"); - return; - } + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); - dbus_remove_account(selectedAccount->accountID); -} + // Find selected iteration and create a copy + GtkTreeIter iter; + gtk_tree_selection_get_selected(selection, &model, &iter); + // The Gvalue will be initialized in the following function + GValue val; + memset(&val, 0, sizeof(val)); + gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_ID, &val); + gchar *selected_accountID = g_strdup(g_value_get_string(&val)); + g_value_unset(&val); + return selected_accountID; +} -/** - * Edit an account - */ -static void edit_account_cb(void) +static gboolean +find_account_in_account_store(const gchar *accountID, GtkTreeModel *model, + GtkTreeIter *iter) { - if (selectedAccount == NULL) { - ERROR("Config: Error: No selected account in edit action"); - return; + gboolean valid = gtk_tree_model_get_iter_first(model, iter); + gboolean found = FALSE; + while (valid && !found) { + gchar *id; + gtk_tree_model_get(model, iter, COLUMN_ACCOUNT_ID, &id, -1); + if (g_strcmp0(id, accountID) == 0) + found = TRUE; + else + valid = gtk_tree_model_iter_next(model, iter); + g_free(id); } - - show_account_window(selectedAccount); + return found; } -/** - * Add an account - */ -static void add_account_cb(void) -{ - show_account_window(NULL); -} -/** - * Fills the treelist with accounts - */ -void account_list_config_dialog_fill() +static void delete_account_cb(GtkButton *button UNUSED, gpointer data) { - if (accountListDialog == NULL) { - DEBUG("Config: No account dialog, returning"); - return; - } - + gchar *selected_accountID = get_selected_accountID(data); + RETURN_IF_NULL(selected_accountID, "No selected account in delete action"); + GtkTreeModel *model = GTK_TREE_MODEL(account_store); GtkTreeIter iter; + if (find_account_in_account_store(selected_accountID, model, &iter)) + gtk_list_store_remove(account_store, &iter); - gtk_list_store_clear(accountStore); + dbus_remove_account(selected_accountID); + g_free(selected_accountID); +} - // IP2IP account must be first - account_t *a = account_list_get_by_id("IP2IP"); +static void +run_account_dialog(const gchar *selected_accountID) +{ + account_t *account = account_list_get_by_id(selected_accountID); + GtkWidget *dialog = show_account_window(account); + update_account_from_dialog(dialog, account); +} - if (a == NULL) { - ERROR("Config: Error: Could not find IP2IP account"); - return; - } +static void row_activated_cb(GtkTreeView *view, + GtkTreePath *path UNUSED, + GtkTreeViewColumn *col UNUSED, + gpointer user_data UNUSED) +{ + gchar *selected_accountID = get_selected_accountID(view); + RETURN_IF_NULL(selected_accountID, "No selected account ID"); + run_account_dialog(selected_accountID); + g_free(selected_accountID); +} - gtk_list_store_append(accountStore, &iter); +static void edit_account_cb(GtkButton *button UNUSED, gpointer data) +{ + gchar *selected_accountID = get_selected_accountID(data); + RETURN_IF_NULL(selected_accountID, "No selected account ID"); + run_account_dialog(selected_accountID); + g_free(selected_accountID); +} - DEBUG("Config: Filling accounts: Account is enabled :%s", g_hash_table_lookup(a->properties, ACCOUNT_ENABLED)); +static void account_store_add(GtkTreeIter *iter, account_t *account) +{ + const gchar *enabled = account_lookup(account, ACCOUNT_ENABLED); + const gchar *type = account_lookup(account, ACCOUNT_TYPE); + DEBUG("Account is enabled :%s", enabled); + const gchar *state_name = account_state_name(account->state); + + gtk_list_store_set(account_store, iter, + COLUMN_ACCOUNT_ALIAS, account_lookup(account, ACCOUNT_ALIAS), + COLUMN_ACCOUNT_TYPE, type, + COLUMN_ACCOUNT_STATUS, state_name, + COLUMN_ACCOUNT_ACTIVE, utf8_case_equal(enabled, "true"), + COLUMN_ACCOUNT_ID, account->accountID, -1); +} - gtk_list_store_set(accountStore, &iter, - COLUMN_ACCOUNT_ALIAS, g_hash_table_lookup(a->properties, ACCOUNT_ALIAS), // Name - COLUMN_ACCOUNT_TYPE, g_hash_table_lookup(a->properties, ACCOUNT_TYPE), // Protocol - COLUMN_ACCOUNT_STATUS, account_state_name(a->state), // Status - COLUMN_ACCOUNT_ACTIVE, (g_strcasecmp(g_hash_table_lookup(a->properties, ACCOUNT_ENABLED),"true") == 0) ? TRUE:FALSE, // Enable/Disable - COLUMN_ACCOUNT_DATA, a, // Pointer - -1); +/** + * Fills the treelist with accounts, should be called whenever the account + * list is modified. + */ +static void account_store_fill() +{ + RETURN_IF_NULL(account_list_dialog, "No account dialog"); + gtk_list_store_clear(account_store); - for (size_t i = 0; i < account_list_get_size(); i++) { - a = account_list_get_nth(i); + // IP2IP account must be first + account_t *ip2ip = account_list_get_by_id(IP2IP_PROFILE); + ip2ip->state = ACCOUNT_STATE_IP2IP_READY; + RETURN_IF_NULL(ip2ip, "Could not find IP2IP account"); - if (a == NULL) { - ERROR("Config: Error: Account %d is NULL while parsing the list", i); - return; - } + GtkTreeIter iter; + gtk_list_store_append(account_store, &iter); - // we dont wnat to process account twice - if (g_strcmp0(a->accountID, "IP2IP") != 0) { - gtk_list_store_append(accountStore, &iter); + account_store_add(&iter, ip2ip); - DEBUG("Config: Filling accounts: Account is enabled :%s", g_hash_table_lookup(a->properties, ACCOUNT_ENABLED)); + for (size_t i = 0; i < account_list_get_size(); ++i) { + account_t *a = account_list_get_nth(i); + RETURN_IF_NULL(a, "Account %d is NULL", i); - gtk_list_store_set(accountStore, &iter, - COLUMN_ACCOUNT_ALIAS, g_hash_table_lookup(a->properties, ACCOUNT_ALIAS), // Name - COLUMN_ACCOUNT_TYPE, g_hash_table_lookup(a->properties, ACCOUNT_TYPE), // Protocol - COLUMN_ACCOUNT_STATUS, account_state_name(a->state), // Status - COLUMN_ACCOUNT_ACTIVE, (g_strcasecmp(g_hash_table_lookup(a->properties, ACCOUNT_ENABLED),"true") == 0) ? TRUE:FALSE, // Enable/Disable - COLUMN_ACCOUNT_DATA, a, // Pointer - -1); + // we don't want to process the IP2IP twice + if (a != ip2ip) { + gtk_list_store_append(account_store, &iter); + account_store_add(&iter, a); } } } +static void add_account_cb(void) +{ + account_t *new_account = create_default_account(); + account_list_add(new_account); + run_account_dialog(new_account->accountID); + account_store_fill(); +} + /** * Call back when the user click on an account in the list */ @@ -164,174 +204,131 @@ static void select_account_cb(GtkTreeSelection *selection, GtkTreeModel *model) { GtkTreeIter iter; - GValue val; - gchar *state; - - memset(&val, 0, sizeof(val)); - if (!gtk_tree_selection_get_selected(selection, &model, &iter)) { - selectedAccount = NULL; - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(editButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE); + gtk_widget_set_sensitive(move_up_button, FALSE); + gtk_widget_set_sensitive(move_down_button, FALSE); + gtk_widget_set_sensitive(edit_button, FALSE); + gtk_widget_set_sensitive(delete_button, FALSE); return; } // The Gvalue will be initialized in the following function - gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_DATA, &val); + GValue val; + memset(&val, 0, sizeof(val)); + gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_ID, &val); - selectedAccount = (account_t*) g_value_get_pointer(&val); + gchar *selected_accountID = g_value_dup_string(&val); g_value_unset(&val); - if (selectedAccount != NULL) { - gtk_widget_set_sensitive(GTK_WIDGET(editButton), TRUE); - - if (g_strcasecmp(selectedAccount->accountID, IP2IP) != 0) { - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), TRUE); - - /* Update status bar about current registration state */ - gtk_statusbar_pop(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION); - - if (selectedAccount->protocol_state_description != NULL - && selectedAccount->protocol_state_code != 0) { - - gchar * response = g_strdup_printf( - _("Server returned \"%s\" (%d)"), - selectedAccount->protocol_state_description, - selectedAccount->protocol_state_code); - gchar * message = g_strconcat( - account_state_name(selectedAccount->state), - ". ", - response, - NULL); + DEBUG("Selected account has accountID %s", selected_accountID); + account_t *selected_account = account_list_get_by_id(selected_accountID); + RETURN_IF_NULL(selected_account, "Selected account is NULL"); - gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, message); + gtk_widget_set_sensitive(edit_button, TRUE); - g_free(response); - g_free(message); + if (!account_is_IP2IP(selected_account)) { + gtk_widget_set_sensitive(move_up_button, TRUE); + gtk_widget_set_sensitive(move_down_button, TRUE); + gtk_widget_set_sensitive(delete_button, TRUE); - } else { - state = (gchar*) account_state_name(selectedAccount->state); - gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, state); - } - } else { - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE); - } + /* Update status bar about current registration state */ + update_account_list_status_bar(selected_account); + } else { + gtk_widget_set_sensitive(move_up_button, FALSE); + gtk_widget_set_sensitive(move_down_button, FALSE); + gtk_widget_set_sensitive(delete_button, FALSE); } - - DEBUG("Selecting account in account window"); + g_free(selected_accountID); } -static void enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path, gpointer data) +static void +enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path, + gpointer data) { - - GtkTreeIter iter; - GtkTreePath *treePath; - GtkTreeModel *model; - gboolean enable; - account_t* acc ; - // The IP2IP profile can't be disabled - if (g_strcasecmp(path, "0") == 0) + if (g_strcmp0(path, "0") == 0) return; // Get pointer on object - treePath = gtk_tree_path_new_from_string(path); - model = gtk_tree_view_get_model(GTK_TREE_VIEW(data)); - gtk_tree_model_get_iter(model, &iter, treePath); - gtk_tree_model_get(model, &iter, - COLUMN_ACCOUNT_ACTIVE, &enable, - COLUMN_ACCOUNT_DATA, &acc, - -1); + GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(data)); + GtkTreeIter iter; + gtk_tree_model_get_iter(model, &iter, tree_path); + gboolean enable; + gchar *id; + gtk_tree_model_get(model, &iter, COLUMN_ACCOUNT_ACTIVE, &enable, + COLUMN_ACCOUNT_ID, &id, -1); + account_t *account = account_list_get_by_id(id); + g_assert(account); enable = !enable; - DEBUG("Account is %d enabled", enable); // Store value - gtk_list_store_set(GTK_LIST_STORE(model), &iter, - COLUMN_ACCOUNT_ACTIVE, enable, - -1); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_ACCOUNT_ACTIVE, + enable, -1); // Modify account state - gchar * registrationState; - - if (enable == TRUE) - registrationState = g_strdup("true"); - else - registrationState = g_strdup("false"); + const gchar * enabled_str = enable ? "true" : "false"; + DEBUG("Account is enabled: %s", enabled_str); - DEBUG("Replacing with %s", registrationState); - g_hash_table_replace(acc->properties , g_strdup(ACCOUNT_ENABLED), registrationState); - - dbus_send_register(acc->accountID, enable); + account_replace(account, ACCOUNT_ENABLED, enabled_str); + dbus_send_register(account->accountID, enable); } /** * Move account in list depending on direction and selected account */ -static void account_move(gboolean moveUp, gpointer data) +static void +account_move(gboolean move_up, gpointer data) { - - GtkTreeIter iter; - GtkTreeIter *iter2; - GtkTreeView *treeView; - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreePath *treePath; - gchar *path; - - // Get view, model and selection of codec store - treeView = GTK_TREE_VIEW(data); - model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeView)); - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView)); + // Get view, model and selection of account + GtkTreeView *tree_view = GTK_TREE_VIEW(data); + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); // Find selected iteration and create a copy - gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter); - iter2 = gtk_tree_iter_copy(&iter); + GtkTreeIter iter; + gtk_tree_selection_get_selected(selection, &model, &iter); + GtkTreeIter *iter_copy; + iter_copy = gtk_tree_iter_copy(&iter); // Find path of iteration - path = gtk_tree_model_get_string_from_iter(GTK_TREE_MODEL(model), &iter); + gchar *path = gtk_tree_model_get_string_from_iter(model, &iter); // The first real account in the list can't move up because of the IP2IP account // It can still move down though - if (g_strcasecmp(path, "1") == 0 && moveUp) + if (g_strcmp0(path, "1") == 0 && move_up) return; - treePath = gtk_tree_path_new_from_string(path); - gint *indices = gtk_tree_path_get_indices(treePath); - gint indice = indices[0]; + GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); + gint *indices = gtk_tree_path_get_indices(tree_path); + const gint pos = indices[0]; // Depending on button direction get new path - if (moveUp) - gtk_tree_path_prev(treePath); + if (move_up) + gtk_tree_path_prev(tree_path); else - gtk_tree_path_next(treePath); + gtk_tree_path_next(tree_path); - gtk_tree_model_get_iter(model, &iter, treePath); + gtk_tree_model_get_iter(model, &iter, tree_path); // Swap iterations if valid if (gtk_list_store_iter_is_valid(GTK_LIST_STORE(model), &iter)) - gtk_list_store_swap(GTK_LIST_STORE(model), &iter, iter2); + gtk_list_store_swap(GTK_LIST_STORE(model), &iter, iter_copy); // Scroll to new position - gtk_tree_view_scroll_to_cell(treeView, treePath, NULL, FALSE, 0, 0); + gtk_tree_view_scroll_to_cell(tree_view, tree_path, NULL, FALSE, 0, 0); // Free resources - gtk_tree_path_free(treePath); - gtk_tree_iter_free(iter2); + gtk_tree_path_free(tree_path); + gtk_tree_iter_free(iter_copy); g_free(path); // Perpetuate changes in account queue - if (moveUp) - account_list_move_up(indice); + if (move_up) + account_list_move_up(pos); else - account_list_move_down(indice); - + account_list_move_down(pos); // Set the order in the configuration file gchar *ordered_account_list = account_list_get_ordered_list(); @@ -343,9 +340,9 @@ static void account_move(gboolean moveUp, gpointer data) * Called from move up account button signal */ static void -account_move_up_cb(GtkButton *button UNUSED, gpointer data) +move_up_cb(GtkButton *button UNUSED, gpointer data) { - // Change tree view ordering and get indice changed + // Change tree view ordering and get index changed account_move(TRUE, data); } @@ -353,9 +350,9 @@ account_move_up_cb(GtkButton *button UNUSED, gpointer data) * Called from move down account button signal */ static void -account_move_down_cb(GtkButton *button UNUSED, gpointer data) +move_down_cb(GtkButton *button UNUSED, gpointer data) { - // Change tree view ordering and get indice changed + // Change tree view ordering and get index changed account_move(FALSE, data); } @@ -372,181 +369,182 @@ help_contents_cb(GtkWidget * widget UNUSED, } static void -close_dialog_cb(GtkWidget * widget UNUSED, - gpointer data UNUSED) +close_dialog_cb(GtkWidget * widget UNUSED, gpointer data UNUSED) { - gtk_dialog_response(GTK_DIALOG(accountListDialog), GTK_RESPONSE_ACCEPT); - + gtk_dialog_response(GTK_DIALOG(account_list_dialog), GTK_RESPONSE_ACCEPT); } -void highlight_ip_profile(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data UNUSED) +static void +highlight_ip_profile(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, + GtkTreeModel *tree_model, GtkTreeIter *iter, + gpointer data UNUSED) { - GValue val; - account_t *current; - memset(&val, 0, sizeof(val)); - gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_DATA, &val); - current = (account_t*) g_value_get_pointer(&val); - + gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_ID, &val); + account_t *current = account_list_get_by_id(g_value_get_string(&val)); g_value_unset(&val); - if (current != NULL) { - - // Make the first line appear differently - (g_strcasecmp(current->accountID, IP2IP) == 0) ? g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_THIN, - "style", PANGO_STYLE_ITALIC, - "stretch", PANGO_STRETCH_ULTRA_EXPANDED, - "scale", 0.95, - NULL) : - g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_MEDIUM, - "style", PANGO_STYLE_NORMAL, - "stretch", PANGO_STRETCH_NORMAL, - "scale", 1.0, - NULL) ; + // Make the IP2IP account appear differently + if (current) { + if (account_is_IP2IP(current)) { + g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_THIN, "style", + PANGO_STYLE_ITALIC, "stretch", + PANGO_STRETCH_ULTRA_EXPANDED, "scale", 0.95, NULL); + } else { + g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_MEDIUM, + "style", PANGO_STYLE_NORMAL, "stretch", + PANGO_STRETCH_NORMAL, "scale", 1.0, NULL); + } } } -void highlight_registration(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data UNUSED) +static const gchar* +state_color(account_t *a) { + if (!account_is_IP2IP(a)) + if (a->state == ACCOUNT_STATE_REGISTERED) + return "Dark Green"; + else + return "Dark Red"; + else + return "Black"; +} +static void +highlight_registration(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, + GtkTreeModel *tree_model, GtkTreeIter *iter, + gpointer data UNUSED) +{ GValue val; - account_t *current; - memset(&val, 0, sizeof(val)); - gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_DATA, &val); - current = (account_t*) g_value_get_pointer(&val); - + gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_ID, &val); + account_t *current = account_list_get_by_id(g_value_get_string(&val)); g_value_unset(&val); - if (current != NULL) { - if (g_strcasecmp(current->accountID, IP2IP) != 0) { - // Color the account state: green -> registered, otherwise red - (current->state == ACCOUNT_STATE_REGISTERED) ? g_object_set(G_OBJECT(rend), "foreground", "Dark Green", NULL) : - g_object_set(G_OBJECT(rend), "foreground", "Dark Red", NULL); - } else - g_object_set(G_OBJECT(rend), "foreground", "Black", NULL); - } - + if (current) + g_object_set(G_OBJECT(rend), "foreground", state_color(current), NULL); } /** * Account settings tab */ -GtkWidget* create_account_list(GtkDialog * dialog UNUSED) +static GtkWidget* +create_account_list() { - - GtkWidget *table, *scrolledWindow, *buttonBox; - GtkCellRenderer *renderer; - GtkTreeView * treeView; - GtkTreeViewColumn *treeViewColumn; - GtkTreeSelection *treeSelection; - GtkRequisition requisition; - - selectedAccount = NULL; - - table = gtk_table_new(1, 2, FALSE/* homogeneous */); + GtkWidget *table = gtk_table_new(1, 2, FALSE /* homogeneous */); gtk_table_set_col_spacings(GTK_TABLE(table), 10); gtk_container_set_border_width(GTK_CONTAINER(table), 10); - scrolledWindow = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_SHADOW_IN); - gtk_table_attach(GTK_TABLE(table), scrolledWindow, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - accountStore = gtk_list_store_new(COLUMN_ACCOUNT_COUNT, - G_TYPE_STRING, // Name - G_TYPE_STRING, // Protocol - G_TYPE_STRING, // Status - G_TYPE_BOOLEAN, // Enabled / Disabled - G_TYPE_POINTER // Pointer to the Object - ); - - account_list_config_dialog_fill(); - - treeView = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(accountStore))); - treeSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView)); - g_signal_connect(G_OBJECT(treeSelection), "changed", - G_CALLBACK(select_account_cb), - accountStore); - - renderer = gtk_cell_renderer_toggle_new(); - treeViewColumn = gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active", COLUMN_ACCOUNT_ACTIVE , NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn); - g_signal_connect(G_OBJECT(renderer) , "toggled" , G_CALLBACK(enable_account_cb), (gpointer) treeView); - - // gtk_cell_renderer_toggle_set_activatable (renderer, FALSE); + GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_SHADOW_IN); + gtk_table_attach(GTK_TABLE(table), scrolled_window, 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + + account_store = gtk_list_store_new(COLUMN_ACCOUNT_COUNT, + G_TYPE_STRING, // Name + G_TYPE_STRING, // Protocol + G_TYPE_STRING, // Status + G_TYPE_BOOLEAN, // Enabled / Disabled + G_TYPE_STRING // AccountID + ); + + account_store_fill(); + + GtkTreeView * tree_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(account_store))); + GtkTreeSelection *tree_selection = gtk_tree_view_get_selection(tree_view); + g_signal_connect(G_OBJECT(tree_selection), "changed", + G_CALLBACK(select_account_cb), NULL); + + GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new(); + GtkTreeViewColumn *tree_view_column = + gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active", + COLUMN_ACCOUNT_ACTIVE , NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column); + g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(enable_account_cb), tree_view); renderer = gtk_cell_renderer_text_new(); - treeViewColumn = gtk_tree_view_column_new_with_attributes("Alias", - renderer, - "markup", COLUMN_ACCOUNT_ALIAS, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn); + tree_view_column = gtk_tree_view_column_new_with_attributes("Alias", + renderer, + "markup", + COLUMN_ACCOUNT_ALIAS, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column); // A double click on the account line opens the window to edit the account - g_signal_connect(G_OBJECT(treeView) , "row-activated" , G_CALLBACK(edit_account_cb) , NULL); - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL); + g_signal_connect(G_OBJECT(tree_view), "row-activated", G_CALLBACK(row_activated_cb), NULL); + gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer, + highlight_ip_profile, NULL, NULL); renderer = gtk_cell_renderer_text_new(); - treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Protocol"), - renderer, - "markup", COLUMN_ACCOUNT_TYPE, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn); - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL); + tree_view_column = gtk_tree_view_column_new_with_attributes(_("Protocol"), + renderer, + "markup", + COLUMN_ACCOUNT_TYPE, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column); + gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer, + highlight_ip_profile, NULL, NULL); renderer = gtk_cell_renderer_text_new(); - treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Status"), + tree_view_column = gtk_tree_view_column_new_with_attributes(_("Status"), renderer, - "markup", COLUMN_ACCOUNT_STATUS, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn); + "markup", COLUMN_ACCOUNT_STATUS, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column); // Highlight IP profile - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL); + gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer, + highlight_ip_profile, NULL, NULL); // Highlight account registration state - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_registration, NULL, NULL); + gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer, + highlight_registration, NULL, + NULL); - g_object_unref(G_OBJECT(accountStore)); + g_object_unref(G_OBJECT(account_store)); - gtk_container_add(GTK_CONTAINER(scrolledWindow), GTK_WIDGET(treeView)); + gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(tree_view)); /* The buttons to press! */ - buttonBox = gtk_button_box_new(GTK_ORIENTATION_VERTICAL); - gtk_box_set_spacing(GTK_BOX(buttonBox), 10); - gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_START); - gtk_table_attach(GTK_TABLE(table), buttonBox, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - accountMoveUpButton = gtk_button_new_from_stock(GTK_STOCK_GO_UP); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE); - gtk_box_pack_start(GTK_BOX(buttonBox), accountMoveUpButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(accountMoveUpButton), "clicked", G_CALLBACK(account_move_up_cb), treeView); - - accountMoveDownButton = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE); - gtk_box_pack_start(GTK_BOX(buttonBox), accountMoveDownButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(accountMoveDownButton), "clicked", G_CALLBACK(account_move_down_cb), treeView); - - addButton = gtk_button_new_from_stock(GTK_STOCK_ADD); - g_signal_connect_swapped(G_OBJECT(addButton), "clicked", + GtkWidget *button_box = gtk_button_box_new(GTK_ORIENTATION_VERTICAL); + gtk_box_set_spacing(GTK_BOX(button_box), 10); + gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START); + gtk_table_attach(GTK_TABLE(table), button_box, 1, 2, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + + move_up_button = gtk_button_new_from_stock(GTK_STOCK_GO_UP); + gtk_widget_set_sensitive(move_up_button, FALSE); + gtk_box_pack_start(GTK_BOX(button_box), move_up_button, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(move_up_button), "clicked", + G_CALLBACK(move_up_cb), tree_view); + + move_down_button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); + gtk_widget_set_sensitive(move_down_button, FALSE); + gtk_box_pack_start(GTK_BOX(button_box), move_down_button, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(move_down_button), "clicked", + G_CALLBACK(move_down_cb), tree_view); + + GtkWidget *add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); + g_signal_connect_swapped(G_OBJECT(add_button), "clicked", G_CALLBACK(add_account_cb), NULL); - gtk_box_pack_start(GTK_BOX(buttonBox), addButton, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(button_box), add_button, FALSE, FALSE, 0); - editButton = gtk_button_new_from_stock(GTK_STOCK_EDIT); - gtk_widget_set_sensitive(GTK_WIDGET(editButton), FALSE); - g_signal_connect_swapped(G_OBJECT(editButton), "clicked", - G_CALLBACK(edit_account_cb), NULL); - gtk_box_pack_start(GTK_BOX(buttonBox), editButton, FALSE, FALSE, 0); + edit_button = gtk_button_new_from_stock(GTK_STOCK_EDIT); + gtk_widget_set_sensitive(edit_button, FALSE); + g_signal_connect(G_OBJECT(edit_button), "clicked", G_CALLBACK(edit_account_cb), tree_view); + gtk_box_pack_start(GTK_BOX(button_box), edit_button, FALSE, FALSE, 0); - deleteButton = gtk_button_new_from_stock(GTK_STOCK_REMOVE); - gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE); - g_signal_connect_swapped(G_OBJECT(deleteButton), "clicked", - G_CALLBACK(delete_account_cb), NULL); - gtk_box_pack_start(GTK_BOX(buttonBox), deleteButton, FALSE, FALSE, 0); + delete_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + gtk_widget_set_sensitive(delete_button, FALSE); + g_signal_connect(G_OBJECT(delete_button), "clicked", + G_CALLBACK(delete_account_cb), tree_view); + gtk_box_pack_start(GTK_BOX(button_box), delete_button, FALSE, FALSE, 0); /* help and close buttons */ GtkWidget * buttonHbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); - gtk_table_attach(GTK_TABLE(table), buttonHbox, 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 10); + gtk_table_attach(GTK_TABLE(table), buttonHbox, 0, 2, 1, 2, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 10); GtkWidget * helpButton = gtk_button_new_from_stock(GTK_STOCK_HELP); g_signal_connect_swapped(G_OBJECT(helpButton), "clicked", @@ -554,70 +552,115 @@ GtkWidget* create_account_list(GtkDialog * dialog UNUSED) gtk_box_pack_start(GTK_BOX(buttonHbox), helpButton, FALSE, FALSE, 0); GtkWidget * closeButton = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - g_signal_connect_swapped(G_OBJECT(closeButton), "clicked", G_CALLBACK(close_dialog_cb), NULL); + g_signal_connect_swapped(G_OBJECT(closeButton), "clicked", + G_CALLBACK(close_dialog_cb), NULL); gtk_box_pack_start(GTK_BOX(buttonHbox), closeButton, FALSE, FALSE, 0); gtk_widget_show_all(table); - // account_list_config_dialog_fill(); - /* Resize the scrolledWindow for a better view */ - gtk_widget_get_preferred_size(GTK_WIDGET(treeView), NULL, &requisition); - gtk_widget_set_size_request(GTK_WIDGET(scrolledWindow), requisition.width + 20, requisition.height); + /* Resize the scrolled window for a better view */ + GtkRequisition requisition; + gtk_widget_get_preferred_size(GTK_WIDGET(tree_view), NULL, &requisition); + gtk_widget_set_size_request(scrolled_window, requisition.width + 20, + requisition.height); GtkRequisition requisitionButton; - gtk_widget_get_preferred_size(GTK_WIDGET(deleteButton), NULL, &requisitionButton); - gtk_widget_set_size_request(GTK_WIDGET(closeButton), requisitionButton.width, -1); - gtk_widget_set_size_request(GTK_WIDGET(helpButton), requisitionButton.width, -1); + gtk_widget_get_preferred_size(delete_button, NULL, &requisitionButton); + gtk_widget_set_size_request(closeButton, requisitionButton.width, -1); + gtk_widget_set_size_request(helpButton, requisitionButton.width, -1); gtk_widget_show_all(table); return table; } -void -show_account_list_config_dialog(void) +void update_account_list_status_bar(account_t *account) { - accountListDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Accounts"), - GTK_WINDOW(get_main_window()), - GTK_DIALOG_DESTROY_WITH_PARENT, - NULL)); + if (!account || !account_list_status_bar) + return; + + /* Update status bar about current registration state */ + gtk_statusbar_pop(GTK_STATUSBAR(account_list_status_bar), + CONTEXT_ID_REGISTRATION); + + const gchar *state_name = account_state_name(account->state); + if (account->protocol_state_description != NULL && + account->protocol_state_code != 0) { + + gchar * response = g_strdup_printf(_("Server returned \"%s\" (%d)"), + account->protocol_state_description, + account->protocol_state_code); + gchar * message = g_strconcat(state_name, ". ", response, NULL); + gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), + CONTEXT_ID_REGISTRATION, message); + + g_free(response); + g_free(message); + } else { + gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), + CONTEXT_ID_REGISTRATION, state_name); + } + + GtkTreeModel *model = GTK_TREE_MODEL(account_store); + GtkTreeIter iter; + if (find_account_in_account_store(account->accountID, model, &iter)) + gtk_list_store_set(account_store, &iter, COLUMN_ACCOUNT_STATUS, state_name, -1); +} + +void show_account_list_config_dialog(void) +{ + account_list_dialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Accounts"), + GTK_WINDOW(get_main_window()), + GTK_DIALOG_DESTROY_WITH_PARENT, NULL, + NULL)); /* Set window properties */ - gtk_container_set_border_width(GTK_CONTAINER(accountListDialog), 0); - gtk_window_set_resizable(GTK_WINDOW(accountListDialog), FALSE); + gtk_container_set_border_width(GTK_CONTAINER(account_list_dialog), 0); + gtk_window_set_resizable(GTK_WINDOW(account_list_dialog), FALSE); GtkWidget *accountFrame = gnome_main_section_new(_("Configured Accounts")); - gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(accountListDialog)), + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(account_list_dialog)), accountFrame, TRUE, TRUE, 0); gtk_widget_show(accountFrame); /* Accounts tab */ - GtkWidget *tab = create_account_list(accountListDialog); + GtkWidget *tab = create_account_list(); gtk_widget_show(tab); gtk_container_add(GTK_CONTAINER(accountFrame), tab); /* Status bar for the account list */ - status_bar = gtk_statusbar_new(); - gtk_widget_show (status_bar); - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area(accountListDialog)), status_bar, TRUE, TRUE, 0); + account_list_status_bar = gtk_statusbar_new(); + gtk_widget_show(account_list_status_bar); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(account_list_dialog)), account_list_status_bar, TRUE, TRUE, 0); - int number_accounts = account_list_get_registered_accounts(); + const gint num_accounts = account_list_get_registered_accounts(); - if (number_accounts) { + if (num_accounts) { gchar * message = g_strdup_printf(n_("There is %d active account", "There are %d active accounts", - number_accounts), number_accounts); - gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, message); + num_accounts), num_accounts); + gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), CONTEXT_ID_REGISTRATION, + message); g_free(message); - } else - gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, + } else { + gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), CONTEXT_ID_REGISTRATION, _("You have no active account")); + } - gtk_dialog_run(accountListDialog); + gtk_dialog_run(account_list_dialog); status_bar_display_account(); - gtk_widget_destroy(GTK_WIDGET(accountListDialog)); - accountListDialog = NULL; + gtk_widget_destroy(GTK_WIDGET(account_list_dialog)); + + /* Invalidate static pointers */ + account_list_dialog = NULL; + account_list_status_bar = NULL; + edit_button = NULL; + delete_button = NULL; + move_down_button = NULL; + move_up_button = NULL; + account_store = NULL; + update_actions(); } diff --git a/gnome/src/config/accountlistconfigdialog.h b/gnome/src/config/accountlistconfigdialog.h index 94764a5f989af1dd8282200d7999c89651cdec68..bae376b6d92152cd13c6dc43fcb0dc3765a34cca 100644 --- a/gnome/src/config/accountlistconfigdialog.h +++ b/gnome/src/config/accountlistconfigdialog.h @@ -29,12 +29,12 @@ */ -#ifndef __SFL_ACCOUNTLISTDIALOG_H__ -#define __SFL_ACCOUNTLISTDIALOG_H__ +#ifndef ACCOUNTLISTDIALOG_H_ +#define ACCOUNTLISTDIALOG_H_ -#include <sflphone_const.h> +#include "accountlist.h" -void show_account_list_config_dialog (void); -void account_list_config_dialog_fill (void); +void show_account_list_config_dialog(void); +void update_account_list_status_bar(account_t *account); -#endif +#endif // ACCOUNTLISTDIALOG_H_ diff --git a/gnome/src/config/addressbook-config.c b/gnome/src/config/addressbook-config.c index 4c56da203677369e5e7f14d7d8c4be75d7b89b60..14476e033085df903358b0a1bfc89ac8b87a0f05 100644 --- a/gnome/src/config/addressbook-config.c +++ b/gnome/src/config/addressbook-config.c @@ -29,11 +29,14 @@ */ #include "addressbook-config.h" +#include "gtk2_wrappers.h" +#include "str_utils.h" #include "dbus.h" #include "unused.h" #include "logger.h" #include "searchbar.h" #include "contacts/addrbookfactory.h" +#include <glib/gi18n.h> #include <string.h> #include <stdlib.h> @@ -216,7 +219,7 @@ addressbook_config_book_active_toggled( treePath = gtk_tree_path_new_from_string(path); if (!(model = gtk_tree_view_get_model(GTK_TREE_VIEW(data)))) { - DEBUG("Addressbook: No valid model (%s:%d)", __FILE__, __LINE__); + DEBUG("No valid model (%s:%d)", __FILE__, __LINE__); return; } @@ -238,7 +241,8 @@ addressbook_config_book_active_toggled( book_data = addrbook->get_book_data_by_uid(uid); if (book_data == NULL) { - ERROR("Addressbook: Error: Could not find addressbook %s", uid); + ERROR("Could not find addressbook %s", uid); + return; } book_data->active = active; @@ -296,12 +300,12 @@ addressbook_config_fill_book_list() GSList *books_data = addrbook->get_books_data(book_list); if (!books_data) { - DEBUG("Addressbook: No valid books data (%s:%d)", __FILE__, __LINE__); + DEBUG("No valid books data (%s:%d)", __FILE__, __LINE__); } // Get model of view and clear it if (!(store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(book_tree_view))))) { - DEBUG("Addressbook: Could not find model from treeview (%s:%d)", __FILE__, __LINE__); + DEBUG("Could not find model from treeview (%s:%d)", __FILE__, __LINE__); return; } @@ -442,14 +446,14 @@ addressbook_display(AddressBook_Config *settings, const gchar *field) { gboolean display; - if (g_strcasecmp(field, ADDRESSBOOK_DISPLAY_CONTACT_PHOTO) == 0) - display = (settings->display_contact_photo == 1) ? TRUE : FALSE; - else if (g_strcasecmp(field, ADDRESSBOOK_DISPLAY_PHONE_BUSINESS) == 0) - display = (settings->search_phone_business == 1) ? TRUE : FALSE; - else if (g_strcasecmp(field, ADDRESSBOOK_DISPLAY_PHONE_HOME) == 0) - display = (settings->search_phone_home == 1) ? TRUE : FALSE; - else if (g_strcasecmp(field, ADDRESSBOOK_DISPLAY_PHONE_MOBILE) == 0) - display = (settings->search_phone_mobile == 1) ? TRUE : FALSE; + if (utf8_case_equal(field, ADDRESSBOOK_DISPLAY_CONTACT_PHOTO)) + display = settings->display_contact_photo == 1; + else if (utf8_case_equal(field, ADDRESSBOOK_DISPLAY_PHONE_BUSINESS)) + display = settings->search_phone_business == 1; + else if (utf8_case_equal(field, ADDRESSBOOK_DISPLAY_PHONE_HOME)) + display = settings->search_phone_home == 1; + else if (utf8_case_equal(field, ADDRESSBOOK_DISPLAY_PHONE_MOBILE)) + display = settings->search_phone_mobile == 1; else display = FALSE; diff --git a/gnome/src/config/addressbook-config.h b/gnome/src/config/addressbook-config.h index cb102604eeb80fd1b9914e24362ef05f4bcc3ec5..cd7a9ac7bc0b0ca120d20ccc8f2731ce6c177748 100644 --- a/gnome/src/config/addressbook-config.h +++ b/gnome/src/config/addressbook-config.h @@ -32,7 +32,7 @@ #define _ADDRESS_BOOK_CONFIG #include <gtk/gtk.h> -#include <glib/gtypes.h> +#include <glib.h> #include "addressbook.h" #include "actions.h" diff --git a/gnome/src/config/assistant.c b/gnome/src/config/assistant.c index 8ca002115543ba01327688b250497f8344797bff..d25e882bd63050b624af210d2ce7c088ff616071 100644 --- a/gnome/src/config/assistant.c +++ b/gnome/src/config/assistant.c @@ -29,7 +29,8 @@ */ #include <string.h> - +#include <glib/gi18n.h> +#include "gtk2_wrappers.h" #include "unused.h" #include "assistant.h" #include "logger.h" @@ -40,26 +41,26 @@ struct _wizard *wiz; static int account_type; -static int use_sflphone_org = 1; +static gboolean use_sflphone_org = TRUE; static account_t* current; static char message[1024]; /** * Forward function */ -static gint forward_page_func(gint current_page , gpointer data); +static gint forward_page_func(gint current_page, gpointer data); /** * Page template */ static GtkWidget* create_vbox(GtkAssistantPageType type, const gchar *title, const gchar *section); -void prefill_sip(void) ; +void prefill_sip(void); -void set_account_type(GtkWidget* widget , gpointer data UNUSED) +void set_account_type(GtkWidget* widget, gpointer data UNUSED) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) account_type = _SIP; else - account_type = _IAX ; + account_type = _IAX; } static void show_password_cb(GtkWidget *widget UNUSED, gpointer data) @@ -100,13 +101,11 @@ void getMessageSummary(const gchar * alias, const gchar * server, const gchar * strcat(message, _("None")); } -void set_sflphone_org(GtkWidget* widget , gpointer data UNUSED) +void set_sflphone_org(GtkWidget* widget, gpointer data UNUSED) { - use_sflphone_org = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ?1:0) ; + use_sflphone_org = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); } - - /** * Callback when the close button of the dialog is clicked * Action : close the assistant widget and get back to sflphone main window @@ -145,26 +144,25 @@ static void sip_apply_callback(void) } if (account_type == _SIP) { - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ALIAS), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_alias)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ENABLED), g_strdup("true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_MAILBOX), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_voicemail)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_TYPE), g_strdup("SIP")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_HOSTNAME), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_server)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_PASSWORD), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_password)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_USERNAME), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_username)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_SIP_STUN_ENABLED), g_strdup((gchar *)(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiz->enable)) ? "true":"false"))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_SIP_STUN_SERVER), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->addr)))); + account_insert(current, ACCOUNT_ALIAS, gtk_entry_get_text(GTK_ENTRY(wiz->sip_alias))); + account_insert(current, ACCOUNT_ENABLED, "true"); + account_insert(current, ACCOUNT_MAILBOX, gtk_entry_get_text(GTK_ENTRY(wiz->sip_voicemail))); + account_insert(current, ACCOUNT_TYPE, "SIP"); + account_insert(current, ACCOUNT_HOSTNAME, gtk_entry_get_text(GTK_ENTRY(wiz->sip_server))); + account_insert(current, ACCOUNT_PASSWORD, gtk_entry_get_text(GTK_ENTRY(wiz->sip_password))); + account_insert(current, ACCOUNT_USERNAME, gtk_entry_get_text(GTK_ENTRY(wiz->sip_username))); + account_insert(current, ACCOUNT_SIP_STUN_ENABLED, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiz->enable)) ? "true" : "false"); + account_insert(current, ACCOUNT_SIP_STUN_SERVER, gtk_entry_get_text(GTK_ENTRY(wiz->addr))); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiz->zrtp_enable)) == TRUE) { - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_SRTP_ENABLED), g_strdup((gchar *) "true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_KEY_EXCHANGE), g_strdup((gchar *) ZRTP)); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ZRTP_DISPLAY_SAS), g_strdup((gchar *) "true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ZRTP_NOT_SUPP_WARNING), g_strdup((gchar *) "true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ZRTP_HELLO_HASH), g_strdup((gchar *) "true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_DISPLAY_SAS_ONCE), g_strdup((gchar *) "false")); + account_insert(current, ACCOUNT_SRTP_ENABLED, "true"); + account_insert(current, ACCOUNT_KEY_EXCHANGE, ZRTP); + account_insert(current, ACCOUNT_ZRTP_DISPLAY_SAS, "true"); + account_insert(current, ACCOUNT_ZRTP_NOT_SUPP_WARNING, "true"); + account_insert(current, ACCOUNT_ZRTP_HELLO_HASH, "true"); + account_insert(current, ACCOUNT_DISPLAY_SAS_ONCE, "false"); } - // Add default interface info gchar ** iface_list = NULL; iface_list = (gchar**) dbus_get_all_ip_interface_by_name(); @@ -174,9 +172,8 @@ static void sip_apply_callback(void) iface = iface_list; DEBUG("Selected interface %s", *iface); - g_hash_table_insert(current->properties, g_strdup(LOCAL_INTERFACE), g_strdup((gchar *) *iface)); - - g_hash_table_insert(current->properties, g_strdup(PUBLISHED_ADDRESS), g_strdup((gchar *) *iface)); + account_insert(current, LOCAL_INTERFACE, *iface); + account_insert(current, PUBLISHED_ADDRESS, *iface); dbus_add_account(current); getMessageSummary(gtk_entry_get_text(GTK_ENTRY(wiz->sip_alias)), @@ -196,20 +193,19 @@ static void sip_apply_callback(void) static void iax_apply_callback(void) { if (account_type == _IAX) { - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ALIAS), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_alias)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ENABLED), g_strdup("true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_MAILBOX), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_voicemail)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_TYPE), g_strdup("IAX")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_USERNAME), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_username)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_HOSTNAME), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_server)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_PASSWORD), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_password)))); + account_insert(current, ACCOUNT_ALIAS, gtk_entry_get_text(GTK_ENTRY(wiz->iax_alias))); + account_insert(current, ACCOUNT_ENABLED, "true"); + account_insert(current, ACCOUNT_MAILBOX, gtk_entry_get_text(GTK_ENTRY(wiz->iax_voicemail))); + account_insert(current, ACCOUNT_TYPE, "IAX"); + account_insert(current, ACCOUNT_USERNAME, gtk_entry_get_text(GTK_ENTRY(wiz->iax_username))); + account_insert(current, ACCOUNT_HOSTNAME, gtk_entry_get_text(GTK_ENTRY(wiz->iax_server))); + account_insert(current, ACCOUNT_PASSWORD, gtk_entry_get_text(GTK_ENTRY(wiz->iax_password))); dbus_add_account(current); getMessageSummary(gtk_entry_get_text(GTK_ENTRY(wiz->iax_alias)), gtk_entry_get_text(GTK_ENTRY(wiz->iax_server)), gtk_entry_get_text(GTK_ENTRY(wiz->iax_username)), - FALSE - ) ; + FALSE); gtk_label_set_text(GTK_LABEL(wiz->label_summary), message); } @@ -222,28 +218,24 @@ void enable_stun(GtkWidget* widget) void build_wizard(void) { - use_sflphone_org = 1; + use_sflphone_org = TRUE; if (wiz) - return ; + return; wiz = (struct _wizard*) g_malloc(sizeof(struct _wizard)); - current = g_new0(account_t, 1); - current->properties = NULL; - current->properties = dbus_get_account_details(NULL); + current = create_default_account(); if (current->properties == NULL) { DEBUG("Failed to get default values. Creating from scratch"); current->properties = g_hash_table_new(NULL, g_str_equal); } - current->accountID = g_strdup("new"); - wiz->assistant = gtk_assistant_new(); gtk_window_set_title(GTK_WINDOW(wiz->assistant), _("SFLphone account creation wizard")); gtk_window_set_position(GTK_WINDOW(wiz->assistant), GTK_WIN_POS_CENTER); - gtk_window_set_default_size(GTK_WINDOW(wiz->assistant), 200 , 200); + gtk_window_set_default_size(GTK_WINDOW(wiz->assistant), 200, 200); build_intro(); build_sfl_or_account(); @@ -254,22 +246,20 @@ void build_wizard(void) build_email_configuration(); build_summary(); - g_signal_connect(G_OBJECT(wiz->assistant), "close" , G_CALLBACK(close_callback), NULL); + g_signal_connect(G_OBJECT(wiz->assistant), "close", G_CALLBACK(close_callback), NULL); - g_signal_connect(G_OBJECT(wiz->assistant), "cancel" , G_CALLBACK(cancel_callback), NULL); + g_signal_connect(G_OBJECT(wiz->assistant), "cancel", G_CALLBACK(cancel_callback), NULL); gtk_widget_show_all(wiz->assistant); - gtk_assistant_set_forward_page_func(GTK_ASSISTANT(wiz->assistant), (GtkAssistantPageFunc) forward_page_func , NULL , NULL); + gtk_assistant_set_forward_page_func(GTK_ASSISTANT(wiz->assistant), (GtkAssistantPageFunc) forward_page_func, NULL, NULL); gtk_assistant_update_buttons_state(GTK_ASSISTANT(wiz->assistant)); } GtkWidget* build_intro() { - GtkWidget *label; - - wiz->intro = create_vbox(GTK_ASSISTANT_PAGE_INTRO , "SFLphone GNOME client" , _("Welcome to the Account creation wizard of SFLphone!")); - label = gtk_label_new(_("This installation wizard will help you configure an account.")) ; + wiz->intro = create_vbox(GTK_ASSISTANT_PAGE_INTRO, "SFLphone GNOME client", _("Welcome to the Account creation wizard of SFLphone!")); + GtkWidget *label = gtk_label_new(_("This installation wizard will help you configure an account.")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_widget_set_size_request(GTK_WIDGET(label), 380, -1); @@ -281,17 +271,14 @@ GtkWidget* build_intro() GtkWidget* build_select_account() { - GtkWidget* sip; - GtkWidget* iax; - - wiz->protocols = create_vbox(GTK_ASSISTANT_PAGE_CONTENT , _("VoIP Protocols") , _("Select an account type")); + wiz->protocols = create_vbox(GTK_ASSISTANT_PAGE_CONTENT, _("VoIP Protocols"), _("Select an account type")); - sip = gtk_radio_button_new_with_label(NULL, _("SIP (Session Initiation Protocol)")); - gtk_box_pack_start(GTK_BOX(wiz->protocols) , sip , TRUE, TRUE, 0); - iax = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sip), _("IAX2 (InterAsterix Exchange)")); - gtk_box_pack_start(GTK_BOX(wiz->protocols) , iax , TRUE, TRUE, 0); + GtkWidget *sip = gtk_radio_button_new_with_label(NULL, _("SIP (Session Initiation Protocol)")); + gtk_box_pack_start(GTK_BOX(wiz->protocols), sip, TRUE, TRUE, 0); + GtkWidget *iax = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sip), _("IAX2 (InterAsterix Exchange)")); + gtk_box_pack_start(GTK_BOX(wiz->protocols), iax, TRUE, TRUE, 0); - g_signal_connect(G_OBJECT(sip) , "clicked" , G_CALLBACK(set_account_type) , NULL); + g_signal_connect(G_OBJECT(sip), "clicked", G_CALLBACK(set_account_type), NULL); gtk_assistant_set_page_complete(GTK_ASSISTANT(wiz->assistant), wiz->protocols, TRUE); return wiz->protocols; @@ -300,16 +287,13 @@ GtkWidget* build_select_account() GtkWidget* build_sfl_or_account() { - GtkWidget* sfl; - GtkWidget* cus; + wiz->sflphone_org = create_vbox(GTK_ASSISTANT_PAGE_CONTENT, _("Account"), _("Please select one of the following options")); - wiz->sflphone_org = create_vbox(GTK_ASSISTANT_PAGE_CONTENT , _("Account") , _("Please select one of the following options")); - - sfl = gtk_radio_button_new_with_label(NULL, _("Create a free SIP/IAX2 account on sflphone.org \n(For testing purpose only)")); - gtk_box_pack_start(GTK_BOX(wiz->sflphone_org) , sfl , TRUE, TRUE, 0); - cus = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sfl), _("Register an existing SIP or IAX2 account")); - gtk_box_pack_start(GTK_BOX(wiz->sflphone_org) , cus , TRUE, TRUE, 0); - g_signal_connect(G_OBJECT(sfl) , "clicked" , G_CALLBACK(set_sflphone_org) , NULL); + GtkWidget *sfl = gtk_radio_button_new_with_label(NULL, _("Create a free SIP/IAX2 account on sflphone.org \n(For testing purpose only)")); + gtk_box_pack_start(GTK_BOX(wiz->sflphone_org), sfl, TRUE, TRUE, 0); + GtkWidget *cus = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sfl), _("Register an existing SIP or IAX2 account")); + gtk_box_pack_start(GTK_BOX(wiz->sflphone_org), cus, TRUE, TRUE, 0); + g_signal_connect(G_OBJECT(sfl), "clicked", G_CALLBACK(set_sflphone_org), NULL); return wiz->sflphone_org; } @@ -321,12 +305,12 @@ GtkWidget* build_sip_account_configuration(void) GtkWidget* label; GtkWidget * clearTextCheckbox; - wiz->sip_account = create_vbox(GTK_ASSISTANT_PAGE_CONTENT , _("SIP account settings") , _("Please fill the following information")); + wiz->sip_account = create_vbox(GTK_ASSISTANT_PAGE_CONTENT, _("SIP account settings"), _("Please fill the following information")); // table - table = gtk_table_new(7, 2 , FALSE/* homogeneous */); + table = gtk_table_new(7, 2, FALSE/* homogeneous */); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); - gtk_box_pack_start(GTK_BOX(wiz->sip_account) , table , TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(wiz->sip_account), table, TRUE, TRUE, 0); // alias field label = gtk_label_new_with_mnemonic(_("_Alias")); @@ -380,7 +364,7 @@ GtkWidget* build_sip_account_configuration(void) wiz->zrtp_enable = gtk_check_button_new_with_mnemonic(_("Secure communications with _ZRTP")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wiz->zrtp_enable), FALSE); gtk_table_attach(GTK_TABLE(table), wiz->zrtp_enable, 0, 1, 6, 7, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(wiz->zrtp_enable) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(wiz->zrtp_enable), TRUE); //gtk_assistant_set_page_complete(GTK_ASSISTANT(wiz->assistant), wiz->sip_account, TRUE); return wiz->sip_account; @@ -391,12 +375,12 @@ GtkWidget* build_email_configuration(void) GtkWidget* label; GtkWidget* table; - wiz->email = create_vbox(GTK_ASSISTANT_PAGE_CONTENT , _("Optional email address") , _("This email address will be used to send your voicemail messages.")); + wiz->email = create_vbox(GTK_ASSISTANT_PAGE_CONTENT, _("Optional email address"), _("This email address will be used to send your voicemail messages.")); - table = gtk_table_new(4, 2 , FALSE/* homogeneous */); + table = gtk_table_new(4, 2, FALSE/* homogeneous */); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); - gtk_box_pack_start(GTK_BOX(wiz->email) , table , TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(wiz->email), table, TRUE, TRUE, 0); // email field label = gtk_label_new_with_mnemonic(_("_Email address")); @@ -410,7 +394,7 @@ GtkWidget* build_email_configuration(void) wiz->zrtp_enable = gtk_check_button_new_with_mnemonic(_("Secure communications with _ZRTP")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wiz->zrtp_enable), FALSE); gtk_table_attach(GTK_TABLE(table), wiz->zrtp_enable, 0, 1, 5, 6, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(wiz->zrtp_enable) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(wiz->zrtp_enable), TRUE); return wiz->email; } @@ -421,12 +405,12 @@ GtkWidget* build_iax_account_configuration(void) GtkWidget* table; GtkWidget * clearTextCheckbox; - wiz->iax_account = create_vbox(GTK_ASSISTANT_PAGE_CONFIRM , _("IAX2 account settings") , _("Please fill the following information")); + wiz->iax_account = create_vbox(GTK_ASSISTANT_PAGE_CONFIRM, _("IAX2 account settings"), _("Please fill the following information")); - table = gtk_table_new(6, 2 , FALSE/* homogeneous */); + table = gtk_table_new(6, 2, FALSE/* homogeneous */); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); - gtk_box_pack_start(GTK_BOX(wiz->iax_account) , table , TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(wiz->iax_account), table, TRUE, TRUE, 0); // alias field label = gtk_label_new_with_mnemonic(_("_Alias")); @@ -477,7 +461,7 @@ GtkWidget* build_iax_account_configuration(void) current -> state = ACCOUNT_STATE_UNREGISTERED; - g_signal_connect(G_OBJECT(wiz->assistant) , "apply" , G_CALLBACK(iax_apply_callback), NULL); + g_signal_connect(G_OBJECT(wiz->assistant), "apply", G_CALLBACK(iax_apply_callback), NULL); return wiz->iax_account; } @@ -487,20 +471,20 @@ GtkWidget* build_nat_settings(void) GtkWidget* label; GtkWidget* table; - wiz->nat = create_vbox(GTK_ASSISTANT_PAGE_CONFIRM , _("Network Address Translation (NAT)") , _("You should probably enable this if you are behind a firewall.")); + wiz->nat = create_vbox(GTK_ASSISTANT_PAGE_CONFIRM, _("Network Address Translation (NAT)"), _("You should probably enable this if you are behind a firewall.")); // table - table = gtk_table_new(2, 2 , FALSE/* homogeneous */); + table = gtk_table_new(2, 2, FALSE/* homogeneous */); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); - gtk_box_pack_start(GTK_BOX(wiz->nat), table , TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(wiz->nat), table, TRUE, TRUE, 0); // enable wiz->enable = gtk_check_button_new_with_mnemonic(_("E_nable STUN")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wiz->enable), FALSE); gtk_table_attach(GTK_TABLE(table), wiz->enable, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(wiz->enable) , TRUE); - g_signal_connect(G_OBJECT(GTK_TOGGLE_BUTTON(wiz->enable)) , "toggled" , G_CALLBACK(enable_stun), NULL); + gtk_widget_set_sensitive(GTK_WIDGET(wiz->enable), TRUE); + g_signal_connect(G_OBJECT(GTK_TOGGLE_BUTTON(wiz->enable)), "toggled", G_CALLBACK(enable_stun), NULL); // server address label = gtk_label_new_with_mnemonic(_("_STUN server")); @@ -511,21 +495,20 @@ GtkWidget* build_nat_settings(void) gtk_table_attach(GTK_TABLE(table), wiz->addr, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_set_sensitive(GTK_WIDGET(wiz->addr), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiz->enable))); - g_signal_connect(G_OBJECT(wiz->assistant) , "apply" , G_CALLBACK(sip_apply_callback), NULL); + g_signal_connect(G_OBJECT(wiz->assistant), "apply", G_CALLBACK(sip_apply_callback), NULL); return wiz->nat; } GtkWidget* build_summary() { - wiz->summary = create_vbox(GTK_ASSISTANT_PAGE_SUMMARY , _("Account Registration") , _("Congratulations!")); + wiz->summary = create_vbox(GTK_ASSISTANT_PAGE_SUMMARY, _("Account Registration"), _("Congratulations!")); strcpy(message,""); - wiz->label_summary = gtk_label_new(message) ; + wiz->label_summary = gtk_label_new(message); gtk_label_set_selectable(GTK_LABEL(wiz->label_summary), TRUE); gtk_misc_set_alignment(GTK_MISC(wiz->label_summary), 0, 0); gtk_label_set_line_wrap(GTK_LABEL(wiz->label_summary), TRUE); - //gtk_widget_set_size_request(GTK_WIDGET(wiz->label_summary), 380, -1); gtk_box_pack_start(GTK_BOX(wiz->summary), wiz->label_summary, FALSE, TRUE, 0); return wiz->summary; @@ -534,9 +517,9 @@ GtkWidget* build_summary() GtkWidget* build_registration_error() { GtkWidget *label; - wiz->reg_failed = create_vbox(GTK_ASSISTANT_PAGE_SUMMARY , "Account Registration" , "Registration error"); + wiz->reg_failed = create_vbox(GTK_ASSISTANT_PAGE_SUMMARY, "Account Registration", "Registration error"); - label = gtk_label_new(" Please correct the information.") ; + label = gtk_label_new(" Please correct the information."); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_widget_set_size_request(GTK_WIDGET(label), 380, -1); @@ -555,7 +538,7 @@ void set_sip_infos_sentivite(gboolean b) void prefill_sip(void) { - if (use_sflphone_org == 1) { + if (use_sflphone_org) { char alias[300]; char *email; email = (char *) gtk_entry_get_text(GTK_ENTRY(wiz->mailbox)); @@ -585,7 +568,7 @@ typedef enum { PAGE_SUMMARY } assistant_state; -static gint forward_page_func(gint current_page , gpointer data UNUSED) +static gint forward_page_func(gint current_page, gpointer data UNUSED) { gint next_page = 0; @@ -595,9 +578,9 @@ static gint forward_page_func(gint current_page , gpointer data UNUSED) break; case PAGE_SFL: - if (use_sflphone_org) { + if (use_sflphone_org) next_page = PAGE_EMAIL; - } else + else next_page = PAGE_TYPE; break; @@ -606,8 +589,9 @@ static gint forward_page_func(gint current_page , gpointer data UNUSED) if (account_type == _SIP) { set_sip_infos_sentivite(TRUE); next_page = PAGE_SIP; - } else + } else { next_page = PAGE_IAX; + } break; case PAGE_SIP: @@ -635,18 +619,13 @@ static gint forward_page_func(gint current_page , gpointer data UNUSED) static GtkWidget* create_vbox(GtkAssistantPageType type, const gchar *title, const gchar *section) { - GtkWidget *vbox; - GtkWidget *label; - gchar *str; - - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); + GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); gtk_container_set_border_width(GTK_CONTAINER(vbox), 24); gtk_assistant_append_page(GTK_ASSISTANT(wiz->assistant), vbox); gtk_assistant_set_page_type(GTK_ASSISTANT(wiz->assistant), vbox, type); - str = g_strdup_printf(" %s", title); + gchar *str = g_strdup_printf(" %s", title); gtk_assistant_set_page_title(GTK_ASSISTANT(wiz->assistant), vbox, str); - g_free(str); gtk_assistant_set_page_complete(GTK_ASSISTANT(wiz->assistant), vbox, TRUE); @@ -660,7 +639,7 @@ static GtkWidget* create_vbox(GtkAssistantPageType type, const gchar *title, con #endif if (section) { - label = gtk_label_new(NULL); + GtkWidget *label = gtk_label_new(NULL); str = g_strdup_printf("<b>%s</b>\n", section); gtk_label_set_markup(GTK_LABEL(label), str); g_free(str); diff --git a/gnome/src/config/audioconf.c b/gnome/src/config/audioconf.c index d449d3e51a9c91659e18d85a08d2dea9663e18d1..c47effe19e0f3f7aae9e03c30ee6f70f0e447d63 100644 --- a/gnome/src/config/audioconf.c +++ b/gnome/src/config/audioconf.c @@ -28,7 +28,9 @@ * as that of the covered work. */ - +#include <glib/gi18n.h> +#include "gtk2_wrappers.h" +#include "str_utils.h" #include "audioconf.h" #include "utils.h" #include "logger.h" @@ -69,15 +71,16 @@ static void active_is_always_recording(void); /** * Fills the tree list with supported codecs */ -static void preferences_dialog_fill_codec_list(account_t *a) +static void +preferences_dialog_fill_codec_list(const account_t *account) { // Get model of view and clear it GtkListStore *codecStore = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(codecTreeView))); gtk_list_store_clear(codecStore); - GQueue *current = a ? a->codecs : get_system_codec_list(); + GQueue *current = account ? account->codecs : get_system_codec_list(); - if (!a) DEBUG("Using system codec list"); + if (!account) DEBUG("Using system codec list"); // Insert codecs for (guint i = 0; i < g_queue_get_length(current); i++) { @@ -90,7 +93,7 @@ static void preferences_dialog_fill_codec_list(account_t *a) gtk_list_store_set(codecStore, &iter, COLUMN_CODEC_ACTIVE, c->is_active, COLUMN_CODEC_NAME, c->name, - COLUMN_CODEC_FREQUENCY, g_strdup_printf("%f kHz", c->sample_rate * 0.001), + COLUMN_CODEC_FREQUENCY, g_strdup_printf("%d kHz", (gint)(c->sample_rate * 0.001)), COLUMN_CODEC_BITRATE, g_strdup_printf("%.1f kbps", c->_bitrate), -1); } @@ -181,7 +184,7 @@ select_active_output_audio_device() } while (gtk_tree_model_iter_next(model, &iter)); // No index was found, select first one - WARN("Warning : No active output device found"); + WARN("No active output device found"); gtk_combo_box_set_active(GTK_COMBO_BOX(output), 0); } @@ -271,7 +274,7 @@ select_active_input_audio_device() void update_device_widget(gchar *pluginName) { - if (g_strcasecmp(pluginName, "default") == 0) { + if (utf8_case_equal(pluginName, "default")) { gtk_widget_set_sensitive(output, FALSE); gtk_widget_set_sensitive(input, FALSE); gtk_widget_set_sensitive(ringtone, FALSE); @@ -314,7 +317,7 @@ select_active_output_audio_plugin() do { gtk_tree_model_get(model, &iter, 0, &pluginname, -1); - if (g_strcasecmp(tmp, pluginname) == 0) { + if (utf8_case_equal(tmp, pluginname)) { // Set current iteration the active one gtk_combo_box_set_active_iter(GTK_COMBO_BOX(plugin), &iter); return; @@ -404,7 +407,7 @@ codec_active_toggled(GtkCellRendererToggle *renderer UNUSED, gchar *path, gpoint account_t *acc = (account_t*) data; if (!acc) { - ERROR("Aie, no account selected"); + ERROR("no account selected"); return; } @@ -416,16 +419,15 @@ codec_active_toggled(GtkCellRendererToggle *renderer UNUSED, gchar *path, gpoint COLUMN_CODEC_NAME, &name, COLUMN_CODEC_FREQUENCY, &srate, -1); - DEBUG("%s, %s\n", name, srate); - DEBUG("%i\n", g_queue_get_length(acc->codecs)); + DEBUG("Selected Codec: %s, %s", name, srate); codec_t* codec; - if ((g_strcasecmp(name,"speex") == 0) && (g_strcasecmp(srate,"8 kHz") == 0)) + if (utf8_case_equal(name,"speex") && utf8_case_equal(srate,"8 kHz")) codec = codec_list_get_by_payload((gconstpointer) 110, acc->codecs); - else if ((g_strcasecmp(name,"speex") ==0) && (g_strcasecmp(srate,"16 kHz") ==0)) + else if (utf8_case_equal(name,"speex") && utf8_case_equal(srate,"16 kHz")) codec = codec_list_get_by_payload((gconstpointer) 111, acc->codecs); - else if ((g_strcasecmp(name,"speex") ==0) && (g_strcasecmp(srate,"32 kHz") ==0)) + else if (utf8_case_equal(name,"speex") && utf8_case_equal(srate, "32 kHz")) codec = codec_list_get_by_payload((gconstpointer) 112, acc->codecs); else codec = codec_list_get_by_name((gconstpointer) name, acc->codecs); @@ -516,7 +518,7 @@ static void codec_move_down(GtkButton *button UNUSED, gpointer data) codec_move(FALSE, data); } -GtkWidget* audiocodecs_box(account_t *a) +GtkWidget* audiocodecs_box(const account_t *account) { GtkWidget *audiocodecs_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_container_set_border_width(GTK_CONTAINER(audiocodecs_hbox), 10); @@ -528,10 +530,11 @@ GtkWidget* audiocodecs_box(account_t *a) gtk_box_pack_start(GTK_BOX(audiocodecs_hbox), scrolledWindow, TRUE, TRUE, 0); GtkListStore *codecStore = gtk_list_store_new(CODEC_COLUMN_COUNT, G_TYPE_BOOLEAN, /* Active */ - G_TYPE_STRING, /* Name */ - G_TYPE_STRING, /* Frequency */ - G_TYPE_STRING, /* Bit rate */ - G_TYPE_STRING /* Bandwith */); + G_TYPE_STRING, /* Name */ + G_TYPE_STRING, /* Frequency */ + G_TYPE_STRING, /* Bit rate */ + G_TYPE_STRING /* Bandwidth */ + ); // Create codec tree view with list store codecTreeView = gtk_tree_view_new_with_model(GTK_TREE_MODEL(codecStore)); @@ -547,7 +550,8 @@ GtkWidget* audiocodecs_box(account_t *a) gtk_tree_view_append_column(GTK_TREE_VIEW(codecTreeView), treeViewColumn); // Toggle codec active property on clicked - g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(codec_active_toggled),(gpointer) a); + g_signal_connect(G_OBJECT(renderer), "toggled", + G_CALLBACK(codec_active_toggled), (gpointer) account); // Name column renderer = gtk_cell_renderer_text_new(); @@ -575,14 +579,16 @@ GtkWidget* audiocodecs_box(account_t *a) codecMoveUpButton = gtk_button_new_from_stock(GTK_STOCK_GO_UP); gtk_widget_set_sensitive(GTK_WIDGET(codecMoveUpButton), FALSE); gtk_box_pack_start(GTK_BOX(buttonBox), codecMoveUpButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(codecMoveUpButton), "clicked", G_CALLBACK(codec_move_up), a); + g_signal_connect(G_OBJECT(codecMoveUpButton), "clicked", + G_CALLBACK(codec_move_up), (gpointer) account); codecMoveDownButton = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); gtk_widget_set_sensitive(GTK_WIDGET(codecMoveDownButton), FALSE); gtk_box_pack_start(GTK_BOX(buttonBox), codecMoveDownButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(codecMoveDownButton), "clicked", G_CALLBACK(codec_move_down), a); + g_signal_connect(G_OBJECT(codecMoveDownButton), "clicked", + G_CALLBACK(codec_move_down), (gpointer) account); - preferences_dialog_fill_codec_list(a); + preferences_dialog_fill_codec_list(account); return audiocodecs_hbox; } @@ -610,6 +616,7 @@ select_audio_manager(void) gtk_action_set_sensitive(volumeToggle_, FALSE); } + } void @@ -670,7 +677,7 @@ GtkWidget* alsa_box() GtkWidget *info_bar = gnome_info_bar(message, GTK_MESSAGE_INFO); gtk_table_attach(GTK_TABLE(table), info_bar, 1, 3, 1, 2, GTK_FILL, GTK_SHRINK, 10, 10); - DEBUG("Audio: Configuration plugin"); + DEBUG("Configuration plugin"); GtkWidget *label = gtk_label_new(_("ALSA plugin")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); @@ -692,7 +699,7 @@ GtkWidget* alsa_box() // Device : Output device // Create title label - DEBUG("Audio: Configuration output"); + DEBUG("Configuration output"); label = gtk_label_new(_("Output")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); @@ -714,7 +721,7 @@ GtkWidget* alsa_box() // Device : Input device // Create title label - DEBUG("Audio: Configuration input"); + DEBUG("Configuration input"); label = gtk_label_new(_("Input")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 4, 5, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); @@ -735,7 +742,7 @@ GtkWidget* alsa_box() gtk_table_attach(GTK_TABLE(table), input, 2, 3, 4, 5, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); gtk_widget_show(input); - DEBUG("Audio: Configuration rintgtone"); + DEBUG("Configuration rintgtone"); label = gtk_label_new(_("Ringtone")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 5, 6, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); @@ -820,7 +827,7 @@ GtkWidget* create_audio_configuration() GtkWidget *folderChooser = gtk_file_chooser_button_new(_("Select a folder"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); /* Get the path where to save audio files */ gchar *recordingPath = dbus_get_record_path(); - DEBUG("AudioConf: Load recording path %s", recordingPath); + DEBUG("Load recording path %s", recordingPath); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(folderChooser), recordingPath); g_free(recordingPath); diff --git a/gnome/src/config/audioconf.h b/gnome/src/config/audioconf.h index 6f0b399f733a404964776239e22156bfd4f86058..c3f3e221d1ca9fb51eb143ecccec25c7b0c86a90 100644 --- a/gnome/src/config/audioconf.h +++ b/gnome/src/config/audioconf.h @@ -38,7 +38,7 @@ GtkWidget* create_audio_configuration (void); GtkWidget* api_box(); GtkWidget* alsa_box(); GtkWidget* pulse_box(); -GtkWidget* audiocodecs_box(); +GtkWidget* audiocodecs_box(const account_t *a); GtkWidget* ringtone_box(); gboolean get_api(); diff --git a/gnome/src/config/hooks-config.c b/gnome/src/config/hooks-config.c index 2b3e9e882cb9c9cb7de77567699b5008eb764aa4..cfbc79e44d4a2d766132089f63c85e2a8370784f 100644 --- a/gnome/src/config/hooks-config.c +++ b/gnome/src/config/hooks-config.c @@ -28,6 +28,9 @@ * as that of the covered work. */ +#include <glib/gi18n.h> +#include "gtk2_wrappers.h" +#include "str_utils.h" #include "hooks-config.h" #include "dbus.h" @@ -155,7 +158,7 @@ GtkWidget* create_hooks_settings() gtk_table_attach(GTK_TABLE(table), info_bar, 0, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 10, 10); widg = gtk_check_button_new_with_mnemonic(_("Trigger on specific _SIP header")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), (g_strcasecmp(_urlhook_config->sip_enabled, "true") ==0) ?TRUE:FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), utf8_case_equal(_urlhook_config->sip_enabled, "true")); g_signal_connect(G_OBJECT(widg) , "clicked" , G_CALLBACK(sip_enabled_cb), NULL); gtk_table_attach(GTK_TABLE(table), widg, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); @@ -164,7 +167,7 @@ GtkWidget* create_hooks_settings() gtk_table_attach(GTK_TABLE(table), field, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); widg = gtk_check_button_new_with_mnemonic(_("Trigger on _IAX2 URL")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), (g_strcasecmp(_urlhook_config->iax2_enabled, "true") ==0) ?TRUE:FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), utf8_case_equal(_urlhook_config->iax2_enabled, "true")); g_signal_connect(G_OBJECT(widg) , "clicked" , G_CALLBACK(iax2_enabled_cb), NULL); gtk_table_attach(GTK_TABLE(table), widg, 0, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); @@ -176,14 +179,12 @@ GtkWidget* create_hooks_settings() gtk_entry_set_text(GTK_ENTRY(command), _urlhook_config->command); gtk_table_attach(GTK_TABLE(table), command, 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 10); - - gnome_main_section_new_with_table(_("Phone number rewriting"), &frame, &table, 4, 2); gtk_box_pack_start(GTK_BOX(ret), frame, FALSE, FALSE, 0); gtk_widget_show(frame); widg = gtk_check_button_new_with_mnemonic(_("_Prefix dialed numbers with")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), (g_strcasecmp(_urlhook_config->phone_number_enabled, "true") ==0) ?TRUE:FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), utf8_case_equal(_urlhook_config->phone_number_enabled, "true")); g_signal_connect(G_OBJECT(widg) , "clicked" , G_CALLBACK(phone_number_enabled_cb), NULL); gtk_table_attach(GTK_TABLE(table), widg, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); diff --git a/gnome/src/config/hooks-config.h b/gnome/src/config/hooks-config.h index 6f51be9249afb8b37306ebc315209d419daef85b..e35a5b9f203aa7f5ec2a1e90ea5ee755e2ac136f 100644 --- a/gnome/src/config/hooks-config.h +++ b/gnome/src/config/hooks-config.h @@ -32,7 +32,7 @@ #define _HOOKS_CONFIG #include <gtk/gtk.h> -#include <glib/gtypes.h> +#include <glib.h> #include "actions.h" #include "utils.h" diff --git a/gnome/src/config/preferencesdialog.c b/gnome/src/config/preferencesdialog.c index 3bd50579130952f4b00f007b497ca63b3c44145a..fb281af2fd4d6b85389f4aa3514e47e0f72c80f9 100644 --- a/gnome/src/config/preferencesdialog.c +++ b/gnome/src/config/preferencesdialog.c @@ -32,12 +32,14 @@ * as that of the covered work. */ +#include <glib/gi18n.h> #include <gtk/gtk.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> +#include "gtk2_wrappers.h" #include "eel-gconf-extensions.h" #include "dbus.h" #include "logger.h" @@ -362,7 +364,7 @@ static GtkTreeModel* create_model(GtkWidget *widget) PAGE_NUMBER, browser_entries_full[i].page_number, -1); if (pixbuf) - gdk_pixbuf_unref(pixbuf); + g_object_unref(pixbuf); } return GTK_TREE_MODEL(store); diff --git a/gnome/src/config/shortcuts-config.c b/gnome/src/config/shortcuts-config.c index caa354a22c2030d920c88ed846d61bc9a321ff08..f6a31c82c03a17ab84bae5cba7e8b28ecd71bf66 100644 --- a/gnome/src/config/shortcuts-config.c +++ b/gnome/src/config/shortcuts-config.c @@ -28,7 +28,10 @@ * as that of the covered work. */ +#include "gtk2_wrappers.h" +#include <glib/gi18n.h> #include <gdk/gdk.h> +#include <X11/XKBlib.h> #include "shortcuts-config.h" #include "shortcuts.h" #include "unused.h" @@ -129,7 +132,7 @@ create_shortcuts_settings() gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, ACTION, _(list[i].action), MASK, (gint) list[i].mask, VALUE, - XKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), list[i].key, 0), -1); + XkbKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), list[i].key, 0, 0), -1); } gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store)); diff --git a/gnome/src/config/shortcuts-config.h b/gnome/src/config/shortcuts-config.h index abcb424201bdd7f0a568744508acbe3bf0bfc962..123cb9c743a12693eb2ce1e0a39af7f722c4131e 100644 --- a/gnome/src/config/shortcuts-config.h +++ b/gnome/src/config/shortcuts-config.h @@ -32,7 +32,7 @@ #define _SHORTCUTS_CONFIG #include <gtk/gtk.h> -#include <glib/gtypes.h> +#include <glib.h> #include "actions.h" #include <utils.h> diff --git a/gnome/src/config/tlsadvanceddialog.c b/gnome/src/config/tlsadvanceddialog.c index 3d6c11860099d0647afb3b88f35b97dc07e37d99..2ae6f2b8c611a97cf9ccfcecc7a0f9bdc90d9937 100644 --- a/gnome/src/config/tlsadvanceddialog.c +++ b/gnome/src/config/tlsadvanceddialog.c @@ -28,15 +28,30 @@ * as that of the covered work. */ -#include <tlsadvanceddialog.h> -#include <sflphone_const.h> -#include <utils.h> +#include "tlsadvanceddialog.h" +#include "gtk2_wrappers.h" +#include "str_utils.h" +#include "sflphone_const.h" +#include "mainwindow.h" +#include "utils.h" #include <dbus.h> - +#include <glib/gi18n.h> #include <gtk/gtk.h> #include <math.h> -void show_advanced_tls_options(GHashTable * properties) +static +const gchar *toggle_to_string(GtkWidget *toggle) +{ + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)) ? "true" : "false"; +} + +static +const gchar *get_filename(GtkWidget *chooser) +{ + return gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser)); +} + +void show_advanced_tls_options(account_t *account) { GtkDialog *tlsDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Advanced options for TLS"), GTK_WINDOW(get_main_window()), @@ -71,7 +86,6 @@ void show_advanced_tls_options(GHashTable * properties) gtk_label_set_markup(GTK_LABEL(label), description); gtk_table_attach(GTK_TABLE(table), label, 0, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gchar * account_id = NULL; gchar * tls_listener_port = NULL; gchar * tls_ca_list_file = NULL; gchar * tls_certificate_file = NULL; @@ -86,23 +100,20 @@ void show_advanced_tls_options(GHashTable * properties) gchar * negotiation_timeout_sec = NULL; gchar * negotiation_timeout_msec = NULL; - if (properties != NULL) { - - account_id = g_hash_table_lookup(properties, ACCOUNT_ID); - tls_listener_port = g_hash_table_lookup(properties, TLS_LISTENER_PORT); - tls_ca_list_file = g_hash_table_lookup(properties, TLS_CA_LIST_FILE); - tls_certificate_file = g_hash_table_lookup(properties, TLS_CERTIFICATE_FILE); - tls_private_key_file = g_hash_table_lookup(properties, TLS_PRIVATE_KEY_FILE); - tls_password = g_hash_table_lookup(properties, TLS_PASSWORD); - tls_method = g_hash_table_lookup(properties, TLS_METHOD); - tls_ciphers = g_hash_table_lookup(properties, TLS_CIPHERS); - tls_server_name = g_hash_table_lookup(properties, TLS_SERVER_NAME); - verify_server = g_hash_table_lookup(properties, TLS_VERIFY_SERVER); - verify_client = g_hash_table_lookup(properties, TLS_VERIFY_CLIENT); - require_client_certificate = g_hash_table_lookup(properties, TLS_REQUIRE_CLIENT_CERTIFICATE); - negotiation_timeout_sec = g_hash_table_lookup(properties, TLS_NEGOTIATION_TIMEOUT_SEC); - negotiation_timeout_msec = g_hash_table_lookup(properties, TLS_NEGOTIATION_TIMEOUT_MSEC); - + if (account->properties != NULL) { + tls_listener_port = account_lookup(account, TLS_LISTENER_PORT); + tls_ca_list_file = account_lookup(account, TLS_CA_LIST_FILE); + tls_certificate_file = account_lookup(account, TLS_CERTIFICATE_FILE); + tls_private_key_file = account_lookup(account, TLS_PRIVATE_KEY_FILE); + tls_password = account_lookup(account, TLS_PASSWORD); + tls_method = account_lookup(account, TLS_METHOD); + tls_ciphers = account_lookup(account, TLS_CIPHERS); + tls_server_name = account_lookup(account, TLS_SERVER_NAME); + verify_server = account_lookup(account, TLS_VERIFY_SERVER); + verify_client = account_lookup(account, TLS_VERIFY_CLIENT); + require_client_certificate = account_lookup(account, TLS_REQUIRE_CLIENT_CERTIFICATE); + negotiation_timeout_sec = account_lookup(account, TLS_NEGOTIATION_TIMEOUT_SEC); + negotiation_timeout_msec = account_lookup(account, TLS_NEGOTIATION_TIMEOUT_MSEC); } @@ -116,23 +127,18 @@ void show_advanced_tls_options(GHashTable * properties) gtk_spin_button_set_value(GTK_SPIN_BUTTON(tlsListenerPort), g_ascii_strtod(tls_listener_port, NULL)); gtk_box_pack_start(GTK_BOX(hbox), tlsListenerPort, TRUE, TRUE, 0); - if (g_strcmp0(account_id, IP2IP_PROFILE) != 0) { - gtk_widget_set_sensitive(tlsListenerPort, FALSE); - } - label = gtk_label_new(_("Certificate of Authority list")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); GtkWidget * caListFileChooser = gtk_file_chooser_button_new(_("Choose a CA list file (optional)"), GTK_FILE_CHOOSER_ACTION_OPEN); gtk_table_attach(GTK_TABLE(table), caListFileChooser, 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - if (!tls_ca_list_file || !*tls_ca_list_file) { - gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(caListFileChooser)); - } else { + if (tls_ca_list_file && *tls_ca_list_file) { GFile *file = g_file_new_for_path(tls_ca_list_file); gtk_file_chooser_set_file(GTK_FILE_CHOOSER(caListFileChooser), file, NULL); g_object_unref(file); + } else { + gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(caListFileChooser)); } label = gtk_label_new(_("Public endpoint certificate file")); @@ -237,7 +243,7 @@ void show_advanced_tls_options(GHashTable * properties) GtkWidget * tlsTimeOutSec; hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 10, 11, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - tlsTimeOutSec = gtk_spin_button_new_with_range(0, pow(2,sizeof(long)), 1); + tlsTimeOutSec = gtk_spin_button_new_with_range(0, pow(2, sizeof(long)), 1); gtk_label_set_mnemonic_widget(GTK_LABEL(label), tlsTimeOutSec); gtk_spin_button_set_value(GTK_SPIN_BUTTON(tlsTimeOutSec), g_ascii_strtod(negotiation_timeout_sec, NULL)); gtk_box_pack_start(GTK_BOX(hbox), tlsTimeOutSec, TRUE, TRUE, 0); @@ -250,71 +256,53 @@ void show_advanced_tls_options(GHashTable * properties) GtkWidget * verifyCertificateServer; verifyCertificateServer = gtk_check_button_new_with_mnemonic(_("Verify incoming certificates, as a server")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(verifyCertificateServer), - g_strcasecmp(verify_server,"true") == 0 ? TRUE: FALSE); + utf8_case_equal(verify_server, "true")); gtk_table_attach(GTK_TABLE(table), verifyCertificateServer, 0, 1, 11, 12, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); GtkWidget * verifyCertificateClient; verifyCertificateClient = gtk_check_button_new_with_mnemonic(_("Verify certificates from answer, as a client")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(verifyCertificateClient), - g_strcasecmp(verify_client,"true") == 0 ? TRUE: FALSE); + utf8_case_equal(verify_client, "true")); gtk_table_attach(GTK_TABLE(table), verifyCertificateClient, 0, 1, 12, 13, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); GtkWidget * requireCertificate; requireCertificate = gtk_check_button_new_with_mnemonic(_("Require certificate for incoming tls connections")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(requireCertificate), - g_strcasecmp(require_client_certificate,"true") == 0 ? TRUE: FALSE); + utf8_case_equal(require_client_certificate,"true")); gtk_table_attach(GTK_TABLE(table), requireCertificate, 0, 1, 13, 14, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show_all(ret); if (gtk_dialog_run(GTK_DIALOG(tlsDialog)) == GTK_RESPONSE_ACCEPT) { - g_hash_table_replace(properties, - g_strdup(TLS_LISTENER_PORT), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(tlsListenerPort)))); - g_hash_table_replace(properties, - g_strdup(TLS_CA_LIST_FILE), g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(caListFileChooser)))); + account_replace(account, TLS_LISTENER_PORT, + gtk_entry_get_text(GTK_ENTRY(tlsListenerPort))); + account_replace(account, TLS_CA_LIST_FILE, get_filename(caListFileChooser)); - g_hash_table_replace(properties, - g_strdup(TLS_CERTIFICATE_FILE), g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(certificateFileChooser)))); + account_replace(account, TLS_CERTIFICATE_FILE, + get_filename(certificateFileChooser)); - g_hash_table_replace(properties, - g_strdup(TLS_PRIVATE_KEY_FILE), g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(privateKeyFileChooser)))); + account_replace(account, TLS_PRIVATE_KEY_FILE, + get_filename(privateKeyFileChooser)); - g_hash_table_replace(properties, - g_strdup(TLS_PASSWORD), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(privateKeyPasswordEntry)))); + account_replace(account, TLS_PASSWORD, gtk_entry_get_text(GTK_ENTRY(privateKeyPasswordEntry))); - g_hash_table_replace(properties, - g_strdup(TLS_METHOD), - g_strdup((gchar *) gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tlsProtocolMethodCombo)))); + gchar *tls_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tlsProtocolMethodCombo)); + account_replace(account, TLS_METHOD, tls_text); + g_free(tls_text); - g_hash_table_replace(properties, - g_strdup(TLS_CIPHERS), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(cipherListEntry)))); + account_replace(account, TLS_CIPHERS, gtk_entry_get_text(GTK_ENTRY(cipherListEntry))); - g_hash_table_replace(properties, - g_strdup(TLS_SERVER_NAME), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(serverNameInstance)))); + account_replace(account, TLS_SERVER_NAME, gtk_entry_get_text(GTK_ENTRY(serverNameInstance))); - g_hash_table_replace(properties, - g_strdup(TLS_VERIFY_SERVER), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(verifyCertificateServer)) ? "true": "false")); + account_replace(account, TLS_VERIFY_SERVER, toggle_to_string(verifyCertificateServer)); - g_hash_table_replace(properties, - g_strdup(TLS_VERIFY_CLIENT), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(verifyCertificateClient)) ? "true": "false")); + account_replace(account, TLS_VERIFY_CLIENT, toggle_to_string(verifyCertificateClient)); - g_hash_table_replace(properties, - g_strdup(TLS_REQUIRE_CLIENT_CERTIFICATE), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(requireCertificate)) ? "true": "false")); + account_replace(account, TLS_REQUIRE_CLIENT_CERTIFICATE, toggle_to_string(requireCertificate)); - g_hash_table_replace(properties, - g_strdup(TLS_NEGOTIATION_TIMEOUT_SEC), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(tlsTimeOutSec)))); + account_replace(account, TLS_NEGOTIATION_TIMEOUT_SEC, gtk_entry_get_text(GTK_ENTRY(tlsTimeOutSec))); - g_hash_table_replace(properties, - g_strdup(TLS_NEGOTIATION_TIMEOUT_MSEC), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(tlsTimeOutMSec)))); + account_replace(account, TLS_NEGOTIATION_TIMEOUT_MSEC, gtk_entry_get_text(GTK_ENTRY(tlsTimeOutMSec))); } gtk_widget_destroy(GTK_WIDGET(tlsDialog)); diff --git a/gnome/src/config/tlsadvanceddialog.h b/gnome/src/config/tlsadvanceddialog.h index 35d45d7eee4787c0b0d90a48e2704696d36b5cea..73a40ea6da7838d77ab680cf82019552eab7bc8f 100644 --- a/gnome/src/config/tlsadvanceddialog.h +++ b/gnome/src/config/tlsadvanceddialog.h @@ -28,19 +28,16 @@ * as that of the covered work. */ -#ifndef __SFL_TLS_ADVANCED_DIALOG__ -#define __SFL_TLS_ADVANCED_DIALOG__ +#ifndef TLS_ADVANCED_DIALOG_ +#define TLS_ADVANCED_DIALOG_ /** @file tlsadvanceddialog.h * @brief Display the advanced options window for tls */ -#include <glib.h> -#include <mainwindow.h> - +#include "accountlist.h" /** * Display the advanced options window for zrtp */ - -void show_advanced_tls_options (GHashTable * properties); +void show_advanced_tls_options(account_t *account); #endif diff --git a/gnome/src/config/zrtpadvanceddialog.c b/gnome/src/config/zrtpadvanceddialog.c index e50898a7be8b2b3bd5edd21ddfa1d9a866ef1636..8b1090655239eb32a19fac11c086d45babc3a6ad 100644 --- a/gnome/src/config/zrtpadvanceddialog.c +++ b/gnome/src/config/zrtpadvanceddialog.c @@ -28,24 +28,26 @@ * as that of the covered work. */ -#include <zrtpadvanceddialog.h> -#include <sflphone_const.h> -#include <utils.h> - +#include <glib/gi18n.h> #include <gtk/gtk.h> +#include "str_utils.h" +#include "mainwindow.h" +#include "zrtpadvanceddialog.h" +#include "sflphone_const.h" +#include "utils.h" -void show_advanced_zrtp_options(GHashTable * properties) +void show_advanced_zrtp_options(account_t *account) { gboolean curSasConfirm = TRUE; gboolean curHelloEnabled = TRUE; gboolean curZrtpNotSuppOther = TRUE; gboolean curDisplaySasOnce = FALSE; - if (properties != NULL) { - curHelloEnabled = !g_strcasecmp(g_hash_table_lookup(properties, ACCOUNT_ZRTP_HELLO_HASH), "true"); - curSasConfirm = !g_strcasecmp(g_hash_table_lookup(properties, ACCOUNT_ZRTP_DISPLAY_SAS), "true"); - curZrtpNotSuppOther = !g_strcasecmp(g_hash_table_lookup(properties, ACCOUNT_ZRTP_NOT_SUPP_WARNING), "true"); - curDisplaySasOnce = !g_strcasecmp(g_hash_table_lookup(properties, ACCOUNT_DISPLAY_SAS_ONCE), "true"); + if (account != NULL) { + curHelloEnabled = utf8_case_equal(account_lookup(account, ACCOUNT_ZRTP_HELLO_HASH), "true"); + curSasConfirm = utf8_case_equal(account_lookup(account, ACCOUNT_ZRTP_DISPLAY_SAS), "true"); + curZrtpNotSuppOther = utf8_case_equal(account_lookup(account, ACCOUNT_ZRTP_NOT_SUPP_WARNING), "true"); + curDisplaySasOnce = utf8_case_equal(account_lookup(account, ACCOUNT_DISPLAY_SAS_ONCE), "true"); } GtkDialog *securityDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("ZRTP Options"), @@ -55,13 +57,11 @@ void show_advanced_zrtp_options(GHashTable * properties) GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL) - ); + NULL)); gtk_window_set_resizable(GTK_WINDOW(securityDialog), FALSE); gtk_container_set_border_width(GTK_CONTAINER(securityDialog), 0); - - GtkWidget *tableZrtp = gtk_table_new(4, 2 , FALSE/* homogeneous */); + GtkWidget *tableZrtp = gtk_table_new(4, 2, FALSE /* homogeneous */); gtk_table_set_row_spacings(GTK_TABLE(tableZrtp), 10); gtk_table_set_col_spacings(GTK_TABLE(tableZrtp), 10); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(securityDialog)), tableZrtp, FALSE, FALSE, 0); @@ -70,70 +70,63 @@ void show_advanced_zrtp_options(GHashTable * properties) GtkWidget *enableHelloHash = gtk_check_button_new_with_mnemonic(_("Send Hello Hash in S_DP")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableHelloHash), curHelloEnabled); gtk_table_attach(GTK_TABLE(tableZrtp), enableHelloHash, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(enableHelloHash) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(enableHelloHash), TRUE); GtkWidget *enableSASConfirm = gtk_check_button_new_with_mnemonic(_("Ask User to Confirm SAS")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableSASConfirm), curSasConfirm); gtk_table_attach(GTK_TABLE(tableZrtp), enableSASConfirm, 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(enableSASConfirm) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(enableSASConfirm), TRUE); GtkWidget *enableZrtpNotSuppOther = gtk_check_button_new_with_mnemonic(_("_Warn if ZRTP not supported")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableZrtpNotSuppOther), curZrtpNotSuppOther); gtk_table_attach(GTK_TABLE(tableZrtp), enableZrtpNotSuppOther, 0, 1, 4, 5, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(enableZrtpNotSuppOther) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(enableZrtpNotSuppOther), TRUE); GtkWidget *displaySasOnce = gtk_check_button_new_with_mnemonic(_("Display SAS once for hold events")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displaySasOnce), curDisplaySasOnce); gtk_table_attach(GTK_TABLE(tableZrtp), displaySasOnce, 0, 1, 5, 6, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(displaySasOnce) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(displaySasOnce), TRUE); gtk_widget_show_all(tableZrtp); gtk_container_set_border_width(GTK_CONTAINER(tableZrtp), 10); if (gtk_dialog_run(GTK_DIALOG(securityDialog)) == GTK_RESPONSE_ACCEPT) { - g_hash_table_replace(properties, - g_strdup(ACCOUNT_ZRTP_DISPLAY_SAS), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableSASConfirm)) ? "true": "false")); + account_replace(account, ACCOUNT_ZRTP_DISPLAY_SAS, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableSASConfirm)) ? "true": "false"); - g_hash_table_replace(properties, - g_strdup(ACCOUNT_DISPLAY_SAS_ONCE), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displaySasOnce)) ? "true": "false")); + account_replace(account, ACCOUNT_DISPLAY_SAS_ONCE, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displaySasOnce)) ? "true": "false"); - g_hash_table_replace(properties, - g_strdup(ACCOUNT_ZRTP_HELLO_HASH), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableHelloHash)) ? "true": "false")); + account_replace(account, ACCOUNT_ZRTP_HELLO_HASH, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableHelloHash)) ? "true": "false"); - g_hash_table_replace(properties, - g_strdup(ACCOUNT_ZRTP_NOT_SUPP_WARNING), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableZrtpNotSuppOther)) ? "true": "false")); + account_replace(account, ACCOUNT_ZRTP_NOT_SUPP_WARNING, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableZrtpNotSuppOther)) ? "true": "false"); } gtk_widget_destroy(GTK_WIDGET(securityDialog)); } -void show_advanced_sdes_options(GHashTable * properties) +void show_advanced_sdes_options(account_t *account) { gboolean rtpFallback = FALSE; - if (properties != NULL) { - rtpFallback = !g_strcasecmp(g_hash_table_lookup(properties, ACCOUNT_SRTP_RTP_FALLBACK), "true"); - } + if (account != NULL) + rtpFallback = utf8_case_equal(account_lookup(account, ACCOUNT_SRTP_RTP_FALLBACK), "true"); GtkDialog *securityDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("SDES Options"), GTK_WINDOW(get_main_window()), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, - GTK_RESPONSE_ACCEPT, - NULL)); + GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, + GTK_RESPONSE_ACCEPT, NULL)); gtk_window_set_resizable(GTK_WINDOW(securityDialog), FALSE); gtk_container_set_border_width(GTK_CONTAINER(securityDialog), 0); - GtkWidget *sdesTable = gtk_table_new(1, 2 , FALSE/* homogeneous */); + GtkWidget *sdesTable = gtk_table_new(1, 2, FALSE /* homogeneous */); gtk_table_set_row_spacings(GTK_TABLE(sdesTable), 10); gtk_table_set_col_spacings(GTK_TABLE(sdesTable), 10); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(securityDialog)), sdesTable, FALSE, FALSE, 0); @@ -142,16 +135,15 @@ void show_advanced_sdes_options(GHashTable * properties) GtkWidget *enableRtpFallback = gtk_check_button_new_with_mnemonic(_("Fallback on RTP on SDES failure")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableRtpFallback), rtpFallback); gtk_table_attach(GTK_TABLE(sdesTable), enableRtpFallback, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(enableRtpFallback) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(enableRtpFallback), TRUE); gtk_widget_show_all(sdesTable); gtk_container_set_border_width(GTK_CONTAINER(sdesTable), 10); if (gtk_dialog_run(GTK_DIALOG(securityDialog)) == GTK_RESPONSE_ACCEPT) { - g_hash_table_replace(properties, - g_strdup(ACCOUNT_SRTP_RTP_FALLBACK), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableRtpFallback)) ? "true": "false")); + account_replace(account, ACCOUNT_SRTP_RTP_FALLBACK, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableRtpFallback)) ? "true": "false"); } gtk_widget_destroy(GTK_WIDGET(securityDialog)); diff --git a/gnome/src/config/zrtpadvanceddialog.h b/gnome/src/config/zrtpadvanceddialog.h index 0a98ddb96089001c66f0df3cdf15e3b20de00fb0..ddc09114beb8d4fbb2455139c981618bf4e324af 100644 --- a/gnome/src/config/zrtpadvanceddialog.h +++ b/gnome/src/config/zrtpadvanceddialog.h @@ -34,14 +34,13 @@ * @brief Display the advanced options window for zrtp */ -#include <glib.h> -#include <mainwindow.h> +#include "accountlist.h" /** * Display the advanced options window for zrtp */ -void show_advanced_zrtp_options (GHashTable * properties); +void show_advanced_zrtp_options (account_t *account); -void show_advanced_sdes_options (GHashTable * properties); +void show_advanced_sdes_options (account_t *account); #endif diff --git a/gnome/src/contacts/addrbookfactory.c b/gnome/src/contacts/addrbookfactory.c index 3db2562ffcbaa58fe557f69a28c800107b780d47..821adcf280dd81e29cc3786407a1a6a0fa6a41ee 100644 --- a/gnome/src/contacts/addrbookfactory.c +++ b/gnome/src/contacts/addrbookfactory.c @@ -39,7 +39,6 @@ AddrBookHandle *addrbook = NULL; - /** * Callback called after all book have been processed */ @@ -93,7 +92,7 @@ void abook_init() void *handle = dlopen(PLUGINS_DIR"/libevladdrbook.so", RTLD_LAZY); if (handle == NULL) { - ERROR("Addressbook: Error: Could not load addressbook"); + DEBUG("Did not load addressbook"); return; } @@ -102,7 +101,7 @@ void abook_init() #define LOAD(func) do { \ addrbook-> func = dlsym(handle, "addressbook_" #func); \ if (addrbook-> func == NULL) \ - ERROR("Addressbook: Couldn't load " # func); \ + ERROR("Couldn't load " # func); \ } while(0) diff --git a/gnome/src/contacts/calllist.c b/gnome/src/contacts/calllist.c index 4cc64dbf3875e006cacfe56a41f72ab283245150..fb54e10cf06648dec203cf0d0deb37b297532644 100644 --- a/gnome/src/contacts/calllist.c +++ b/gnome/src/contacts/calllist.c @@ -29,6 +29,7 @@ */ #include "calllist.h" +#include "str_utils.h" #include <string.h> #include "calltab.h" #include "calltree.h" @@ -36,15 +37,19 @@ #include "logger.h" #include "eel-gconf-extensions.h" -static -gint is_callID_callstruct(gconstpointer a, gconstpointer b) +// Must return 0 when a match is found +static gint +is_callID_callstruct(gconstpointer a, gconstpointer b) { - const QueueElement *c = a; + const callable_obj_t *c = a; - if (c == NULL || c->type != HIST_CALL) + // if it's null or not a call it's not the call we're looking for + if (c == NULL) { + ERROR("NULL element in list"); return 1; + } - return g_strcasecmp(c->elem.call->_callID, (const gchar *) b); + return g_strcmp0(c->_callID, (const gchar *) b); } // TODO : try to do this more generically @@ -85,17 +90,13 @@ void calllist_add_contact(gchar *contact_name, gchar *contact_phone, contact_typ } /* - * Function passed to calllist_clean to free every QueueElement. + * Function passed to calllist_clean to free every callable_obj_t. */ static void calllist_free_element(gpointer data, gpointer user_data UNUSED) { - QueueElement *element = data; - - g_assert(element->type == HIST_CALL); - free_callable_obj_t(element->elem.call); - - g_free(element); + callable_obj_t *call = data; + free_callable_obj_t(call); } void @@ -103,6 +104,7 @@ calllist_clean(calltab_t* tab) { g_queue_foreach(tab->callQueue, calllist_free_element, NULL); g_queue_free(tab->callQueue); + tab->callQueue = 0; } void @@ -115,19 +117,15 @@ calllist_reset(calltab_t* tab) void calllist_add_call(calltab_t* tab, callable_obj_t * c) { - QueueElement *element = g_new0(QueueElement, 1); - element->type = HIST_CALL; - element->elem.call = c; - g_queue_push_tail(tab->callQueue, (gpointer) element); + DEBUG("Adding call with callID %s to tab %s", c->_callID, tab->_name); + g_queue_push_tail(tab->callQueue, c); + DEBUG("Tab %s has %d calls", tab->_name, calllist_get_size(tab)); } void calllist_add_call_to_front(calltab_t* tab, callable_obj_t * c) { - QueueElement *element = g_new0(QueueElement, 1); - element->type = HIST_CALL; - element->elem.call = c; - g_queue_push_head(tab->callQueue, (gpointer) element); + g_queue_push_head(tab->callQueue, c); } void @@ -136,10 +134,9 @@ calllist_clean_history(void) guint size = calllist_get_size(history_tab); for (guint i = 0; i < size; i++) { - QueueElement* c = calllist_get_nth(history_tab, i); - - if (c->type == HIST_CALL) - calltree_remove_call(history_tab, c->elem.call); + callable_obj_t * c = calllist_get_nth(history_tab, i); + if (c) + calltree_remove_call(history_tab, c->_callID); } calllist_reset(history_tab); @@ -149,7 +146,7 @@ void calllist_remove_from_history(callable_obj_t* c) { calllist_remove_call(history_tab, c->_callID); - calltree_remove_call(history_tab, c); + calltree_remove_call(history_tab, c->_callID); } void @@ -160,23 +157,18 @@ calllist_remove_call(calltab_t* tab, const gchar * callID) if (c == NULL) return; - QueueElement *element = (QueueElement *) c->data; + callable_obj_t *call = c->data; - if (element->type != HIST_CALL) { - ERROR("CallList: Error: Element %s is not a call", callID); - return; - } - - g_queue_remove(tab->callQueue, element); + DEBUG("Removing call %s from tab %s", callID, tab->_name); + g_queue_remove(tab->callQueue, call); /* Don't save empty (i.e. started dialing, then deleted) calls */ - if (element->elem.call->_peer_number && strlen(element->elem.call->_peer_number) > 0) { - calllist_add_call(history_tab, element->elem.call); - calltree_add_history_entry(element->elem.call); + if (call->_peer_number && strlen(call->_peer_number) > 0) { + calllist_add_call(history_tab, call); + calltree_add_history_entry(call); } } - callable_obj_t * calllist_get_by_state(calltab_t* tab, call_state_t state) { @@ -190,7 +182,7 @@ calllist_get_size(const calltab_t* tab) return g_queue_get_length(tab->callQueue); } -QueueElement * +callable_obj_t* calllist_get_nth(calltab_t* tab, guint n) { return g_queue_peek_nth(tab->callQueue, n); @@ -202,16 +194,9 @@ calllist_get_call(calltab_t* tab, const gchar * callID) GList * c = g_queue_find_custom(tab->callQueue, callID, is_callID_callstruct); if (c == NULL) { - ERROR("CallList: Error: Could not find call %s", callID); - return NULL; - } - - QueueElement *element = c->data; - - if (element->type != HIST_CALL) { - ERROR("CallList: Error: Element %s is not a call", callID); + ERROR("Could not find call %s in tab %s", callID, tab->_name); return NULL; } - return element->elem.call; + return c->data; } diff --git a/gnome/src/contacts/calllist.h b/gnome/src/contacts/calllist.h index b69814b5e14d4549878e6747d6a72e8358fc8a0e..1cb3c5d268b0f484340c5860e0ae38dc33564187 100644 --- a/gnome/src/contacts/calllist.h +++ b/gnome/src/contacts/calllist.h @@ -39,18 +39,6 @@ * @brief A list to hold calls. */ -typedef enum { HIST_CALL } ElementType; - -typedef union { - callable_obj_t *call; - conference_obj_t *conf; -} callableElement; - -typedef struct { - ElementType type; - callableElement elem; -} QueueElement; - typedef struct { GtkTreeStore* store; GtkWidget* view; @@ -118,7 +106,7 @@ calllist_get_size(const calltab_t* tab); /** Return the call at the nth position in the list * @param n The position of the call you want * @return A call or NULL */ -QueueElement * +callable_obj_t* calllist_get_nth(calltab_t* tab, guint n); /** Return the call corresponding to the callID diff --git a/gnome/src/contacts/calltab.c b/gnome/src/contacts/calltab.c index fcf0d85009f6333cddaeef6884bf57bb991c2def..e3ef874209d2f466d76348a21ee94c3e339679e5 100644 --- a/gnome/src/contacts/calltab.c +++ b/gnome/src/contacts/calltab.c @@ -31,6 +31,7 @@ #include "calltab.h" #include <gtk/gtk.h> #include <stdlib.h> +#include "str_utils.h" #include "calltree.h" #include "contacts/searchbar.h" #include "logger.h" @@ -52,7 +53,7 @@ void calltab_select_call(calltab_t* tab, callable_obj_t * c) { g_assert(tab); - DEBUG("CallTab: Select call %s", c ? c->_callID : ""); + DEBUG("Select call %s", c ? c->_callID : ""); tab->selectedType = A_CALL; tab->selectedCall = c; @@ -64,7 +65,7 @@ void calltab_select_conf(calltab_t *tab, conference_obj_t * c) { g_assert(tab); - DEBUG("CallTab: Selected conf %s", c ? c->_confID : ""); + DEBUG("Selected conf %s", c ? c->_confID : ""); tab->selectedType = A_CONFERENCE; tab->selectedConf = c; @@ -97,9 +98,9 @@ calltab_create_searchbar(calltab_t* tab) { g_assert(tab); - if (g_strcasecmp(tab->_name, HISTORY) == 0) + if (g_strcmp0(tab->_name, HISTORY) == 0) tab->searchbar = history_searchbar_new(); - else if (g_strcasecmp(tab->_name, CONTACTS) == 0) + else if (g_strcmp0(tab->_name, CONTACTS) == 0) tab->searchbar = contacts_searchbar_new(); else ERROR("Current calls tab does not need a searchbar\n"); diff --git a/gnome/src/contacts/calltree.c b/gnome/src/contacts/calltree.c index ce92c7b9de6b76ee8a7c457654774f9e688b3017..3fc9df6ae9236cf3f178807b531c82938d71c6df 100644 --- a/gnome/src/contacts/calltree.c +++ b/gnome/src/contacts/calltree.c @@ -32,8 +32,12 @@ #include "calllist.h" #include "calltree.h" +#include "str_utils.h" +#include <string.h> #include <stdlib.h> +#include <gtk/gtk.h> +#include "gtk2_wrappers.h" #include "eel-gconf-extensions.h" #include "unused.h" #include "dbus.h" @@ -48,47 +52,33 @@ #include "imwindow.h" #include "searchbar.h" +#if !GLIB_CHECK_VERSION(2, 30, 0) +#define G_VALUE_INIT { 0, { { 0 } } } +#endif + +typedef struct { + gchar *source_ID; + gchar *dest_ID; +} PopupData; + +static PopupData *popup_data = NULL; + // Messages used in menu item static const gchar * const SFL_CREATE_CONFERENCE = "Create conference"; static const gchar * const SFL_TRANSFER_CALL = "Transfer call to"; -static GtkWidget *calltree_sw = NULL; -static GtkCellRenderer *calltree_rend = NULL; -static GtkTreeViewColumn *calltree_col = NULL; -static GtkTreeSelection *calltree_sel = NULL; - static GtkWidget *calltree_popupmenu = NULL; static GtkWidget *calltree_menu_items = NULL; -static CallType calltree_dragged_type = A_INVALID; -static CallType calltree_selected_type = A_INVALID; - -static const gchar *calltree_dragged_call_id = NULL; -static const gchar *calltree_selected_call_id = NULL; -static const gchar *calltree_dragged_path = NULL; -static const gchar *calltree_selected_path = NULL; - -static gint calltree_dragged_path_depth = -1; -static gint calltree_selected_path_depth = -1; - -static callable_obj_t *calltree_dragged_call = NULL; -static callable_obj_t *calltree_selected_call = NULL; - -static conference_obj_t *calltree_dragged_conf = NULL; -static conference_obj_t *calltree_selected_conf = NULL; - -static void drag_end_cb(GtkWidget *, GdkDragContext *, gpointer); static void drag_data_received_cb(GtkWidget *, GdkDragContext *, gint, gint, GtkSelectionData *, guint, guint, gpointer); -static void drag_history_received_cb(GtkWidget *, GdkDragContext *, gint, gint, GtkSelectionData *, guint, guint, gpointer); -static void menuitem_response(gchar *); - -enum { - COLUMN_ACCOUNT_PIXBUF = 0, - COLUMN_ACCOUNT_DESC, - COLUMN_ACCOUNT_SECURITY_PIXBUF, - COLUMN_ACCOUNT_PTR +static void menuitem_response(gchar * string); + +static GtkTargetEntry target_list[] = { + { "MY_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 } }; +static const guint n_targets = G_N_ELEMENTS(target_list); + /** * Show popup menu */ @@ -100,90 +90,64 @@ popup_menu(GtkWidget *widget, return TRUE; } +/* Returns TRUE if row contains a conference object pointer */ +gboolean +is_conference(GtkTreeModel *model, GtkTreeIter *iter) +{ + gboolean result = FALSE; + gtk_tree_model_get(model, iter, COLUMN_IS_CONFERENCE, &result, -1); + return result; +} + /* Call back when the user click on a call in the list */ static void call_selected_cb(GtkTreeSelection *sel, void* data UNUSED) { - DEBUG("CallTree: Selection callback"); - GtkTreeModel *model = GTK_TREE_MODEL(active_calltree_tab->store); + GtkTreeModel *model = gtk_tree_view_get_model(gtk_tree_selection_get_tree_view(sel)); GtkTreeIter iter; - if (!gtk_tree_selection_get_selected(sel, &model, &iter)) return; if (active_calltree_tab == history_tab) - DEBUG("CallTree: Current call tree is history"); + DEBUG("Current call tree is history"); else if (active_calltree_tab == current_calls_tab) - DEBUG("CallTree: Current call tree is current calls"); + DEBUG("Current call tree is current calls"); - // store info for dragndrop - GtkTreePath *path = gtk_tree_model_get_path(model, &iter); - gchar *string_path = gtk_tree_path_to_string(path); - calltree_selected_path_depth = gtk_tree_path_get_depth(path); + /* Get ID of selected object, may be a call or a conference */ + gchar *id; + gtk_tree_model_get(model, &iter, COLUMN_ID, &id, -1); - if (gtk_tree_model_iter_has_child(model, &iter)) { - DEBUG("CallTree: Selected a conference"); - calltree_selected_type = A_CONFERENCE; + if (is_conference(model, &iter)) { + DEBUG("Selected a conference"); - GValue val; - val.g_type = 0; - gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_PTR, &val); + conference_obj_t *calltree_selected_conf = conferencelist_get(active_calltree_tab, id); + g_free(id); - calltree_selected_conf = (conference_obj_t*) g_value_get_pointer(&val); - g_value_unset(&val); - - if (calltree_selected_conf) { + if (calltree_selected_conf) calltab_select_conf(active_calltree_tab, calltree_selected_conf); - calltree_selected_call_id = calltree_selected_conf->_confID; - calltree_selected_path = string_path; - calltree_selected_call = NULL; - - if (calltree_selected_conf->_im_widget) - im_window_show_tab(calltree_selected_conf->_im_widget); - - DEBUG("CallTree: selected_path %s, selected_conf_id %s, selected_path_depth %d", - calltree_selected_path, calltree_selected_call_id, calltree_selected_path_depth); - } } else { - DEBUG("CallTree: Selected a call"); - calltree_selected_type = A_CALL; + DEBUG("Selected a call"); - GValue val; - val.g_type = 0; - gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_PTR, &val); + callable_obj_t *selected_call = calllist_get_call(active_calltree_tab, id); + g_free(id); - calltree_selected_call = g_value_get_pointer(&val); - g_value_unset(&val); - - if (calltree_selected_call) { - calltab_select_call(active_calltree_tab, calltree_selected_call); - calltree_selected_call_id = calltree_selected_call->_callID; - calltree_selected_path = string_path; - calltree_selected_conf = NULL; - - if (calltree_selected_call->_im_widget) - im_window_show_tab(calltree_selected_call->_im_widget); - - DEBUG("CallTree: selected_path %s, selected_call_id %s, selected_path_depth %d", - calltree_selected_path, calltree_selected_call_id, calltree_selected_path_depth); - } + if (selected_call) + calltab_select_call(active_calltree_tab, selected_call); } update_actions(); } /* A row is activated when it is double clicked */ -void -row_activated(GtkTreeView *tree_view UNUSED, - GtkTreePath *path UNUSED, - GtkTreeViewColumn *column UNUSED, - void * data UNUSED) +static void +row_activated_cb(GtkTreeView *tree_view UNUSED, + GtkTreePath *path UNUSED, + GtkTreeViewColumn *column UNUSED, + void * data UNUSED) { - DEBUG("CallTree: Double click action"); - if (calltab_get_selected_type(active_calltree_tab) == A_CALL) { - DEBUG("CallTree: Selected a call"); + DEBUG("Selected a call"); callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab); if (selectedCall) { @@ -220,7 +184,7 @@ row_activated(GtkTreeView *tree_view UNUSED, } } } else if (calltab_get_selected_type(active_calltree_tab) == A_CONFERENCE) { - DEBUG("CallTree: Selected a conference"); + DEBUG("Selected a conference"); if (active_calltree_tab == current_calls_tab) { conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab); @@ -243,7 +207,7 @@ row_activated(GtkTreeView *tree_view UNUSED, } } } else - WARN("CallTree: Selected a conference in history, should not be possible"); + WARN("Selected a conference in history, should not be possible"); } } @@ -253,18 +217,15 @@ row_single_click(GtkTreeView *tree_view UNUSED, void * data UNUSED) { gchar * displaySasOnce = NULL; - DEBUG("CallTree: Single click action"); - callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab); conference_obj_t *selectedConf = calltab_get_selected_conf(active_calltree_tab); if (active_calltree_tab == current_calls_tab) - DEBUG("CallTree: Active calltree is current_calls"); + DEBUG("Active calltree is current_calls"); else if (active_calltree_tab == history_tab) - DEBUG("CallTree: Active calltree is history"); + DEBUG("Active calltree is history"); if (calltab_get_selected_type(active_calltree_tab) == A_CALL) { - DEBUG("CallTree: Selected a call"); if (selectedCall) { account_t *account_details = account_list_get_by_id(selectedCall->_accountID); @@ -290,7 +251,7 @@ row_single_click(GtkTreeView *tree_view UNUSED, void * data UNUSED) case SRTP_STATE_ZRTP_SAS_UNCONFIRMED: selectedCall->_srtp_state = SRTP_STATE_ZRTP_SAS_CONFIRMED; - if (g_strcasecmp(displaySasOnce, "true") == 0) + if (utf8_case_equal(displaySasOnce, "true")) selectedCall->_zrtp_confirmed = TRUE; dbus_confirm_sas(selectedCall); @@ -308,11 +269,10 @@ row_single_click(GtkTreeView *tree_view UNUSED, void * data UNUSED) } } } else if (calltab_get_selected_type(active_calltree_tab) == A_CONFERENCE) { - DEBUG("CallTree: Selected a conference"); if (selectedConf) - DEBUG("CallTree: There is actually a selected conf"); + DEBUG("There is actually a selected conf"); } else - WARN("CallTree: Warning: Unknown selection type"); + WARN("Unknown selection type"); } static gboolean @@ -339,29 +299,34 @@ static gchar *clean_display_number(gchar *name) name += (sizeof(SIP_PREFIX) - 1); else if (g_str_has_prefix(name, SIPS_PREFIX)) name += (sizeof(SIPS_PREFIX) - 1); + + gchar * pos = g_strrstr(name, ">"); + if (pos) + *pos = '\0'; return name; } static gchar * -calltree_display_call_info(callable_obj_t * c, CallDisplayType display_type, const gchar *const audio_codec) +calltree_display_call_info(callable_obj_t * call, CallDisplayType display_type, const gchar *const audio_codec) { - gchar display_number[strlen(c->_peer_number) + 1]; - strcpy(display_number, c->_peer_number); + gchar display_number[strlen(call->_peer_number) + 1]; + strcpy(display_number, call->_peer_number); - if (c->_type != CALL || !call_was_outgoing(c)) { + if (call->_type != CALL || !call_was_outgoing(call)) { // Get the hostname for this call (NULL if not existent) - gchar * hostname = g_strrstr(c->_peer_number, "@"); + gchar * hostname = g_strrstr(call->_peer_number, "@"); // Test if we are dialing a new number - if (*c->_peer_number && hostname) - display_number[hostname - c->_peer_number] = '\0'; + if (*call->_peer_number && hostname) + display_number[hostname - call->_peer_number] = '\0'; } // Different display depending on type - gchar *name, *details = NULL; + gchar *name = NULL; + gchar *details = NULL; - if (*c->_display_name) { - name = c->_display_name; + if (*call->_display_name) { + name = call->_display_name; details = display_number; } else { name = display_number; @@ -374,24 +339,24 @@ calltree_display_call_info(callable_obj_t * c, CallDisplayType display_type, con switch (display_type) { case DISPLAY_TYPE_CALL: - if (c->_state_code) - suffix = g_markup_printf_escaped("\n<i>%s (%d)</i>", c->_state_code_description, c->_state_code); + if (call->_state_code) + suffix = g_markup_printf_escaped("\n<i>%s (%d)</i>", call->_state_code_description, call->_state_code); break; case DISPLAY_TYPE_STATE_CODE : - if (c->_state_code) + if (call->_state_code) suffix = g_markup_printf_escaped("\n<i>%s (%d)</i> <i>%s</i>", - c->_state_code_description, c->_state_code, + call->_state_code_description, call->_state_code, audio_codec); else suffix = g_markup_printf_escaped("\n<i>%s</i>", audio_codec); break; case DISPLAY_TYPE_CALL_TRANSFER: - suffix = g_markup_printf_escaped("\n<i>Transfer to:%s</i> ", c->_trsft_to); + suffix = g_markup_printf_escaped("\n<i>Transfer to:%s</i> ", call->_trsft_to); break; case DISPLAY_TYPE_SAS: - suffix = g_markup_printf_escaped("\n<i>Confirm SAS <b>%s</b> ?</i>", c->_sas); + suffix = g_markup_printf_escaped("\n<i>Confirm SAS <b>%s</b> ?</i>", call->_sas); break; case DISPLAY_TYPE_HISTORY : default: @@ -414,22 +379,24 @@ calltree_create(calltab_t* tab, int searchbar_type) gtk_container_set_border_width(GTK_CONTAINER(tab->tree), 0); - calltree_sw = gtk_scrolled_window_new(NULL, NULL); + GtkWidget *calltree_sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(calltree_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(calltree_sw), GTK_SHADOW_IN); - tab->store = gtk_tree_store_new(4, + tab->store = gtk_tree_store_new(COLUMNS_IN_TREE_STORE, GDK_TYPE_PIXBUF, /* Icon */ G_TYPE_STRING, /* Description */ GDK_TYPE_PIXBUF, /* Security Icon */ - G_TYPE_POINTER /* Pointer to the Object */ + G_TYPE_STRING, /* ID of the object */ + G_TYPE_BOOLEAN /* True if this is conference */ ); tab->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(tab->store)); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(tab->view), FALSE); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tab->view), FALSE); g_signal_connect(G_OBJECT(tab->view), "row-activated", - G_CALLBACK(row_activated), + G_CALLBACK(row_activated_cb), NULL); gtk_widget_set_can_focus(calltree_sw, TRUE); @@ -447,13 +414,10 @@ calltree_create(calltab_t* tab, int searchbar_type) G_CALLBACK(button_pressed), NULL); - if (tab != history_tab && tab != contacts_tab) { - // Make calltree reordable for drag n drop - gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tab->view), TRUE); - - // source widget drag n drop signals - g_signal_connect(G_OBJECT(tab->view), "drag_end", G_CALLBACK(drag_end_cb), NULL); + if (g_strcmp0(tab->_name, CURRENT_CALLS) == 0) { + gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(tab->view), GDK_BUTTON1_MASK, target_list, n_targets, GDK_ACTION_DEFAULT | GDK_ACTION_MOVE); + gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(tab->view), target_list, n_targets, GDK_ACTION_DEFAULT); // destination widget drag n drop signals g_signal_connect(G_OBJECT(tab->view), "drag_data_received", G_CALLBACK(drag_data_received_cb), NULL); @@ -461,27 +425,22 @@ calltree_create(calltab_t* tab, int searchbar_type) calltree_menu_items = gtk_menu_item_new_with_label(SFL_TRANSFER_CALL); g_signal_connect_swapped(calltree_menu_items, "activate", - G_CALLBACK(menuitem_response), (gpointer) g_strdup(SFL_TRANSFER_CALL)); + G_CALLBACK(menuitem_response), g_strdup(SFL_TRANSFER_CALL)); gtk_menu_shell_append(GTK_MENU_SHELL(calltree_popupmenu), calltree_menu_items); gtk_widget_show(calltree_menu_items); calltree_menu_items = gtk_menu_item_new_with_label(SFL_CREATE_CONFERENCE); g_signal_connect_swapped(calltree_menu_items, "activate", - G_CALLBACK(menuitem_response), (gpointer) g_strdup(SFL_CREATE_CONFERENCE)); + G_CALLBACK(menuitem_response), g_strdup(SFL_CREATE_CONFERENCE)); gtk_menu_shell_append(GTK_MENU_SHELL(calltree_popupmenu), calltree_menu_items); gtk_widget_show(calltree_menu_items); - } else if (tab == history_tab) { - gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tab->view), TRUE); - g_signal_connect(G_OBJECT(tab->view), "drag_data_received", G_CALLBACK(drag_history_received_cb), NULL); } gtk_widget_grab_focus(GTK_WIDGET(tab->view)); - calltree_rend = gtk_cell_renderer_pixbuf_new(); - calltree_col = gtk_tree_view_column_new_with_attributes("Icon", calltree_rend, "pixbuf", COLUMN_ACCOUNT_PIXBUF, - NULL); + GtkCellRenderer *calltree_rend = gtk_cell_renderer_pixbuf_new(); + GtkTreeViewColumn *calltree_col = gtk_tree_view_column_new_with_attributes("Icon", calltree_rend, "pixbuf", COLUMN_ACCOUNT_PIXBUF, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tab->view), calltree_col); - calltree_rend = gtk_cell_renderer_text_new(); calltree_col = gtk_tree_view_column_new_with_attributes("Description", calltree_rend, "markup", COLUMN_ACCOUNT_DESC, @@ -510,7 +469,7 @@ calltree_create(calltab_t* tab, int searchbar_type) g_object_unref(G_OBJECT(tab->store)); gtk_container_add(GTK_CONTAINER(calltree_sw), tab->view); - calltree_sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tab->view)); + GtkTreeSelection *calltree_sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tab->view)); g_signal_connect(G_OBJECT(calltree_sel), "changed", G_CALLBACK(call_selected_cb), NULL); @@ -528,52 +487,37 @@ calltree_create(calltab_t* tab, int searchbar_type) gtk_widget_show(tab->tree); } +static gboolean +remove_element_if_match(GtkTreeModel *model, GtkTreePath *path UNUSED, GtkTreeIter *iter, gpointer data) +{ + const gchar *target_id = (const gchar *) data; + gchar *id; + gtk_tree_model_get(model, iter, COLUMN_ID, &id, -1); + gboolean result = FALSE; + if (g_strcmp0(id, target_id) == 0) { + gtk_tree_store_remove(GTK_TREE_STORE(model), iter); + result = TRUE; // stop iterating, we found it + } + g_free(id); -static void -calltree_remove_call_recursive(calltab_t* tab, callable_obj_t * callable, GtkTreeIter *parent) + return result; +} + +void +calltree_remove_call(calltab_t* tab, const gchar *target_id) { GtkTreeStore *store = tab->store; GtkTreeModel *model = GTK_TREE_MODEL(store); + gtk_tree_model_foreach(model, remove_element_if_match, (gpointer) target_id); - if (!callable) - ERROR("CallTree: Error: Not a valid call"); - - DEBUG("CallTree: Remove call %s", callable->_callID); - - int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), parent); - - for (int i = 0; i < nbChild; i++) { - GtkTreeIter child; - - if (gtk_tree_model_iter_nth_child(model, &child, parent, i)) { - if (gtk_tree_model_iter_has_child(model, &child)) - calltree_remove_call_recursive(tab, callable, &child); - - GValue val = { .g_type = 0 }; - gtk_tree_model_get_value(model, &child, COLUMN_ACCOUNT_PTR, &val); - - callable_obj_t * iterCall = g_value_get_pointer(&val); - g_value_unset(&val); - - if (iterCall == callable) - gtk_tree_store_remove(store, &child); - } - } - - if (calltab_get_selected_call(tab) == callable) + /* invalidate selected call if it was our target */ + callable_obj_t *sel = calltab_get_selected_call(tab); + if (sel && g_strcmp0(sel->_callID, target_id) == 0) calltab_select_call(tab, NULL); - update_actions(); - statusbar_update_clock(""); } -void -calltree_remove_call(calltab_t* tab, callable_obj_t * c) -{ - calltree_remove_call_recursive(tab, c, NULL); -} - GdkPixbuf *history_state_to_pixbuf(const gchar *history_state) { gchar *svg_filename = g_strconcat(ICONS_DIR, "/", history_state, ".svg", NULL); @@ -582,176 +526,173 @@ GdkPixbuf *history_state_to_pixbuf(const gchar *history_state) return pixbuf; } -static void -calltree_update_call_recursive(calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent) +typedef struct { + calltab_t *tab; + callable_obj_t *call; +} CallUpdateCtx; + +typedef struct { + calltab_t *tab; + const conference_obj_t *conf; +} ConferenceRemoveCtx; + +static gboolean +update_call(GtkTreeModel *model, GtkTreePath *path UNUSED, GtkTreeIter *iter, gpointer data) { GdkPixbuf *pixbuf = NULL; GdkPixbuf *pixbuf_security = NULL; - GtkTreeIter iter; - GValue val; + CallUpdateCtx *ctx = (CallUpdateCtx*) data; + calltab_t *tab = ctx->tab; + callable_obj_t *call = ctx->call; GtkTreeStore* store = tab->store; gchar* srtp_enabled = NULL; gboolean display_sas = TRUE; - account_t* account_details=NULL; - - int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), parent); - - if (c) { - account_details = account_list_get_by_id(c->_accountID); - - if (account_details != NULL) { - srtp_enabled = g_hash_table_lookup(account_details->properties, ACCOUNT_SRTP_ENABLED); + account_t* account = NULL; - if (g_strcasecmp(g_hash_table_lookup(account_details->properties, ACCOUNT_ZRTP_DISPLAY_SAS),"false") == 0) - display_sas = FALSE; - } else { - GHashTable * properties = sflphone_get_ip2ip_properties(); - - if (properties != NULL) { - srtp_enabled = g_hash_table_lookup(properties, ACCOUNT_SRTP_ENABLED); + account = account_list_get_by_id(call->_accountID); - if (g_strcasecmp(g_hash_table_lookup(properties, ACCOUNT_ZRTP_DISPLAY_SAS),"false") == 0) - display_sas = FALSE; - } + if (account != NULL) { + srtp_enabled = account_lookup(account, ACCOUNT_SRTP_ENABLED); + display_sas = utf8_case_equal(account_lookup(account, ACCOUNT_ZRTP_DISPLAY_SAS), "true"); + } else { + GHashTable * properties = sflphone_get_ip2ip_properties(); + if (properties != NULL) { + srtp_enabled = g_hash_table_lookup(properties, ACCOUNT_SRTP_ENABLED); + display_sas = utf8_case_equal(g_hash_table_lookup(properties, ACCOUNT_ZRTP_DISPLAY_SAS), "true"); } } - for (gint i = 0; i < nbChild; i++) { - - if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, parent, i)) { + gchar *id; + gtk_tree_model_get(model, iter, COLUMN_ID, &id, -1); - if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), &iter)) - calltree_update_call_recursive(tab, c, &iter); + callable_obj_t * iterCall = calllist_get_call(tab, id); + g_free(id); - val.g_type = 0; - gtk_tree_model_get_value(GTK_TREE_MODEL(store), &iter, COLUMN_ACCOUNT_PTR, &val); - - callable_obj_t * iterCall = (callable_obj_t*) g_value_get_pointer(&val); - g_value_unset(&val); - - if (iterCall != c) - continue; + if (iterCall != call) + return FALSE; - /* Update text */ - gchar * description = NULL; - gchar * audio_codec = call_get_audio_codec(c); + /* Update text */ + gchar * description = NULL; + gchar * audio_codec = call_get_audio_codec(call); - if (c->_state == CALL_STATE_TRANSFER) - description = calltree_display_call_info(c, DISPLAY_TYPE_CALL_TRANSFER, ""); - else - if (c->_sas && display_sas && c->_srtp_state == SRTP_STATE_ZRTP_SAS_UNCONFIRMED && !c->_zrtp_confirmed) - description = calltree_display_call_info(c, DISPLAY_TYPE_SAS, ""); - else - description = calltree_display_call_info(c, DISPLAY_TYPE_STATE_CODE, audio_codec); - - g_free(audio_codec); + if (call->_state == CALL_STATE_TRANSFER) + description = calltree_display_call_info(call, DISPLAY_TYPE_CALL_TRANSFER, ""); + else + if (call->_sas && display_sas && call->_srtp_state == SRTP_STATE_ZRTP_SAS_UNCONFIRMED && !call->_zrtp_confirmed) + description = calltree_display_call_info(call, DISPLAY_TYPE_SAS, ""); + else + description = calltree_display_call_info(call, DISPLAY_TYPE_STATE_CODE, audio_codec); - /* Update icons */ - if (tab == current_calls_tab) { - DEBUG("Receiving in state %d", c->_state); + g_free(audio_codec); - switch (c->_state) { - case CALL_STATE_HOLD: - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/hold.svg", NULL); - break; - case CALL_STATE_INCOMING: - case CALL_STATE_RINGING: - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL); - break; - case CALL_STATE_CURRENT: - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL); - break; - case CALL_STATE_DIALING: - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL); - break; - case CALL_STATE_FAILURE: - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/fail.svg", NULL); - break; - case CALL_STATE_BUSY: - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/busy.svg", NULL); - break; - case CALL_STATE_TRANSFER: - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/transfer.svg", NULL); - break; - case CALL_STATE_RECORD: - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/icon_rec.svg", NULL); - break; - default: - WARN("Update calltree - Should not happen!"); - } + /* Update icons */ + if (tab == current_calls_tab) { + DEBUG("Receiving in state %d", call->_state); - switch (c->_srtp_state) { - case SRTP_STATE_SDES_SUCCESS: - pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL); - break; - case SRTP_STATE_ZRTP_SAS_UNCONFIRMED: - pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_unconfirmed.svg", NULL); - if (c->_sas != NULL) - DEBUG("SAS is ready with value %s", c->_sas); - break; - case SRTP_STATE_ZRTP_SAS_CONFIRMED: - pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL); - break; - case SRTP_STATE_ZRTP_SAS_SIGNED: - pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_certified.svg", NULL); - break; - case SRTP_STATE_UNLOCKED: - if (g_strcasecmp(srtp_enabled,"true") == 0) - pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); - break; - default: - WARN("Update calltree srtp state #%d- Should not happen!", c->_srtp_state); - if (g_strcasecmp(srtp_enabled, "true") == 0) - pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); - } + switch (call->_state) { + case CALL_STATE_HOLD: + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/hold.svg", NULL); + break; + case CALL_STATE_INCOMING: + case CALL_STATE_RINGING: + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL); + break; + case CALL_STATE_CURRENT: + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL); + break; + case CALL_STATE_DIALING: + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL); + break; + case CALL_STATE_FAILURE: + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/fail.svg", NULL); + break; + case CALL_STATE_BUSY: + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/busy.svg", NULL); + break; + case CALL_STATE_TRANSFER: + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/transfer.svg", NULL); + break; + case CALL_STATE_RECORD: + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/icon_rec.svg", NULL); + break; + default: + WARN("Update calltree - Should not happen!"); + } - } else if (tab == history_tab) { - // parent is NULL this is not a conference participant - if (parent == NULL) - pixbuf = history_state_to_pixbuf(c->_history_state); - else // parent is not NULL this is a conference participant - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL); - - g_free(description); - description = calltree_display_call_info(c, DISPLAY_TYPE_HISTORY, ""); - gchar * date = get_formatted_start_timestamp(c->_time_start); - gchar *duration = get_call_duration(c); - gchar *full_duration = g_strconcat(date , duration , NULL); - g_free(date); - g_free(duration); - - gchar *old_description = description; - description = g_strconcat(old_description, full_duration, NULL); - g_free(full_duration); - g_free(old_description); - } + switch (call->_srtp_state) { + case SRTP_STATE_SDES_SUCCESS: + pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL); + break; + case SRTP_STATE_ZRTP_SAS_UNCONFIRMED: + pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_unconfirmed.svg", NULL); + if (call->_sas != NULL) + DEBUG("SAS is ready with value %s", call->_sas); + break; + case SRTP_STATE_ZRTP_SAS_CONFIRMED: + pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL); + break; + case SRTP_STATE_ZRTP_SAS_SIGNED: + pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_certified.svg", NULL); + break; + case SRTP_STATE_UNLOCKED: + if (utf8_case_equal(srtp_enabled, "true")) + pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); + break; + default: + WARN("Update calltree srtp state #%d- Should not happen!", call->_srtp_state); + if (utf8_case_equal(srtp_enabled, "true")) + pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); + } - gtk_tree_store_set(store, &iter, - COLUMN_ACCOUNT_PIXBUF, pixbuf, - COLUMN_ACCOUNT_DESC, description, - COLUMN_ACCOUNT_SECURITY_PIXBUF, pixbuf_security, - COLUMN_ACCOUNT_PTR, c, - -1); + } else if (tab == history_tab) { + pixbuf = history_state_to_pixbuf(call->_history_state); + + g_free(description); + description = calltree_display_call_info(call, DISPLAY_TYPE_HISTORY, ""); + gchar *date = get_formatted_start_timestamp(call->_time_start); + gchar *duration = get_call_duration(call); + gchar *full_duration = g_strconcat(date , duration , NULL); + g_free(date); + g_free(duration); + + gchar *old_description = description; + description = g_strconcat(old_description, full_duration, NULL); + g_free(full_duration); + g_free(old_description); + } - g_free(description); + gtk_tree_store_set(store, iter, + COLUMN_ACCOUNT_PIXBUF, pixbuf, + COLUMN_ACCOUNT_DESC, description, + COLUMN_ACCOUNT_SECURITY_PIXBUF, pixbuf_security, + COLUMN_ID, call->_callID, + COLUMN_IS_CONFERENCE, FALSE, + -1); - if (pixbuf != NULL) - g_object_unref(G_OBJECT(pixbuf)); - if (pixbuf_security != NULL) - g_object_unref(G_OBJECT(pixbuf_security)); - } - } + g_free(description); - update_actions(); + if (pixbuf != NULL) + g_object_unref(G_OBJECT(pixbuf)); + if (pixbuf_security != NULL) + g_object_unref(G_OBJECT(pixbuf_security)); + return TRUE; } -void calltree_update_call(calltab_t* tab, callable_obj_t * c) +void calltree_update_call(calltab_t* tab, callable_obj_t * call) { - calltree_update_call_recursive(tab, c, NULL); + if (!call) { + ERROR("Call is NULL, ignoring"); + return; + } + CallUpdateCtx ctx = {tab, call}; + GtkTreeStore *store = tab->store; + GtkTreeModel *model = GTK_TREE_MODEL(store); + gtk_tree_model_foreach(model, update_call, (gpointer) &ctx); + update_actions(); } -void calltree_add_call(calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent) +void calltree_add_call(calltab_t* tab, callable_obj_t * call, GtkTreeIter *parent) { g_assert(tab != history_tab); @@ -765,12 +706,12 @@ void calltree_add_call(calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent) // New call in the list - gchar *description = calltree_display_call_info(c, DISPLAY_TYPE_CALL, ""); + gchar *description = calltree_display_call_info(call, DISPLAY_TYPE_CALL, ""); gtk_tree_store_prepend(tab->store, &iter, parent); - if (c) { - account_details = account_list_get_by_id(c->_accountID); + if (call) { + account_details = account_list_get_by_id(call->_accountID); if (account_details) { srtp_enabled = g_hash_table_lookup(account_details->properties, ACCOUNT_SRTP_ENABLED); @@ -781,7 +722,7 @@ void calltree_add_call(calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent) DEBUG("Added call key exchange is %s", key_exchange); if (tab == current_calls_tab) { - switch (c->_state) { + switch (call->_state) { case CALL_STATE_INCOMING: pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL); break; @@ -810,13 +751,13 @@ void calltree_add_call(calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent) WARN("Update calltree add - Should not happen!"); } - if (srtp_enabled && g_strcasecmp(srtp_enabled, "true") == 0) + if (srtp_enabled && utf8_case_equal(srtp_enabled, "true")) pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/secure_off.svg", NULL); } else if (tab == contacts_tab) - pixbuf = c->_contact_thumbnail; + pixbuf = call->_contact_thumbnail; else - WARN("CallTree: This widget doesn't exist - This is a bug in the application."); + WARN("This widget doesn't exist - This is a bug in the application."); //Resize it if (pixbuf && (gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)) { @@ -835,7 +776,8 @@ void calltree_add_call(calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent) COLUMN_ACCOUNT_PIXBUF, pixbuf, COLUMN_ACCOUNT_DESC, description, COLUMN_ACCOUNT_SECURITY_PIXBUF, pixbuf_security, - COLUMN_ACCOUNT_PTR, c, + COLUMN_ID, call->_callID, + COLUMN_IS_CONFERENCE, FALSE, -1); g_free(description); @@ -851,21 +793,21 @@ void calltree_add_call(calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent) gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(tab->view)), &iter); } -void calltree_add_history_entry(callable_obj_t *c) +void calltree_add_history_entry(callable_obj_t *call) { if (!eel_gconf_get_integer(HISTORY_ENABLED)) return; // New call in the list - gchar * description = calltree_display_call_info(c, DISPLAY_TYPE_HISTORY, ""); + gchar * description = calltree_display_call_info(call, DISPLAY_TYPE_HISTORY, ""); GtkTreeIter iter; gtk_tree_store_prepend(history_tab->store, &iter, NULL); - GdkPixbuf *pixbuf = history_state_to_pixbuf(c->_history_state); + GdkPixbuf *pixbuf = history_state_to_pixbuf(call->_history_state); - gchar *date = get_formatted_start_timestamp(c->_time_start); - gchar *duration = get_call_duration(c); + gchar *date = get_formatted_start_timestamp(call->_time_start); + gchar *duration = get_call_duration(call); gchar * full_duration = g_strconcat(date, duration, NULL); g_free(date); g_free(duration); @@ -884,7 +826,8 @@ void calltree_add_history_entry(callable_obj_t *c) COLUMN_ACCOUNT_PIXBUF, pixbuf, COLUMN_ACCOUNT_DESC, full_description, COLUMN_ACCOUNT_SECURITY_PIXBUF, NULL, - COLUMN_ACCOUNT_PTR, c, + COLUMN_ID, call->_callID, + COLUMN_IS_CONFERENCE, FALSE, -1); g_free(full_description); @@ -903,11 +846,14 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) account_t *account_details = NULL; if (!conf) { - ERROR("Calltree: Error: Conference is null"); + ERROR("Conference is null"); + return; + } else if (!conf->_confID) { + ERROR("Conference ID is null"); return; } - DEBUG("Calltree: Add conference %s", conf->_confID); + DEBUG("Add conference %s", conf->_confID); GtkTreeIter iter; gtk_tree_store_append(current_calls_tab->store, &iter, NULL); @@ -954,33 +900,33 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) conf->_conference_secured = TRUE; if (conf->participant_list) { - DEBUG("Calltree: Determine if at least one participant uses SRTP"); + DEBUG("Determine if at least one participant uses SRTP"); for (GSList *part = conf->participant_list; part; part = g_slist_next(part)) { - const gchar * const call_id = (gchar *) part->data; + const gchar * const call_id = (const gchar *) part->data; callable_obj_t *call = calllist_get_call(current_calls_tab, call_id); if (call == NULL) - ERROR("Calltree: Error: Could not find call %s in call list", call_id); + ERROR("Could not find call %s in call list", call_id); else { account_details = account_list_get_by_id(call->_accountID); gchar *srtp_enabled = ""; if (!account_details) - ERROR("Calltree: Error: Could not find account %s in account list", call->_accountID); + ERROR("Could not find account %s in account list", call->_accountID); else srtp_enabled = g_hash_table_lookup(account_details->properties, ACCOUNT_SRTP_ENABLED); - if (g_strcasecmp(srtp_enabled, "true") == 0) { - DEBUG("Calltree: SRTP enabled for participant %s", call_id); + if (utf8_case_equal(srtp_enabled, "true")) { + DEBUG("SRTP enabled for participant %s", call_id); conf->_conf_srtp_enabled = TRUE; break; } else - DEBUG("Calltree: SRTP is not enabled for participant %s", call_id); + DEBUG("SRTP is not enabled for participant %s", call_id); } } - DEBUG("Calltree: Determine if all conference participants are secured"); + DEBUG("Determine if all conference participants are secured"); if (conf->_conf_srtp_enabled) { for (GSList *part = conf->participant_list; part; part = g_slist_next(part)) { @@ -989,11 +935,11 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) if (call) { if (call->_srtp_state == SRTP_STATE_UNLOCKED) { - DEBUG("Calltree: Participant %s is not secured", call_id); + DEBUG("Participant %s is not secured", call_id); conf->_conference_secured = FALSE; break; } else - DEBUG("Calltree: Participant %s is secured", call_id); + DEBUG("Participant %s is secured", call_id); } } } @@ -1001,22 +947,21 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) if (conf->_conf_srtp_enabled) { if (conf->_conference_secured) { - DEBUG("Calltree: Conference is secured"); + DEBUG("Conference is secured"); pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL); } else { - DEBUG("Calltree: Conference is not secured"); + DEBUG("Conference is not secured"); pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); } } - DEBUG("Calltree: Add conference to tree store"); - gchar *description = g_markup_printf_escaped("<b>%s</b>", ""); gtk_tree_store_set(current_calls_tab->store, &iter, COLUMN_ACCOUNT_PIXBUF, pixbuf, COLUMN_ACCOUNT_DESC, description, COLUMN_ACCOUNT_SECURITY_PIXBUF, pixbuf_security, - COLUMN_ACCOUNT_PTR, conf, + COLUMN_ID, conf->_confID, + COLUMN_IS_CONFERENCE, TRUE, -1); g_free(description); @@ -1030,7 +975,7 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) const gchar * const call_id = (gchar *) part->data; callable_obj_t *call = calllist_get_call(current_calls_tab, call_id); - calltree_remove_call(current_calls_tab, call); + calltree_remove_call(current_calls_tab, call->_callID); calltree_add_call(current_calls_tab, call, &iter); } @@ -1045,66 +990,65 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) } static -void calltree_remove_conference_recursive(calltab_t* tab, const conference_obj_t* conf, GtkTreeIter *parent) +gboolean +remove_conference(GtkTreeModel *model, GtkTreePath *path UNUSED, GtkTreeIter *iter, gpointer data) { - GtkTreeModel *model = GTK_TREE_MODEL(tab->store); - int nbChildren = gtk_tree_model_iter_n_children(model, parent); - - for (int i = 0; i < nbChildren; i++) { - GtkTreeIter iter_parent; + if (!is_conference(model, iter)) + return FALSE; - /* if the nth child of parent has one or more children */ - if (gtk_tree_model_iter_nth_child(model, &iter_parent, parent, i)) { - /* RECURSION! */ - if (gtk_tree_model_iter_has_child(model, &iter_parent)) - calltree_remove_conference_recursive(tab, conf, &iter_parent); + gchar *conf_id; + gtk_tree_model_get(model, iter, COLUMN_ID, &conf_id, -1); - GValue confval; - confval.g_type = 0; - gtk_tree_model_get_value(model, &iter_parent, COLUMN_ACCOUNT_PTR, &confval); + ConferenceRemoveCtx * ctx = (ConferenceRemoveCtx *) data; + calltab_t *tab = ctx->tab; + conference_obj_t *tempconf = conferencelist_get(tab, conf_id); + g_free(conf_id); - conference_obj_t *tempconf = (conference_obj_t*) g_value_get_pointer(&confval); - g_value_unset(&confval); + const conference_obj_t *conf = ctx->conf; + /* if this is not the conference we want to remove */ + if (tempconf != conf) + return FALSE; - /* if this is the conference we want to remove */ - if (tempconf == conf) { - int nbParticipants = gtk_tree_model_iter_n_children(model, &iter_parent); - DEBUG("CallTree: nbParticipants: %d", nbParticipants); + int nbParticipants = gtk_tree_model_iter_n_children(model, iter); + DEBUG("nbParticipants: %d", nbParticipants); - for (int j = 0; j < nbParticipants; j++) { - GtkTreeIter iter_child; + for (int j = 0; j < nbParticipants; j++) { + GtkTreeIter iter_child; - if (gtk_tree_model_iter_nth_child(model, &iter_child, &iter_parent, j)) { - GValue callval; - callval.g_type = 0; - gtk_tree_model_get_value(model, &iter_child, COLUMN_ACCOUNT_PTR, &callval); + if (gtk_tree_model_iter_nth_child(model, &iter_child, iter, j)) { + gchar *call_id; + gtk_tree_model_get(model, &iter_child, COLUMN_ID, &call_id, -1); - callable_obj_t *call = g_value_get_pointer(&callval); - g_value_unset(&callval); + callable_obj_t *call = calllist_get_call(tab, call_id); + g_free(call_id); - // do not add back call in history calltree when cleaning it - if (call && tab != history_tab) - calltree_add_call(tab, call, NULL); - } - } - - DEBUG("CallTree: Remove conference %s", conf->_confID); - gtk_tree_store_remove(tab->store, &iter_parent); - } + // do not add back call in history calltree when cleaning it + if (call && tab != history_tab) + calltree_add_call(tab, call, NULL); } } + gtk_tree_store_remove(GTK_TREE_STORE(model), iter); + if (calltab_get_selected_conf(tab) == conf) calltab_select_conf(tab, NULL); - - update_actions(); + return TRUE; } void calltree_remove_conference(calltab_t* tab, const conference_obj_t* conf) { - DEBUG("CallTree: Remove conference %s", conf->_confID); - calltree_remove_conference_recursive(tab, conf, NULL); - DEBUG("CallTree: Finished Removing conference"); + if(conf == NULL) { + ERROR("Could not remove conference, conference pointer is NULL"); + return; + } + + ConferenceRemoveCtx context = {tab, conf}; + GtkTreeStore *store = tab->store; + GtkTreeModel *model = GTK_TREE_MODEL(store); + gtk_tree_model_foreach(model, remove_conference, (gpointer) &context); + + update_actions(); + DEBUG("Finished removing conference %s", conf->_confID); } void calltree_display(calltab_t *tab) @@ -1130,14 +1074,13 @@ void calltree_display(calltab_t *tab) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(contactButton_), TRUE); set_focus_on_addressbook_searchbar(); } else - ERROR("CallTree: Error: Not a valid call tab (%d, %s)", __LINE__, __FILE__); + ERROR("Not a valid call tab (%d, %s)", __LINE__, __FILE__); gtk_widget_hide(active_calltree_tab->tree); active_calltree_tab = tab; gtk_widget_show(active_calltree_tab->tree); GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(active_calltree_tab->view)); - DEBUG("CallTree: Emit signal changed from calltree_display"); g_signal_emit_by_name(sel, "changed"); update_actions(); } @@ -1148,10 +1091,10 @@ gboolean calltree_update_clock(gpointer data UNUSED) char timestr[20]; const gchar *msg = ""; long duration; - callable_obj_t *c = calltab_get_selected_call(current_calls_tab); + callable_obj_t *call = calltab_get_selected_call(current_calls_tab); - if (c) - switch (c->_state) { + if (call) + switch (call->_state) { case CALL_STATE_INVALID: case CALL_STATE_INCOMING: case CALL_STATE_RINGING: @@ -1160,7 +1103,7 @@ gboolean calltree_update_clock(gpointer data UNUSED) case CALL_STATE_BUSY: break; default: - duration = difftime(time(NULL), c->_time_start); + duration = difftime(time(NULL), call->_time_start); if (duration < 0) duration = 0; @@ -1174,362 +1117,193 @@ gboolean calltree_update_clock(gpointer data UNUSED) return TRUE; } - -static void drag_end_cb(GtkWidget * widget UNUSED, GdkDragContext * context UNUSED, gpointer data UNUSED) +static void cleanup_popup_data(PopupData **data) { - if (active_calltree_tab == history_tab) - return; - - DEBUG("CallTree: Drag end callback"); - DEBUG("CallTree: selected_path %s, selected_call_id %s, selected_path_depth %d", - calltree_selected_path, calltree_selected_call_id, calltree_selected_path_depth); - DEBUG("CallTree: dragged path %s, dragged_call_id %s, dragged_path_depth %d", - calltree_dragged_path, calltree_dragged_call_id, calltree_dragged_path_depth); - - GtkTreeModel *model = (GtkTreeModel*) current_calls_tab->store; - GtkTreePath *path = gtk_tree_path_new_from_string(calltree_dragged_path); - GtkTreePath *dpath = gtk_tree_path_new_from_string(calltree_dragged_path); - GtkTreePath *spath = gtk_tree_path_new_from_string(calltree_selected_path); - - GtkTreeIter iter; - GtkTreeIter parent_conference; // conference for which this call is attached - - GValue val; - - // Make sure drag n drop does not imply a dialing call for either selected and dragged call - if (calltree_selected_call && (calltree_selected_type == A_CALL)) { - DEBUG("CallTree: Selected a call"); - - if (calltree_selected_call->_state == CALL_STATE_DIALING || - calltree_selected_call->_state == CALL_STATE_INVALID || - calltree_selected_call->_state == CALL_STATE_FAILURE || - calltree_selected_call->_state == CALL_STATE_BUSY || - calltree_selected_call->_state == CALL_STATE_TRANSFER) { - - DEBUG("CallTree: Selected an invalid call"); - - calltree_remove_call(current_calls_tab, calltree_selected_call); - calltree_add_call(current_calls_tab, calltree_selected_call, NULL); - - calltree_dragged_call = NULL; - return; - } - - - if (calltree_dragged_call && (calltree_dragged_type == A_CALL)) { - - DEBUG("CallTree: Dragged on a call"); - - if (calltree_dragged_call->_state == CALL_STATE_DIALING || - calltree_dragged_call->_state == CALL_STATE_INVALID || - calltree_dragged_call->_state == CALL_STATE_FAILURE || - calltree_dragged_call->_state == CALL_STATE_BUSY || - calltree_dragged_call->_state == CALL_STATE_TRANSFER) { - - DEBUG("CallTree: Dragged on an invalid call"); - - calltree_remove_call(current_calls_tab, calltree_selected_call); - - if (calltree_selected_call->_confID) { - - gtk_tree_path_up(spath); - gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &parent_conference, spath); - - calltree_add_call(current_calls_tab, calltree_selected_call, &parent_conference); - } else - calltree_add_call(current_calls_tab, calltree_selected_call, NULL); - - calltree_dragged_call = NULL; - return; - } - } + if (data && *data) { + g_free((*data)->source_ID); + g_free((*data)->dest_ID); + g_free(*data); + *data = 0; } +} - // Make sure a conference is only dragged on another conference - if (calltree_selected_conf && (calltree_selected_type == A_CONFERENCE)) { - - DEBUG("CallTree: Selected a conference"); - - if (!calltree_dragged_conf && (calltree_dragged_type == A_CALL)) { - - DEBUG("CallTree: Dragged on a call"); - conference_obj_t* conf = calltree_selected_conf; - - calltree_remove_conference(current_calls_tab, conf); - calltree_add_conference_to_current_calls(conf); +static gboolean +has_parent(GtkTreeModel *model, GtkTreeIter *child) +{ + GtkTreeIter parent; + return gtk_tree_model_iter_parent(model, &parent, child); +} - calltree_dragged_call = NULL; - return; - } +static gboolean try_detach(GtkTreeModel *model, GtkTreeIter *source_iter, GtkTreeIter *dest_iter) +{ + gboolean result = FALSE; + if (has_parent(model, source_iter) && !has_parent(model, dest_iter)) { + GValue source_val = G_VALUE_INIT; + gtk_tree_model_get_value(model, source_iter, COLUMN_ID, &source_val); + const gchar *source_ID = g_value_get_string(&source_val); + sflphone_detach_participant(source_ID); + result = TRUE; + g_value_unset(&source_val); } + return result; +} - - if (calltree_selected_path_depth == 1) { - if (calltree_dragged_path_depth == 1) { - if (calltree_selected_type == A_CALL && calltree_dragged_type == A_CALL) { - if (gtk_tree_path_compare(dpath, spath) != 0) { - // dragged a single call on a single call - if (calltree_selected_call != NULL && calltree_dragged_call != NULL) { - calltree_remove_call(current_calls_tab, calltree_selected_call); - calltree_add_call(current_calls_tab, calltree_selected_call, NULL); - gtk_menu_popup(GTK_MENU(calltree_popupmenu), NULL, NULL, NULL, NULL, - 0, 0); - } - } - } else if (calltree_selected_type == A_CALL && calltree_dragged_type == A_CONFERENCE) { - - // dragged a single call on a conference - if (!calltree_selected_call) { - DEBUG("Error: call dragged on a conference is null"); - return; - } - - g_free(calltree_selected_call->_confID); - calltree_selected_call->_confID = g_strdup(calltree_dragged_call_id); - - g_free(calltree_selected_call->_historyConfID); - calltree_selected_call->_historyConfID = g_strdup(calltree_dragged_call_id); - - sflphone_add_participant(calltree_selected_call_id, calltree_dragged_call_id); - } else if (calltree_selected_type == A_CONFERENCE && calltree_dragged_type == A_CALL) { - - // dragged a conference on a single call - conference_obj_t* conf = calltree_selected_conf; - - calltree_remove_conference(current_calls_tab, conf); - calltree_add_conference_to_current_calls(conf); - - } else if (calltree_selected_type == A_CONFERENCE && calltree_dragged_type == A_CONFERENCE) { - - // dragged a conference on a conference - if (gtk_tree_path_compare(dpath, spath) == 0) { - - if (!current_calls_tab) { - DEBUG("Error while joining the same conference\n"); - return; - } - - DEBUG("Joined the same conference!\n"); - gtk_tree_view_expand_row(GTK_TREE_VIEW(current_calls_tab->view), path, FALSE); - } else { - if (!calltree_selected_conf) - DEBUG("Error: selected conference is null while joining 2 conference"); - - if (!calltree_dragged_conf) - DEBUG("Error: dragged conference is null while joining 2 conference"); - - DEBUG("Joined conferences %s and %s!\n", calltree_dragged_path, calltree_selected_path); - dbus_join_conference(calltree_selected_conf->_confID, calltree_dragged_conf->_confID); - } +static gboolean +handle_drop_into(GtkTreeModel *model, GtkTreeIter *source_iter, GtkTreeIter *dest_iter) +{ + GValue source_val = G_VALUE_INIT; + gtk_tree_model_get_value(model, source_iter, COLUMN_ID, &source_val); + const gchar *source_ID = g_value_get_string(&source_val); + + GValue dest_val = G_VALUE_INIT; + gtk_tree_model_get_value(model, dest_iter, COLUMN_ID, &dest_val); + const gchar *dest_ID = g_value_get_string(&dest_val); + + gboolean result = FALSE; + + if (has_parent(model, source_iter)) { + DEBUG("Source is participant, should only be detached"); + result = FALSE; + } else if (!has_parent(model, dest_iter)) { + if (is_conference(model, dest_iter)) { + if (is_conference(model, source_iter)) { + DEBUG("dropped conference on conference, merging conferences"); + dbus_join_conference(source_ID, dest_ID); + result = TRUE; + } else { + DEBUG("dropped call on conference, adding a call to a conference"); + sflphone_add_participant(source_ID, dest_ID); + result = TRUE; } - - // TODO: dragged a single call on a NULL element (should do nothing) - // TODO: dragged a conference on a NULL element (should do nothing) - + } else if (is_conference(model, source_iter)) { + DEBUG("dropped conference on call, merging call into conference"); + sflphone_add_participant(dest_ID, source_ID); + result = TRUE; } else { - // dragged_path_depth == 2 - if (calltree_selected_type == A_CALL && calltree_dragged_type == A_CALL) { - // TODO: dragged a call on a conference call - calltree_remove_call(current_calls_tab, calltree_selected_call); - calltree_add_call(current_calls_tab, calltree_selected_call, NULL); - - } else if (calltree_selected_type == A_CONFERENCE && calltree_dragged_type == A_CALL) { - // TODO: dragged a conference on a conference call - calltree_remove_conference(current_calls_tab, calltree_selected_conf); - calltree_add_conference_to_current_calls(calltree_selected_conf); - } - - // TODO: dragged a single call on a NULL element - // TODO: dragged a conference on a NULL element + DEBUG("dropped call on call, creating new conference or transferring"); + calltree_remove_call(current_calls_tab, source_ID); + callable_obj_t *source_call = calllist_get_call(current_calls_tab, source_ID); + calltree_add_call(current_calls_tab, source_call, NULL); + cleanup_popup_data(&popup_data); + popup_data = g_new0(PopupData, 1); + popup_data->source_ID = g_strdup(source_ID); + popup_data->dest_ID = g_strdup(dest_ID); + gtk_menu_popup(GTK_MENU(calltree_popupmenu), NULL, NULL, NULL, NULL, 0, 0); + result = TRUE; } } else { - - if (calltree_dragged_path_depth == 1) { - if (calltree_selected_type == A_CALL && calltree_dragged_type == A_CALL) { - - // dragged a conference call on a call - sflphone_detach_participant(calltree_selected_call_id); - - if (calltree_selected_call && calltree_dragged_call) - gtk_menu_popup(GTK_MENU(calltree_popupmenu), NULL, NULL, NULL, NULL, - 0, 0); - - } else if (calltree_selected_type == A_CALL && calltree_dragged_type == A_CONFERENCE) { - // dragged a conference call on a conference - sflphone_detach_participant(calltree_selected_call_id); - - if (calltree_selected_call && calltree_dragged_conf) { - DEBUG("Adding a participant, since dragged call on a conference"); - sflphone_add_participant(calltree_selected_call_id, calltree_dragged_call_id); - } - } else { - // dragged a conference call on a NULL element - sflphone_detach_participant(calltree_selected_call_id); + // Happens when we drag a call on anther call which participate to a conference + callable_obj_t *dest_call = calllist_get_call(current_calls_tab, dest_ID); + if (dest_call) { + gchar *conf_ID = dbus_get_conference_id(dest_call->_callID); + if (g_strcmp0(conf_ID, "") != 0) { + sflphone_add_participant(source_ID, conf_ID); + result = TRUE; } - - } else { - // dragged_path_depth == 2 - // dragged a conference call on another conference call (same conference) - // TODO: dragged a conference call on another conference call (different conference) - - gtk_tree_path_up(path); - gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &parent_conference, path); - - gtk_tree_path_up(dpath); - gtk_tree_path_up(spath); - - if (gtk_tree_path_compare(dpath, spath) == 0) { - - DEBUG("Dragged a call in the same conference"); - calltree_remove_call(current_calls_tab, calltree_selected_call); - calltree_add_call(current_calls_tab, calltree_selected_call, &parent_conference); - gtk_widget_hide(calltree_menu_items); - gtk_menu_popup(GTK_MENU(calltree_popupmenu), NULL, NULL, NULL, NULL, - 0, 0); - } else { - DEBUG("Dragged a conference call onto another conference call %s, %s", gtk_tree_path_to_string(dpath), gtk_tree_path_to_string(spath)); - - conference_obj_t *conf = NULL; - val.g_type = 0; - - if (gtk_tree_model_get_iter(model, &iter, dpath)) { - gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_PTR, &val); - conf = (conference_obj_t*) g_value_get_pointer(&val); - } - - g_value_unset(&val); - - sflphone_detach_participant(calltree_selected_call_id); - - if (conf) - sflphone_add_participant(calltree_selected_call_id, conf->_confID); - else - DEBUG("didn't find a conf!"); - } - - // TODO: dragged a conference call on another conference call (different conference) - // TODO: dragged a conference call on a NULL element (same conference) - // TODO: dragged a conference call on a NULL element (different conference) } } + g_value_unset(&source_val); + g_value_unset(&dest_val); + return result; } -void drag_history_received_cb(GtkWidget *widget, GdkDragContext *context UNUSED, gint x UNUSED, gint y UNUSED, GtkSelectionData *selection_data UNUSED, guint info UNUSED, guint t UNUSED, gpointer data UNUSED) +static gboolean valid_drop(GtkTreeModel *model, GtkTreeIter *source_iter, GtkTreePath *dest_path) { - g_signal_stop_emission_by_name(G_OBJECT(widget), "drag_data_received"); + gboolean result = TRUE; + GtkTreePath *source_path = gtk_tree_model_get_path(model, source_iter); + if (!gtk_tree_path_compare(source_path, dest_path)) { + ERROR("invalid drop: source and destination are the same"); + result = FALSE; + } else if (gtk_tree_path_is_ancestor(source_path, dest_path)) { + ERROR("invalid drop: source is ancestor of destination"); + result = FALSE; + } else if (gtk_tree_path_is_descendant(source_path, dest_path)) { + ERROR("invalid drop: source is descendant of destination"); + result = FALSE; + } + gtk_tree_path_free(source_path); + return result; } -void drag_data_received_cb(GtkWidget *widget, GdkDragContext *context UNUSED, gint x UNUSED, gint y UNUSED, GtkSelectionData *selection_data UNUSED, guint info UNUSED, guint t UNUSED, gpointer data UNUSED) +static gboolean +render_drop(GtkTreeModel *model, GtkTreePath *dest_path, GtkTreeViewDropPosition dest_pos, + GtkTreeIter *source_iter) { - GtkTreeView *tree_view = GTK_TREE_VIEW(widget); - GtkTreePath *drop_path; - GtkTreeViewDropPosition position; - GValue val; - - if (active_calltree_tab == history_tab) { - g_signal_stop_emission_by_name(G_OBJECT(widget), "drag_data_received"); - return; + GtkTreeIter dest_iter; + if (!gtk_tree_model_get_iter(model, &dest_iter, dest_path)) { + ERROR("Could not get destination iterator"); + return FALSE; } - GtkTreeModel* tree_model = gtk_tree_view_get_model(tree_view); - - GtkTreeIter iter; - - val.g_type = 0; - gtk_tree_view_get_drag_dest_row(tree_view, &drop_path, &position); - - if (drop_path) { - - gtk_tree_model_get_iter(tree_model, &iter, drop_path); - gtk_tree_model_get_value(tree_model, &iter, COLUMN_ACCOUNT_PTR, &val); - - - if (gtk_tree_model_iter_has_child(tree_model, &iter)) { - DEBUG("CallTree: Dragging on a conference"); - calltree_dragged_type = A_CONFERENCE; - calltree_dragged_call = NULL; - } else { - DEBUG("CallTree: Dragging on a call"); - calltree_dragged_type = A_CALL; - calltree_dragged_conf = NULL; - } - - switch (position) { - - case GTK_TREE_VIEW_DROP_AFTER: - DEBUG("CallTree: GTK_TREE_VIEW_DROP_AFTER"); - calltree_dragged_path = gtk_tree_path_to_string(drop_path); - calltree_dragged_path_depth = gtk_tree_path_get_depth(drop_path); - calltree_dragged_call_id = "NULL"; - calltree_dragged_call = NULL; - calltree_dragged_conf = NULL; - break; - - case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: - DEBUG("CallTree: GTK_TREE_VIEW_DROP_INTO_OR_AFTER"); - calltree_dragged_path = gtk_tree_path_to_string(drop_path); - calltree_dragged_path_depth = gtk_tree_path_get_depth(drop_path); - - if (calltree_dragged_type == A_CALL) { - calltree_dragged_call_id = ((callable_obj_t*) g_value_get_pointer(&val))->_callID; - calltree_dragged_call = (callable_obj_t*) g_value_get_pointer(&val); - } else { - calltree_dragged_call_id = ((conference_obj_t*) g_value_get_pointer(&val))->_confID; - calltree_dragged_conf = (conference_obj_t*) g_value_get_pointer(&val); - } - - break; - - case GTK_TREE_VIEW_DROP_BEFORE: - DEBUG("CallTree: GTK_TREE_VIEW_DROP_BEFORE"); - calltree_dragged_path = gtk_tree_path_to_string(drop_path); - calltree_dragged_path_depth = gtk_tree_path_get_depth(drop_path); - calltree_dragged_call_id = "NULL"; - calltree_dragged_call = NULL; - calltree_dragged_conf = NULL; - break; - - case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: - DEBUG("CallTree: GTK_TREE_VIEW_DROP_INTO_OR_BEFORE"); - calltree_dragged_path = gtk_tree_path_to_string(drop_path); - calltree_dragged_path_depth = gtk_tree_path_get_depth(drop_path); - - if (calltree_dragged_type == A_CALL) { - calltree_dragged_call_id = ((callable_obj_t*) g_value_get_pointer(&val))->_callID; - calltree_dragged_call = (callable_obj_t*) g_value_get_pointer(&val); - } else { - calltree_dragged_call_id = ((conference_obj_t*) g_value_get_pointer(&val))->_confID; - calltree_dragged_conf = (conference_obj_t*) g_value_get_pointer(&val); - } + gboolean result = FALSE; + switch (dest_pos) { + case GTK_TREE_VIEW_DROP_BEFORE: + case GTK_TREE_VIEW_DROP_AFTER: + DEBUG("dropped at position %d, detaching if appropriate", dest_pos); + result = try_detach(model, source_iter, &dest_iter); + break; - break; + case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: + case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: + DEBUG("DROP_INTO"); + if (valid_drop(model, source_iter, dest_path)) + result = handle_drop_into(model, source_iter, &dest_iter); + break; + } + return result; +} - default: - break; - } +void drag_data_received_cb(GtkWidget *widget, GdkDragContext *context, gint x UNUSED, + gint y UNUSED, GtkSelectionData *selection_data UNUSED, guint target_type UNUSED, guint etime, gpointer data UNUSED) +{ + GtkTreeView *tree_view = GTK_TREE_VIEW(widget); + GtkTreeModel *model = GTK_TREE_MODEL(gtk_tree_view_get_model(tree_view)); + GtkTreeSelection *tree_selection = gtk_tree_view_get_selection(tree_view); + GtkTreeIter source_iter; + if (!gtk_tree_selection_get_selected(tree_selection, NULL, &source_iter)) { + ERROR("No tree element selected"); + return; } + GtkTreePath *dest_path; + GtkTreeViewDropPosition dest_pos; + if (!gtk_tree_view_get_dest_row_at_pos(tree_view, x, y, &dest_path, &dest_pos)) { + ERROR("No row at given position"); + return; + } + + gboolean success = render_drop(model, dest_path, dest_pos, &source_iter); + if (gdk_drag_context_get_selected_action(context) == GDK_ACTION_MOVE) + gtk_drag_finish(context, success, TRUE, etime); } /* Print a string when a menu item is selected */ -static void menuitem_response(gchar *string) +static void +menuitem_response(gchar * string) { - if (g_strcmp0(string, SFL_CREATE_CONFERENCE) == 0) - dbus_join_participant(calltree_selected_call->_callID, - calltree_dragged_call->_callID); - else if (g_strcmp0(string, SFL_TRANSFER_CALL) == 0) { - DEBUG("Calltree: Transferring call %s, to %s", - calltree_selected_call->_peer_number, - calltree_dragged_call->_peer_number); - dbus_attended_transfer(calltree_selected_call, calltree_dragged_call); - calltree_remove_call(current_calls_tab, calltree_selected_call); + if (g_strcmp0(string, SFL_CREATE_CONFERENCE) == 0) { + dbus_join_participant(popup_data->source_ID, + popup_data->dest_ID); + calltree_remove_call(current_calls_tab, popup_data->source_ID); + calltree_remove_call(current_calls_tab, popup_data->dest_ID); + update_actions(); + } else if (g_strcmp0(string, SFL_TRANSFER_CALL) == 0) { + callable_obj_t * source_call = calllist_get_call(current_calls_tab, popup_data->source_ID); + callable_obj_t * dest_call = calllist_get_call(current_calls_tab, popup_data->dest_ID); + DEBUG("Transferring call %s, to %s", + source_call->_peer_number, + dest_call->_peer_number); + dbus_attended_transfer(source_call, dest_call); + calltree_remove_call(current_calls_tab, popup_data->source_ID); } else - DEBUG("CallTree: Error unknown option selected in menu %s", string); + ERROR("Unknown option in menu %s", string); - // Make sure the create conference opetion will appear next time the menu pops + // Make sure the create conference option will appear next time the menu pops // The create conference option will hide if tow call from the same conference are draged on each other gtk_widget_show(calltree_menu_items); + cleanup_popup_data(&popup_data); + DEBUG("%s", string); } diff --git a/gnome/src/contacts/calltree.h b/gnome/src/contacts/calltree.h index 4f4fde48c77f3ba7d6acc2de617bf0dd07a49efc..b9e9e49768344711467958bcb0474cbb4a5f2dc8 100644 --- a/gnome/src/contacts/calltree.h +++ b/gnome/src/contacts/calltree.h @@ -35,12 +35,10 @@ /** @file calltree.h * @brief The GtkTreeView that list calls in the main window. */ - typedef enum { A_CALL, A_CONFERENCE, - A_INVALID -} CallType; + } CallType; /** * Tags used to identify display type in calltree @@ -80,10 +78,10 @@ calltree_update_call (calltab_t *, callable_obj_t *); /** * Remove a call from the call tree - * @param c The call to remove + * @param c The ID of the call to remove */ void -calltree_remove_call(calltab_t *, callable_obj_t *); +calltree_remove_call(calltab_t *, const gchar*); /** * Add a callable object to history treeview @@ -102,21 +100,22 @@ calltree_remove_conference(calltab_t *, const conference_obj_t *); void calltree_display (calltab_t *); -void -row_activated (GtkTreeView *, GtkTreePath *, GtkTreeViewColumn *, void *); - /** * Update elapsed time based on selected calltree's call */ gboolean calltree_update_clock(gpointer); -/** - * @param The calltab (current_calls, history, contacts) - * @param The call - * @param The callID/confID - */ -void -calltree_(calltab_t *, callable_obj_t *, const gchar * const); +gboolean +is_conference(GtkTreeModel *model, GtkTreeIter *iter); + +enum { + COLUMN_ACCOUNT_PIXBUF = 0, + COLUMN_ACCOUNT_DESC, + COLUMN_ACCOUNT_SECURITY_PIXBUF, + COLUMN_ID, + COLUMN_IS_CONFERENCE, + COLUMNS_IN_TREE_STORE +}; #endif diff --git a/gnome/src/contacts/conferencelist.c b/gnome/src/contacts/conferencelist.c index 3d4c68f8e1f04fbc347f7653fb0e4422e39dce31..1436812e92ddcd5ec4cb8d98841fa8b4748ed658 100644 --- a/gnome/src/contacts/conferencelist.c +++ b/gnome/src/contacts/conferencelist.c @@ -29,6 +29,7 @@ */ #include "calltab.h" +#include "str_utils.h" #include "callable_obj.h" #include "calltree.h" #include "conferencelist.h" @@ -37,13 +38,13 @@ static gint is_confID_confstruct(gconstpointer a, gconstpointer b) { conference_obj_t * c = (conference_obj_t*) a; - return g_strcasecmp(c->_confID, (const gchar*) b); + return utf8_case_cmp(c->_confID, (const gchar*) b); } void conferencelist_init(calltab_t *tab) { if (tab == NULL) { - ERROR("ConferenceList: Error: Call tab is NULL"); + ERROR("Call tab is NULL"); return; } @@ -54,7 +55,7 @@ void conferencelist_init(calltab_t *tab) void conferencelist_clean(calltab_t *tab) { if (tab == NULL) { - ERROR("ConferenceList: Error: Calltab tab is NULL"); + ERROR("Calltab tab is NULL"); return; } @@ -64,7 +65,7 @@ void conferencelist_clean(calltab_t *tab) void conferencelist_reset(calltab_t *tab) { if (tab == NULL) { - ERROR("ConferenceList: Error: Calltab tab is NULL"); + ERROR("Calltab tab is NULL"); return; } @@ -76,12 +77,12 @@ void conferencelist_reset(calltab_t *tab) void conferencelist_add(calltab_t *tab, const conference_obj_t* conf) { if (conf == NULL) { - ERROR("ConferenceList: Error: Conference is NULL"); + ERROR("Conference is NULL"); return; } if (tab == NULL) { - ERROR("ConferenceList: Error: Tab is NULL"); + ERROR("Tab is NULL"); return; } @@ -93,45 +94,41 @@ void conferencelist_add(calltab_t *tab, const conference_obj_t* conf) } -void conferencelist_remove(calltab_t *tab, const gchar* const conf) +void conferencelist_remove(calltab_t *tab, const gchar* const conf_id) { - DEBUG("ConferenceList: Remove conference %s", conf); + DEBUG("Remove conference %s", conf_id); - if (conf == NULL) { - ERROR("ConferenceList: Error: Conf id is NULL"); + if (conf_id == NULL) { + ERROR("Conf id is NULL"); return; } if (tab == NULL) { - ERROR("ConferenceList: Error: Calltab is NULL"); + ERROR("Calltab is NULL"); return; } - gchar *c = (gchar*) conferencelist_get(tab, conf); + conference_obj_t *c = conferencelist_get(tab, conf_id); - if (c == NULL) { - ERROR("ConferenceList: Error: Could not find conference %s", conf); + if (c == NULL) return; - } g_queue_remove(tab->conferenceQueue, c); } conference_obj_t* conferencelist_get(calltab_t *tab, const gchar* const conf_id) { - DEBUG("ConferenceList: Conference list get %s", conf_id); + DEBUG("Conference list get %s", conf_id); if (tab == NULL) { - ERROR("ConferenceList: Error: Calltab is NULL"); + ERROR("Calltab is NULL"); return NULL; } GList *c = g_queue_find_custom(tab->conferenceQueue, conf_id, is_confID_confstruct); - if (c == NULL) { - ERROR("ConferenceList: Error: Could not find conference %s", conf_id); + if (c == NULL) return NULL; - } return (conference_obj_t*) c->data; } @@ -139,14 +136,14 @@ conference_obj_t* conferencelist_get(calltab_t *tab, const gchar* const conf_id) conference_obj_t* conferencelist_get_nth(calltab_t *tab, guint n) { if (tab == NULL) { - ERROR("ConferenceList: Error: Calltab is NULL"); + ERROR("Calltab is NULL"); return NULL; } conference_obj_t *c = g_queue_peek_nth(tab->conferenceQueue, n); if (c == NULL) { - ERROR("ConferenceList: Error: Could not fetch conference %d", n); + ERROR("Could not fetch conference %d", n); return NULL; } @@ -156,7 +153,7 @@ conference_obj_t* conferencelist_get_nth(calltab_t *tab, guint n) conference_obj_t *conferencelist_pop_head(calltab_t *tab) { if (tab == NULL) { - ERROR("ConferenceList: Error: Tab is NULL"); + ERROR("Tab is NULL"); return NULL; } @@ -166,7 +163,7 @@ conference_obj_t *conferencelist_pop_head(calltab_t *tab) guint conferencelist_get_size(calltab_t *tab) { if (tab == NULL) { - ERROR("ConferenceList: Error: Calltab is NULL"); + ERROR("Calltab is NULL"); return 0; } diff --git a/gnome/src/contacts/history.c b/gnome/src/contacts/history.c index 33b01177d9b5db2b7f019cc5b4cd691122406421..681ae12e5bbe8f9f582e7e33cdcf8fa8ba758381 100644 --- a/gnome/src/contacts/history.c +++ b/gnome/src/contacts/history.c @@ -54,45 +54,34 @@ search_type_matches_state(SearchType type, const gchar *state) static gboolean history_is_visible(GtkTreeModel* model, GtkTreeIter* iter, gpointer data UNUSED) { - gboolean ret = TRUE; - callable_obj_t *history_entry = NULL; - const gchar *text = NULL; + /* Skip conferences */ + if (is_conference(model, iter)) + return TRUE; // Fetch the call description - GValue val; - memset(&val, 0, sizeof val); - gtk_tree_model_get_value(GTK_TREE_MODEL(model), iter, 1, &val); - - if (G_VALUE_HOLDS_STRING(&val)) - text = (gchar *) g_value_get_string(&val); - - // Fetch the call type - GValue obj; - memset(&obj, 0, sizeof obj); - gtk_tree_model_get_value(GTK_TREE_MODEL(model), iter, 3, &obj); - - if (G_VALUE_HOLDS_POINTER(&obj)) - history_entry = (gpointer) g_value_get_pointer(&obj); + const gchar *text = NULL; + const gchar *id = NULL; + gtk_tree_model_get(model, iter, COLUMN_ACCOUNT_DESC, &text, COLUMN_ID, &id, -1); + callable_obj_t *history_entry = calllist_get_call(history_tab, id); + gboolean ret = TRUE; if (text && history_entry) { // Filter according to the type of call // MISSED, INCOMING, OUTGOING, ALL const gchar* search = gtk_entry_get_text(history_searchbar_widget); if (!search || !*search) - goto end; + return TRUE; SearchType search_type = get_current_history_search_type(); ret = g_regex_match_simple(search, text, G_REGEX_CASELESS, 0); if (search_type == SEARCH_ALL) - goto end; + return ret; else // We need a match on the history_state and the current search type ret = ret && search_type_matches_state(search_type, history_entry->_history_state); } -end: - g_value_unset(&val); return ret; } diff --git a/gnome/src/contacts/searchbar.c b/gnome/src/contacts/searchbar.c index e48efafbc3a67d32932bc230df4de868c34de642..2fc06edb832a224a2a8ccc9fb0845a7e4943ed72 100644 --- a/gnome/src/contacts/searchbar.c +++ b/gnome/src/contacts/searchbar.c @@ -31,6 +31,8 @@ * as that of the covered work. */ +#include <glib/gi18n.h> +#include "gtk2_wrappers.h" #include "searchbar.h" #include "calltree.h" #include "calltab.h" @@ -45,18 +47,18 @@ static GtkWidget * searchbox; static GtkWidget * addressbookentry; static GtkWidget * cbox; -static GtkListStore * liststore = NULL; +static GtkListStore * liststore; static gint cboxSignalId; -static GtkWidget *menu = NULL; +static GtkWidget *menu; /** * Searchbar icons */ -static GdkPixbuf *incoming_pixbuf = NULL; -static GdkPixbuf *outgoing_pixbuf = NULL; -static GdkPixbuf *missed_pixbuf = NULL; +static GdkPixbuf *incoming_pixbuf; +static GdkPixbuf *outgoing_pixbuf; +static GdkPixbuf *missed_pixbuf; void searchbar_addressbook_activated(GtkEntry *entry, gchar *arg1 UNUSED, gpointer data UNUSED) { diff --git a/gnome/src/dbus/callmanager-introspec.xml b/gnome/src/dbus/callmanager-introspec.xml index 0682fb319c33f663548c74b9ef0db686ed3b94f1..5c48b6262df854a5c95324c3d6052cf248be620b 100644 --- a/gnome/src/dbus/callmanager-introspec.xml +++ b/gnome/src/dbus/callmanager-introspec.xml @@ -313,6 +313,24 @@ </arg> </method> + <method name="getConferenceId" tp:name-for-bindings="getConferenceId"> + <tp:added version="1.1.0"/> + <tp:docstring> + If thsi call participate to a conference, return the conference id. + Return an empty string elsewhere. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call id. + </tp:docstring> + </arg> + <arg type="s" name="confID" direction="out"> + <tp:docstring> + A string containing the conference ID, or an empty string. + </tp:docstring> + </arg> + </method> + <method name="setRecording" tp:name-for-bindings="setRecording"> <tp:docstring> Start recording a call. @@ -375,6 +393,7 @@ <li>DISPLAY_NAME</li> <li>CALL_STATE</li> <li>CALL_TYPE</li> + <li>CONF_ID</li> </ul> </tp:docstring> </arg> @@ -671,7 +690,7 @@ </arg> </signal> - <signal name="transferSucceded" tp:name-for-bindings="transferSucceded"> + <signal name="transferSucceeded" tp:name-for-bindings="transferSucceeded"> <tp:docstring> <p>Transfer has been successfully processed. Client should remove transfered @@ -682,7 +701,7 @@ <signal name="transferFailed" tp:name-for-bindings="transferFailed"> <tp:docstring> - <p>Transfer operation failed. Corespondin + <p>Transfer operation failed. Corresponding call is no longer accessible in SFLphone-daemon.</p> </tp:docstring> diff --git a/gnome/src/dbus/configurationmanager-introspec.xml b/gnome/src/dbus/configurationmanager-introspec.xml index 926ff774de75a99636920b3dc711ab6914695cb9..edf5883da5b183ae0cf1989ddbc73a07b8017dfd 100644 --- a/gnome/src/dbus/configurationmanager-introspec.xml +++ b/gnome/src/dbus/configurationmanager-introspec.xml @@ -37,9 +37,9 @@ <li>DISPLAY_NAMEL: The display name</li> <li>STUN_ENABLE: True or False (Default: False)</li> <li>STUN_SERVER: The STUN server address</li> - <li>REGISTRATION_STATUS: The account registration status. Should be Registered to make calls.</li> - <li>REGISTRATION_STATE_CODE</li> - <li>REGISTRATION_STATE_DESCRIPTION</li> + <li>ACCOUNT_REGISTRATION_STATUS: The account registration status. Should be Registered to make calls.</li> + <li>ACCOUNT_REGISTRATION_STATE_CODE</li> + <li>ACCOUNT_REGISTRATION_STATE_DESC</li> <li>SRTP_KEY_EXCHANGE</li> <li>SRTP_ENABLE: Whether or not voice communication are encrypted - True or False (Default: False)</li> <li>SRTP_RTP_FALLBACK</li> @@ -91,7 +91,6 @@ Get configuration settings of the IP2IP_PROFILE. They are sligthly different from account settings since no VoIP accounts are involved. </tp:docstring> <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <!--<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/>--> <arg type="a{ss}" name="details" direction="out" tp:type="String_String_Map"> <tp:docstring> Available parameters are: @@ -447,6 +446,24 @@ <signal name="accountsChanged" tp:name-for-bindings="accountsChanged"> </signal> + <signal name="historyChanged" tp:name-for-bindings="historyChanged"> + </signal> + + <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged"> + <arg type="s" name="accountID"/> + <arg type="i" name="registration_state"/> + </signal> + + <signal name="stunStatusFailure" tp:name-for_bindings="stunStatusFailure"> + <arg type="s" name="reason"> + </arg> + </signal> + + <signal name="stunStatusSuccess" tp:name-for_bindings="stunStatusSuccess"> + <arg type="s" name="message"> + </arg> + </signal> + <signal name="errorAlert" tp:name-for-bindings="errorAlert"> <arg type="i" name="code"> </arg> diff --git a/gnome/src/dbus/dbus.c b/gnome/src/dbus/dbus.c index e321a671498d0ee17cbab3f8e69df78cbace24e2..05bc9b32acbc17a47dbc406fed0ac03b1ebeffe5 100644 --- a/gnome/src/dbus/dbus.c +++ b/gnome/src/dbus/dbus.c @@ -29,20 +29,25 @@ * shall include the source code for the parts of OpenSSL used as well * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif +#include <glib/gi18n.h> +#include "str_utils.h" #include "logger.h" #include "calltab.h" #include "callmanager-glue.h" #include "configurationmanager-glue.h" #include "instance-glue.h" #include "preferencesdialog.h" -#include "accountlistconfigdialog.h" #include "mainwindow.h" #include "marshaller.h" #include "sliders.h" #include "statusicon.h" #include "assistant.h" +#include "accountlist.h" +#include "accountlistconfigdialog.h" #include "dbus.h" #include "actions.h" @@ -56,12 +61,14 @@ static DBusGProxy *call_proxy; static DBusGProxy *config_proxy; static DBusGProxy *instance_proxy; +// static DBusGProxy *session_manager_proxy; +static GDBusProxy *session_manager_proxy; /* Returns TRUE if there was an error, FALSE otherwise */ static gboolean check_error(GError *error) { if (error) { - DEBUG("DBUS: Error: %s", error->message); + ERROR("%s", error->message); g_error_free(error); return TRUE; } @@ -119,7 +126,7 @@ static void volume_changed_cb(DBusGProxy *proxy UNUSED, const gchar *device, gdouble value, void *foo UNUSED) { - set_slider(device, value); + set_slider_no_update(device, value); } static void @@ -147,7 +154,6 @@ incoming_message_cb(DBusGProxy *proxy UNUSED, const gchar *callID UNUSED, id = call->_callID; } else { conference_obj_t *conf = conferencelist_get(current_calls_tab, callID); - if (!conf) { ERROR("Message received, but no recipient found"); return; @@ -208,7 +214,7 @@ process_existing_call_state_change(callable_obj_t *c, const gchar *state) /** * This function process call state changes in case the call have not been created yet. - * This mainly occurs when anotehr SFLphone client takes actions. + * This mainly occurs when another SFLphone client takes actions. */ static void process_nonexisting_call_state_change(const gchar *callID, const gchar *state) @@ -222,26 +228,19 @@ process_nonexisting_call_state_change(const gchar *callID, const gchar *state) } else if (g_strcmp0(state, "HUNGUP") == 0) return; // Could occur if a user picked up the phone and hung up without making a call - // The callID is unknow, threat it like a new call + // The callID is unknown, treat it like a new call // If it were an incoming call, we won't be here // It means that a new call has been initiated with an other client (cli for instance) if (g_strcmp0(state, "RINGING") == 0 || g_strcmp0(state, "CURRENT") == 0 || g_strcmp0(state, "RECORD")) { - DEBUG("DBUS: New ringing call! accountID: %s", callID); - - // We fetch the details associated to the specified call - GHashTable *call_details = dbus_get_call_details(callID); - callable_obj_t *new_call = create_new_call_from_details(callID, call_details); + DEBUG("New ringing call! accountID: %s", callID); - if (g_strcasecmp(g_hash_table_lookup(call_details, "CALL_TYPE"), INCOMING_STRING) == 0) - new_call->_history_state = g_strdup(INCOMING_STRING); - else - new_call->_history_state = g_strdup(OUTGOING_STRING); - - calllist_add_call(current_calls_tab, new_call); - calltree_add_call(current_calls_tab, new_call, NULL); + restore_call(callID); + callable_obj_t *new_call = calllist_get_call(current_calls_tab, callID); + if (new_call) + calltree_add_call(current_calls_tab, new_call, NULL); update_actions(); calltree_display(current_calls_tab); } @@ -256,7 +255,7 @@ call_state_cb(DBusGProxy *proxy UNUSED, const gchar *callID, if (c) process_existing_call_state_change(c, state); else { - WARN("DBUS: Call does not exist in %s", __func__); + WARN("Call does not exist in %s", __func__); process_nonexisting_call_state_change(callID, state); } } @@ -276,12 +275,11 @@ static void conference_changed_cb(DBusGProxy *proxy UNUSED, const gchar *confID, const gchar *state, void *foo UNUSED) { - DEBUG("DBUS: Conference state changed: %s\n", state); + DEBUG("Conference state changed: %s\n", state); conference_obj_t* changed_conf = conferencelist_get(current_calls_tab, confID); - if (changed_conf == NULL) { - ERROR("DBUS: Conference is NULL in conference state changed"); + ERROR("Conference is NULL in conference state changed"); return; } @@ -319,7 +317,7 @@ conference_changed_cb(DBusGProxy *proxy UNUSED, const gchar *confID, static void conference_created_cb(DBusGProxy *proxy UNUSED, const gchar *confID, void *foo UNUSED) { - DEBUG("DBUS: Conference %s added", confID); + DEBUG("Conference %s added", confID); conference_obj_t *new_conf = create_new_conference(CONFERENCE_STATE_ACTIVE_ATTACHED, confID); @@ -338,7 +336,6 @@ conference_created_cb(DBusGProxy *proxy UNUSED, const gchar *confID, void *foo U if (call->_state == CALL_STATE_RECORD) new_conf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD; - call->_confID = g_strdup(confID); call->_historyConfID = g_strdup(confID); } @@ -354,8 +351,13 @@ static void conference_removed_cb(DBusGProxy *proxy UNUSED, const gchar *confID, void *foo UNUSED) { - DEBUG("DBUS: Conference removed %s", confID); + DEBUG("Conference removed %s", confID); conference_obj_t *c = conferencelist_get(current_calls_tab, confID); + if(c == NULL) { + ERROR("Could not find conference %s from list", confID); + return; + } + calltree_remove_conference(current_calls_tab, c); im_widget_update_state(IM_WIDGET(c->_im_widget), FALSE); @@ -365,8 +367,6 @@ conference_removed_cb(DBusGProxy *proxy UNUSED, const gchar *confID, callable_obj_t *call = calllist_get_call(current_calls_tab, p->data); if (call) { - g_free(call->_confID); - call->_confID = NULL; im_widget_update_state(IM_WIDGET(call->_im_widget), TRUE); } } @@ -378,17 +378,17 @@ static void record_playback_filepath_cb(DBusGProxy *proxy UNUSED, const gchar *id, const gchar *filepath) { - DEBUG("DBUS: Filepath for %s: %s", id, filepath); + DEBUG("Filepath for %s: %s", id, filepath); callable_obj_t *call = calllist_get_call(current_calls_tab, id); conference_obj_t *conf = conferencelist_get(current_calls_tab, id); if (call && conf) { - ERROR("DBUS: Two objects for this callid"); + ERROR("Two objects for this callid"); return; } if (!call && !conf) { - ERROR("DBUS: Could not get object"); + ERROR("Could not get object"); return; } @@ -401,34 +401,64 @@ record_playback_filepath_cb(DBusGProxy *proxy UNUSED, const gchar *id, static void record_playback_stopped_cb(DBusGProxy *proxy UNUSED, const gchar *filepath) { - DEBUG("DBUS: Playback stopped for %s", filepath); + DEBUG("Playback stopped for %s", filepath); const gint calllist_size = calllist_get_size(history_tab); for (gint i = 0; i < calllist_size; i++) { - QueueElement *element = calllist_get_nth(history_tab, i); + callable_obj_t *call = calllist_get_nth(history_tab, i); - if (element == NULL) { - ERROR("DBUS: ERROR: Could not find %dth call", i); + if (call == NULL) { + ERROR("Could not find %dth call", i); break; - } else if (element->type == HIST_CALL) { - if (g_strcmp0(element->elem.call->_recordfile, filepath) == 0) - element->elem.call->_record_is_playing = FALSE; } + if (g_strcmp0(call->_recordfile, filepath) == 0) + call->_record_is_playing = FALSE; } update_actions(); } +static void +registration_state_changed_cb(DBusGProxy *proxy UNUSED, const gchar *accountID, + guint state, void *foo UNUSED) +{ + DEBUG("DBus: Registration state changed to %s for account %s", + account_state_name(state), accountID); + account_t *acc = account_list_get_by_id(accountID); + if (acc) { + acc->state = state; + update_account_list_status_bar(acc); + } +} + static void accounts_changed_cb(DBusGProxy *proxy UNUSED, void *foo UNUSED) { sflphone_fill_account_list(); sflphone_fill_ip2ip_profile(); - account_list_config_dialog_fill(); status_bar_display_account(); statusicon_set_tooltip(); } +static void +stun_status_failure_cb(DBusGProxy *proxy UNUSED, const gchar *accountID, void *foo UNUSED) +{ + ERROR("Error: Stun status failure: account %s failed to setup STUN", + accountID); + // Disable STUN for the account that tried to create the STUN transport + account_t *account = account_list_get_by_id(accountID); + if (account) { + account_replace(account, ACCOUNT_SIP_STUN_ENABLED, "false"); + dbus_set_account_details(account); + } +} + +static void +stun_status_success_cb(DBusGProxy *proxy UNUSED, const gchar *message UNUSED, void *foo UNUSED) +{ + DEBUG("STUN setup successful"); +} + static void transfer_succeeded_cb(DBusGProxy *proxy UNUSED, void *foo UNUSED) { @@ -444,7 +474,7 @@ transfer_failed_cb(DBusGProxy *proxy UNUSED, void *foo UNUSED) static void secure_sdes_on_cb(DBusGProxy *proxy UNUSED, const gchar *callID, void *foo UNUSED) { - DEBUG("DBUS: SRTP using SDES is on"); + DEBUG("SRTP using SDES is on"); callable_obj_t *c = calllist_get_call(current_calls_tab, callID); if (c) { @@ -456,7 +486,7 @@ secure_sdes_on_cb(DBusGProxy *proxy UNUSED, const gchar *callID, void *foo UNUSE static void secure_sdes_off_cb(DBusGProxy *proxy UNUSED, const gchar *callID, void *foo UNUSED) { - DEBUG("DBUS: SRTP using SDES is off"); + DEBUG("SRTP using SDES is off"); callable_obj_t *c = calllist_get_call(current_calls_tab, callID); if (c) { @@ -469,7 +499,7 @@ static void secure_zrtp_on_cb(DBusGProxy *proxy UNUSED, const gchar *callID, const gchar *cipher, void *foo UNUSED) { - DEBUG("DBUS: SRTP using ZRTP is ON secure_on_cb"); + DEBUG("SRTP using ZRTP is ON secure_on_cb"); callable_obj_t *c = calllist_get_call(current_calls_tab, callID); if (c) { @@ -482,7 +512,7 @@ secure_zrtp_on_cb(DBusGProxy *proxy UNUSED, const gchar *callID, static void secure_zrtp_off_cb(DBusGProxy *proxy UNUSED, const gchar *callID, void *foo UNUSED) { - DEBUG("DBUS: SRTP using ZRTP is OFF"); + DEBUG("SRTP using ZRTP is OFF"); callable_obj_t *c = calllist_get_call(current_calls_tab, callID); if (c) { @@ -495,7 +525,7 @@ static void show_zrtp_sas_cb(DBusGProxy *proxy UNUSED, const gchar *callID, const gchar *sas, gboolean verified, void *foo UNUSED) { - DEBUG("DBUS: Showing SAS"); + DEBUG("Showing SAS"); callable_obj_t *c = calllist_get_call(current_calls_tab, callID); if (c) @@ -505,7 +535,7 @@ show_zrtp_sas_cb(DBusGProxy *proxy UNUSED, const gchar *callID, const gchar *sas static void confirm_go_clear_cb(DBusGProxy *proxy UNUSED, const gchar *callID, void *foo UNUSED) { - DEBUG("DBUS: Confirm Go Clear request"); + DEBUG("Confirm Go Clear request"); callable_obj_t *c = calllist_get_call(current_calls_tab, callID); if (c) @@ -528,7 +558,7 @@ static void sip_call_state_cb(DBusGProxy *proxy UNUSED, const gchar *callID, const gchar *description, guint code, void *foo UNUSED) { - DEBUG("DBUS: Sip call state changed %s", callID); + DEBUG("Sip call state changed %s", callID); callable_obj_t *c = calllist_get_call(current_calls_tab, callID); if (c) @@ -567,43 +597,142 @@ error_alert(DBusGProxy *proxy UNUSED, int err, void *foo UNUSED) gtk_widget_show(dialog); } +static void +screensaver_dbus_proxy_new_cb (GObject * source UNUSED, GAsyncResult *result, gpointer user_data UNUSED) +{ + DEBUG("Session manager connection callback"); + + session_manager_proxy = g_dbus_proxy_new_for_bus_finish (result, NULL); + if (session_manager_proxy == NULL) + ERROR("could not initialize gnome session manager"); +} + +#define GS_SERVICE "org.gnome.SessionManager" +#define GS_PATH "/org/gnome/SessionManager" +#define GS_INTERFACE "org.gnome.SessionManager" + +gboolean dbus_connect_session_manager(DBusGConnection *connection) +{ + + if (connection == NULL) { + ERROR("connection is NULL"); + return FALSE; + } +/* + session_manager_proxy = dbus_g_proxy_new_for_name(connection, + "org.gnome.SessionManager", "/org/gnome/SessionManager/Inhibitor", + "org.gnome.SessionManager.Inhibitor"); + + if(session_manager_proxy == NULL) { + ERROR("Error, could not create session manager proxy"); + return FALSE; + } +*/ + + g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, GS_SERVICE, GS_PATH, GS_INTERFACE, NULL, + screensaver_dbus_proxy_new_cb, NULL); + + DEBUG("Connected to gnome session manager"); + + return TRUE; +} + gboolean dbus_connect(GError **error) { + const char *dbus_message_bus_name = "org.sflphone.SFLphone"; + const char *dbus_object_instance = "/org/sflphone/SFLphone/Instance"; + const char *dbus_interface = "org.sflphone.SFLphone.Instance"; + const char *callmanager_object_instance = "/org/sflphone/SFLphone/CallManager"; + const char *callmanager_interface = "org.sflphone.SFLphone.CallManager"; + const char *configurationmanager_object_instance = "/org/sflphone/SFLphone/ConfigurationManager"; + const char *configurationmanager_interface = "org.sflphone.SFLphone.ConfigurationManager"; + g_type_init(); DBusGConnection *connection = dbus_g_bus_get(DBUS_BUS_SESSION, error); - - if (connection == NULL) + if (connection == NULL) { + ERROR("could not establish connection with session bus"); return FALSE; + } /* Create a proxy object for the "bus driver" (name "org.freedesktop.DBus") */ + DEBUG("Connect to message bus: %s", dbus_message_bus_name); + DEBUG(" object instance: %s", dbus_object_instance); + DEBUG(" dbus interface: %s", dbus_interface); - instance_proxy = dbus_g_proxy_new_for_name(connection, - "org.sflphone.SFLphone", "/org/sflphone/SFLphone/Instance", - "org.sflphone.SFLphone.Instance"); - + instance_proxy = dbus_g_proxy_new_for_name(connection, dbus_message_bus_name, dbus_object_instance, dbus_interface); if (instance_proxy == NULL) { - ERROR("Failed to get proxy to Instance"); + ERROR("Error: Failed to connect to %s", dbus_message_bus_name); return FALSE; } - DEBUG("DBus connected to Instance"); + DEBUG("Connect to object instance: %s", callmanager_object_instance); + DEBUG(" dbus interface: %s", callmanager_interface); - call_proxy = dbus_g_proxy_new_for_name(connection, "org.sflphone.SFLphone", - "/org/sflphone/SFLphone/CallManager", - "org.sflphone.SFLphone.CallManager"); - g_assert(call_proxy != NULL); + call_proxy = dbus_g_proxy_new_for_name(connection, dbus_message_bus_name, callmanager_object_instance, callmanager_interface); + if (call_proxy == NULL) { + ERROR("Error: Failed to connect to %s", callmanager_object_instance); + return FALSE; + } - DEBUG("DBus connected to CallManager"); - /* STRING STRING STRING Marshaller */ - /* Incoming call */ + config_proxy = dbus_g_proxy_new_for_name(connection, dbus_message_bus_name, configurationmanager_object_instance, configurationmanager_interface); + if (config_proxy == NULL) { + ERROR("Error: Failed to connect to %s", configurationmanager_object_instance); + return FALSE; + } + + /* Register INT Marshaller */ + dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__INT, + G_TYPE_NONE, G_TYPE_INT, G_TYPE_INVALID); + + /* Register STRING STRING STRING Marshaller */ dbus_g_object_register_marshaller( g_cclosure_user_marshal_VOID__STRING_STRING_STRING, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); + + /* Register STRING STRING INT Marshaller */ + dbus_g_object_register_marshaller( + g_cclosure_user_marshal_VOID__STRING_STRING_INT, G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); + + /* Register STRING STRING Marshaller */ + dbus_g_object_register_marshaller( + g_cclosure_user_marshal_VOID__STRING_STRING, G_TYPE_NONE, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_INVALID); + + /* Register STRING INT Marshaller */ + dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING_INT, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); + + /* Register STRING DOUBLE Marshaller */ + dbus_g_object_register_marshaller( + g_cclosure_user_marshal_VOID__STRING_DOUBLE, G_TYPE_NONE, G_TYPE_STRING, + G_TYPE_DOUBLE, G_TYPE_INVALID); + + /* Register STRING Marshaller */ + dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID); + + /* Register STRING STRING BOOL Marshaller */ + dbus_g_object_register_marshaller( + g_cclosure_user_marshal_VOID__STRING_STRING_BOOL, G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID); + + /* Register STRING Marshaller */ + dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID); + + + DEBUG("Adding callmanager Dbus signals"); + + /* Incoming call */ dbus_g_proxy_add_signal(call_proxy, "newCallCreated", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "newCallCreated", G_CALLBACK(new_call_created_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "incomingCall", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "incomingCall", @@ -614,30 +743,26 @@ gboolean dbus_connect(GError **error) dbus_g_proxy_connect_signal(call_proxy, "zrtpNegotiationFailed", G_CALLBACK(zrtp_negotiation_failed_cb), NULL, NULL); - /* Register a marshaller for STRING,STRING */ - dbus_g_object_register_marshaller( - g_cclosure_user_marshal_VOID__STRING_STRING, G_TYPE_NONE, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "callStateChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "callStateChanged", G_CALLBACK(call_state_cb), NULL, NULL); - dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING_INT, - G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "voiceMailNotify", G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "voiceMailNotify", G_CALLBACK(voice_mail_cb), NULL, NULL); + dbus_g_proxy_add_signal(config_proxy, "registrationStateChanged", G_TYPE_STRING, + G_TYPE_INT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(config_proxy, "registrationStateChanged", + G_CALLBACK(registration_state_changed_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "incomingMessage", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "incomingMessage", G_CALLBACK(incoming_message_cb), NULL, NULL); - dbus_g_object_register_marshaller( - g_cclosure_user_marshal_VOID__STRING_DOUBLE, G_TYPE_NONE, G_TYPE_STRING, - G_TYPE_DOUBLE, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "volumeChanged", G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "volumeChanged", @@ -652,9 +777,6 @@ gboolean dbus_connect(GError **error) G_CALLBACK(transfer_failed_cb), NULL, NULL); /* Conference related callback */ - - dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING, - G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "conferenceChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "conferenceChanged", @@ -675,12 +797,12 @@ gboolean dbus_connect(GError **error) G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "recordPlaybackFilepath", G_CALLBACK(record_playback_filepath_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "recordPlaybackStopped", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "recordPlaybackStopped", G_CALLBACK(record_playback_stopped_cb), NULL, NULL); /* Security related callbacks */ - dbus_g_proxy_add_signal(call_proxy, "secureSdesOn", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "secureSdesOn", @@ -691,10 +813,6 @@ gboolean dbus_connect(GError **error) dbus_g_proxy_connect_signal(call_proxy, "secureSdesOff", G_CALLBACK(secure_sdes_off_cb), NULL, NULL); - /* Register a marshaller for STRING,STRING,BOOL */ - dbus_g_object_register_marshaller( - g_cclosure_user_marshal_VOID__STRING_STRING_BOOL, G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "showSAS", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "showSAS", @@ -705,48 +823,43 @@ gboolean dbus_connect(GError **error) dbus_g_proxy_connect_signal(call_proxy, "secureZrtpOn", G_CALLBACK(secure_zrtp_on_cb), NULL, NULL); - /* Register a marshaller for STRING*/ - dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING, - G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "secureZrtpOff", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "secureZrtpOff", G_CALLBACK(secure_zrtp_off_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "zrtpNotSuppOther", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "zrtpNotSuppOther", G_CALLBACK(zrtp_not_supported_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "confirmGoClear", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "confirmGoClear", G_CALLBACK(confirm_go_clear_cb), NULL, NULL); - /* VOID STRING STRING INT */ - dbus_g_object_register_marshaller( - g_cclosure_user_marshal_VOID__STRING_STRING_INT, G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); - dbus_g_proxy_add_signal(call_proxy, "sipCallStateChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "sipCallStateChanged", G_CALLBACK(sip_call_state_cb), NULL, NULL); - config_proxy = dbus_g_proxy_new_for_name(connection, - "org.sflphone.SFLphone", - "/org/sflphone/SFLphone/ConfigurationManager", - "org.sflphone.SFLphone.ConfigurationManager"); - g_assert(config_proxy != NULL); - DEBUG("DBus connected to ConfigurationManager"); + DEBUG("Adding configurationmanager Dbus signals"); + dbus_g_proxy_add_signal(config_proxy, "accountsChanged", G_TYPE_INVALID); dbus_g_proxy_connect_signal(config_proxy, "accountsChanged", G_CALLBACK(accounts_changed_cb), NULL, NULL); - dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__INT, - G_TYPE_NONE, G_TYPE_INT, G_TYPE_INVALID); - dbus_g_proxy_add_signal(config_proxy, "errorAlert", G_TYPE_INT, - G_TYPE_INVALID); + dbus_g_proxy_add_signal(config_proxy, "stunStatusFailure", G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(config_proxy, "stunStatusFailure", + G_CALLBACK(stun_status_failure_cb), NULL, NULL); + + dbus_g_proxy_add_signal(config_proxy, "stunStatusSuccess", G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(config_proxy, "stunStatusSuccess", + G_CALLBACK(stun_status_success_cb), NULL, NULL); + + dbus_g_proxy_add_signal(config_proxy, "errorAlert", G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_connect_signal(config_proxy, "errorAlert", G_CALLBACK(error_alert), NULL, NULL); @@ -758,6 +871,12 @@ gboolean dbus_connect(GError **error) dbus_g_proxy_set_default_timeout(config_proxy, DEFAULT_DBUS_TIMEOUT); #endif + gboolean status = dbus_connect_session_manager(connection); + if(status == FALSE) { + ERROR("could not connect to gnome session manager"); + return FALSE; + } + return TRUE; } @@ -980,11 +1099,12 @@ dbus_remove_account(const gchar *accountID) { GError *error = NULL; org_sflphone_SFLphone_ConfigurationManager_remove_account(config_proxy, accountID, &error); + account_list_remove(accountID); check_error(error); } void -dbus_set_account_details(account_t *a) +dbus_set_account_details(const account_t *a) { g_assert(a); GError *error = NULL; @@ -997,8 +1117,11 @@ void dbus_add_account(account_t *a) { g_assert(a); - GError *error = NULL; + g_assert(a->accountID); + g_assert(a->properties); g_free(a->accountID); + GError *error = NULL; + a->accountID = NULL; org_sflphone_SFLphone_ConfigurationManager_add_account(config_proxy, a->properties, &a->accountID, &error); check_error(error); @@ -1049,7 +1172,7 @@ void dbus_unregister(int pid) { GError *error = NULL; - org_sflphone_SFLphone_Instance_unregister(instance_proxy, pid, &error); + org_sflphone_SFLphone_Instance_unregister_async(instance_proxy, pid, NULL, NULL); check_error(error); } @@ -1345,7 +1468,7 @@ dbus_is_iax2_enabled() void dbus_join_participant(const gchar *sel_callID, const gchar *drag_callID) { - DEBUG("DBUS: Join participant %s and %s\n", sel_callID, drag_callID); + DEBUG("Join participant %s and %s\n", sel_callID, drag_callID); GError *error = NULL; org_sflphone_SFLphone_CallManager_join_participant(call_proxy, sel_callID, drag_callID, &error); check_error(error); @@ -1362,7 +1485,7 @@ dbus_create_conf_from_participant_list(const gchar **list) void dbus_add_participant(const gchar *callID, const gchar *confID) { - DEBUG("DBUS: Add participant %s to %s\n", callID, confID); + DEBUG("Add participant %s to %s\n", callID, confID); GError *error = NULL; org_sflphone_SFLphone_CallManager_add_participant(call_proxy, callID, confID, &error); check_error(error); @@ -1591,15 +1714,25 @@ gchar ** dbus_get_participant_list(const gchar *confID) { GError *error = NULL; - char **list = NULL; + gchar **list = NULL; - DEBUG("DBUS: Get conference %s participant list", confID); + DEBUG("Get conference %s participant list", confID); org_sflphone_SFLphone_CallManager_get_participant_list(call_proxy, confID, &list, &error); check_error(error); return list; } +gchar * +dbus_get_conference_id(const gchar *callID) +{ + gchar *confID = NULL; + GError *error = NULL; + org_sflphone_SFLphone_CallManager_get_conference_id(call_proxy, callID, &confID, &error); + check_error(error); + return confID; +} + GHashTable * dbus_get_conference_details(const gchar *confID) { @@ -1705,7 +1838,7 @@ dbus_get_all_ip_interface(void) if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) ERROR("Caught remote method (get_all_ip_interface) exception %s: %s", dbus_g_error_get_name(error), error->message); else - ERROR("Error while calling get_all_ip_interface: %s", error->message); + ERROR("%s", error->message); g_error_free(error); } else @@ -1725,7 +1858,7 @@ dbus_get_all_ip_interface_by_name(void) ERROR("Caught remote method (get_all_ip_interface) exception %s: %s", dbus_g_error_get_name(error), error->message); else - ERROR("Error while calling get_all_ip_interface: %s", error->message); + ERROR("%s", error->message); g_error_free(error); } @@ -1744,7 +1877,7 @@ dbus_get_shortcuts(void) ERROR("Caught remote method (get_shortcuts) exception %s: %s", dbus_g_error_get_name(error), error->message); else - ERROR("Error while calling get_shortcuts: %s", error->message); + ERROR("%s", error->message); g_error_free(error); } @@ -1767,3 +1900,89 @@ dbus_send_text_message(const gchar *callID, const gchar *message) org_sflphone_SFLphone_CallManager_send_text_message(call_proxy, callID, message, &error); check_error(error); } + +static guint cookie; +#define GNOME_SESSION_NO_IDLE_FLAG 8 + +static void screensaver_inhibit_cb(GObject * source_object, GAsyncResult * res, + gpointer user_data UNUSED) +{ + GDBusProxy *proxy = G_DBUS_PROXY(source_object); + GError *error = NULL; + GVariant *value = g_dbus_proxy_call_finish(proxy, res, &error); + if (!value) { + ERROR("%s", error->message); + g_error_free(error); + return; + } + + /* save the cookie */ + if (g_variant_is_of_type(value, G_VARIANT_TYPE("(u)"))) + g_variant_get(value, "(u)", &cookie); + else + cookie = 0; + + g_variant_unref(value); +} + +static void screensaver_uninhibit_cb(GObject * source_object, + GAsyncResult * res, + gpointer user_data UNUSED) +{ + GDBusProxy *proxy = G_DBUS_PROXY(source_object); + GError *error = NULL; + + GVariant *value = g_dbus_proxy_call_finish(proxy, res, &error); + if (!value) { + ERROR ("%s", + error->message); + g_error_free(error); + return; + } + + /* clear the cookie */ + cookie = 0; + g_variant_unref(value); +} + +void dbus_screensaver_inhibit(void) +{ + const gchar *appname = g_get_application_name(); + if (appname == NULL) { + ERROR("could not retrieve application name"); + return; + } + + guint xid = 0; + GVariant *parameters = g_variant_new("(susu)", appname, xid, + "Phone call ongoing", + GNOME_SESSION_NO_IDLE_FLAG); + if (parameters == NULL) { + ERROR("Could not create session manager inhibit parameters"); + return; + } + + g_dbus_proxy_call(session_manager_proxy, "Inhibit", parameters, + G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, + screensaver_inhibit_cb, NULL); +} + +void +dbus_screensaver_uninhibit(void) +{ + if (cookie == 0) + return; + DEBUG("uninhibit"); + + GVariant *parameters = g_variant_new("(u)", cookie); + if (parameters == NULL) { + ERROR("Could not create session manager uninhibit " + "parameters"); + return; + } + + g_dbus_proxy_call(session_manager_proxy, "Uninhibit", + g_variant_new("(u)", cookie), + G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, + screensaver_uninhibit_cb, NULL); +} diff --git a/gnome/src/dbus/dbus.h b/gnome/src/dbus/dbus.h index 65987bbba21b47c214ed0fb1c72e6e8357addfc7..2604ba5934afc77ef17059a3aeedd52ac1b7eec5 100644 --- a/gnome/src/dbus/dbus.h +++ b/gnome/src/dbus/dbus.h @@ -123,7 +123,7 @@ GHashTable *dbus_get_account_details(const gchar *accountID); * ConfigurationManager - Set the details of a specific account * @param a The account to update */ -void dbus_set_account_details(account_t *a); +void dbus_set_account_details(const account_t *a); /** * ConfigurationManager - Set the additional credential information @@ -388,6 +388,12 @@ void dbus_add_participant(const gchar *callID, const gchar *confID); */ gchar **dbus_get_participant_list(const gchar *confID); +/** + * If thsi call participate to a conference, return the conference id + * Return an empty string elsewhere + */ +gchar *dbus_get_conference_id(const gchar *callID); + /** * Toggle recording for this instance, may be call or conference */ @@ -561,4 +567,14 @@ gboolean dbus_start_recorded_file_playback(const gchar *); */ void dbus_stop_recorded_file_playback(const gchar *); +/** + * Prevent Gnome Session Manager from entering in screen-saver mode + */ +void dbus_screensaver_inhibit(void); + +/** + * Allow Gnome Session Manager to enter in screen-saver mode + */ +void dbus_screensaver_uninhibit(void); + #endif diff --git a/gnome/src/eel-gconf-extensions.c b/gnome/src/eel-gconf-extensions.c index c1947f24ae8ad3a10529d974a2dbc19e393dc7f7..99be9287350befeb8d8cf2b89aedcebcb6a04bbd 100644 --- a/gnome/src/eel-gconf-extensions.c +++ b/gnome/src/eel-gconf-extensions.c @@ -22,23 +22,22 @@ Authors: Ramiro Estrugo <ramiro@eazel.com> */ -#include <stdlib.h> #include "config.h" +#include <glib/gi18n.h> +#include <stdlib.h> #include "eel-gconf-extensions.h" #include <gconf/gconf-client.h> #include <gconf/gconf.h> #include <gtk/gtk.h> -#include <glib/gi18n.h> +#include <glib.h> static GConfClient *global_gconf_client = NULL; -static void -global_client_free(void) +void eel_gconf_global_client_free(void) { - if (global_gconf_client == NULL) { + if (global_gconf_client == NULL) return; - } g_object_unref(G_OBJECT(global_gconf_client)); global_gconf_client = NULL; @@ -81,10 +80,8 @@ eel_gconf_client_get_global(void) } - if (global_gconf_client == NULL) { + if (global_gconf_client == NULL) global_gconf_client = gconf_client_get_default(); - g_atexit(global_client_free); - } return global_gconf_client; } diff --git a/gnome/src/eel-gconf-extensions.h b/gnome/src/eel-gconf-extensions.h index 0068b15b2f4bf6b35a5f426685c3b67cba5bf12b..e9139477759e3388c84881688bf62edbca1b0001 100644 --- a/gnome/src/eel-gconf-extensions.h +++ b/gnome/src/eel-gconf-extensions.h @@ -25,7 +25,7 @@ #ifndef EEL_GCONF_EXTENSIONS_H #define EEL_GCONF_EXTENSIONS_H -#include <glib/gerror.h> +#include <glib.h> #include <gconf/gconf.h> #include <gconf/gconf-client.h> @@ -57,54 +57,52 @@ BEGIN_EXTERN_C #define EEL_GCONF_UNDEFINED_CONNECTION 0 -GConfClient *eel_gconf_client_get_global (void); -gboolean eel_gconf_handle_error (GError **error); -void eel_gconf_set_boolean (const char *key, - gboolean boolean_value); -gboolean eel_gconf_get_boolean (const char *key); -int eel_gconf_get_integer (const char *key); -void eel_gconf_set_integer (const char *key, - int int_value); -gfloat eel_gconf_get_float (const char *key); -void eel_gconf_set_float (const char *key, - gfloat float_value); -char * eel_gconf_get_string (const char *key); -void eel_gconf_set_string (const char *key, - const char *string_value); -GSList * eel_gconf_get_string_list (const char *key); -void eel_gconf_set_string_list (const char *key, - const GSList *string_list_value); -gboolean eel_gconf_is_default (const char *key); -gboolean eel_gconf_monitor_add (const char *directory); -gboolean eel_gconf_monitor_remove (const char *directory); -void eel_gconf_suggest_sync (void); -GConfValue* eel_gconf_get_value (const char *key); -gboolean eel_gconf_value_is_equal (const GConfValue *a, - const GConfValue *b); -void eel_gconf_set_value (const char *key, - const GConfValue *value); -gboolean eel_gconf_key_exists (const char *key); - -void eel_gconf_value_free (GConfValue *value); -void eel_gconf_unset (const char *key); +GConfClient *eel_gconf_client_get_global(void); + +void eel_gconf_global_client_free(void); + +gboolean eel_gconf_handle_error(GError **error); + +void eel_gconf_set_boolean(const gchar *key, gboolean boolean_value); + +gboolean eel_gconf_get_boolean(const gchar *key); + +int eel_gconf_get_integer(const gchar *key); + +void eel_gconf_set_integer(const gchar *key, gint value); + +gfloat eel_gconf_get_float(const gchar *key); + +void eel_gconf_set_float(const gchar *key, gfloat value); + +gchar *eel_gconf_get_string(const gchar *key); +void eel_gconf_set_string(const gchar *key, const gchar *value); +GSList *eel_gconf_get_string_list (const gchar *key); +void eel_gconf_set_string_list(const gchar *key, const GSList *value); +gboolean eel_gconf_is_default(const gchar *key); +gboolean eel_gconf_monitor_add(const gchar *directory); +gboolean eel_gconf_monitor_remove(const gchar *directory); +void eel_gconf_suggest_sync(void); +GConfValue *eel_gconf_get_value(const gchar *key); +gboolean eel_gconf_value_is_equal(const GConfValue *a, const GConfValue *b); +void eel_gconf_set_value (const gchar *key, const GConfValue *value); +gboolean eel_gconf_key_exists(const gchar *key); +void eel_gconf_value_free(GConfValue *value); +void eel_gconf_unset(const gchar *key); /* Functions which weren't part of the eel-gconf-extensions.h file from eel */ -GSList *eel_gconf_get_integer_list (const char *key); -void eel_gconf_set_integer_list (const char *key, - const GSList *slist); -void gpdf_notification_add (const char *key, - GConfClientNotifyFunc notification_callback, - gpointer callback_data, - GList **notifiers); -void gpdf_notification_remove (GList **notifiers); -guint eel_gconf_notification_add (const char *key, - GConfClientNotifyFunc notification_callback, - gpointer callback_data); -void eel_gconf_notification_remove (guint notification_id); +GSList *eel_gconf_get_integer_list(const gchar *key); +void eel_gconf_set_integer_list(const gchar *key, const GSList *slist); +void gpdf_notification_add(const gchar *key, GConfClientNotifyFunc notification_callback, + gpointer callback_data, GList **notifiers); +void gpdf_notification_remove(GList **notifiers); +guint eel_gconf_notification_add(const gchar *key, + GConfClientNotifyFunc notification_callback, + gpointer callback_data); +void eel_gconf_notification_remove(guint notification_id); #ifdef __cplusplus END_EXTERN_C #endif #endif /* EEL_GCONF_EXTENSIONS_H */ - diff --git a/gnome/src/gtk2_wrappers.c b/gnome/src/gtk2_wrappers.c new file mode 100644 index 0000000000000000000000000000000000000000..72f3bc9559f774bd6a302c4b00ddc09cc1c45018 --- /dev/null +++ b/gnome/src/gtk2_wrappers.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include "gtk2_wrappers.h" +#include "unused.h" + +#if !GTK_CHECK_VERSION(3, 0, 0) + +GtkWidget *gtk_box_new(GtkOrientation orientation, gint spacing) +{ + if (orientation == GTK_ORIENTATION_HORIZONTAL) + return gtk_hbox_new(FALSE, spacing); + else + return gtk_vbox_new(FALSE, spacing); +} + +GtkWidget* gtk_button_box_new(GtkOrientation orientation) +{ + if (orientation == GTK_ORIENTATION_HORIZONTAL) + return gtk_hbutton_box_new(); + else + return gtk_vbutton_box_new(); +} + +void +gtk_widget_get_preferred_size(GtkWidget* widget, GtkRequisition *min_size UNUSED, GtkRequisition *natural_size) +{ + gtk_widget_size_request(widget, natural_size); +} + +GdkPixbuf * +gtk_widget_render_icon_pixbuf(GtkWidget *widget, const gchar *stock_id, GtkIconSize size) +{ + return gtk_widget_render_icon(widget, stock_id, size, NULL); +} + +GtkWidget * +gtk_scale_new_with_range(GtkOrientation orientation, gdouble min, gdouble max, + gdouble step) +{ + if (orientation == GTK_ORIENTATION_HORIZONTAL) + return gtk_hscale_new_with_range(min, max, step); + else + return gtk_vscale_new_with_range(min, max, step); +} + +#endif diff --git a/gnome/src/gtk2_wrappers.h b/gnome/src/gtk2_wrappers.h new file mode 100644 index 0000000000000000000000000000000000000000..6b2d72328f4d3820c596017b6a8a9b1cdbbbd32c --- /dev/null +++ b/gnome/src/gtk2_wrappers.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef BOX_H_ +#define BOX_H_ + +#include <gtk/gtk.h> + +/* Wrappers needed if using gtk2 */ +#if !GTK_CHECK_VERSION(3, 0, 0) +GtkWidget* +gtk_box_new(GtkOrientation orientation, gint spacing); + +GtkWidget* +gtk_button_box_new(GtkOrientation orientation); + +void +gtk_widget_get_preferred_size(GtkWidget* widget, GtkRequisition *min_size, GtkRequisition *natural_size); + +GdkPixbuf * +gtk_widget_render_icon_pixbuf(GtkWidget *widget, const gchar *stock_id, GtkIconSize size); + +GtkWidget * +gtk_scale_new_with_range(GtkOrientation orientation, gdouble min, gdouble max, + gdouble step); + +#endif + +#endif // BOX_H_ diff --git a/gnome/src/imwindow.c b/gnome/src/imwindow.c index d7841631faf03ba3e6d63419bd60e6b08e31e444..0ddd14d135815e1c8ef954ebcff511c3e0fd3406 100644 --- a/gnome/src/imwindow.c +++ b/gnome/src/imwindow.c @@ -30,7 +30,11 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif + +#include "gtk2_wrappers.h" #include "eel-gconf-extensions.h" #include "logger.h" #include "imwindow.h" @@ -41,9 +45,8 @@ #include <sys/stat.h> /** Local variables */ -static GtkWidget *im_window = NULL; -static GtkWidget *im_notebook = NULL; - +static GtkWidget *im_window; +static GtkWidget *im_notebook; static void im_window_init(); diff --git a/gnome/src/logger.h b/gnome/src/logger.h index f196360da9f686cc04d00de4e4cd0bd9b3c9b4e9..849785432e41f04c6b7a17ee6f7f1a07e77cd746 100644 --- a/gnome/src/logger.h +++ b/gnome/src/logger.h @@ -28,8 +28,8 @@ * as that of the covered work. */ -#ifndef __LOGGER_H -#define __LOGGER_H +#ifndef LOGGER_H_ +#define LOGGER_H_ void internal_log (const int level, const char* format, ...); void set_log_level (const int level); @@ -39,9 +39,16 @@ void set_log_level (const int level); #define LOG_INFO 3 #define LOG_DEBUG 4 -#define ERROR(...) internal_log(LOG_ERR, __VA_ARGS__) -#define WARN(...) internal_log(LOG_WARN, __VA_ARGS__) -#define INFO(...) internal_log(LOG_INFO, __VA_ARGS__) -#define DEBUG(...) internal_log(LOG_DEBUG, __VA_ARGS__) +#define INTERNAL_LOG(M, LEVEL, ...) internal_log(LEVEL, "%s:%d: " M, __FILE__, \ + __LINE__, ##__VA_ARGS__) -#endif +#define ERROR(M, ...) INTERNAL_LOG(M, LOG_ERR, ##__VA_ARGS__) +#define WARN(M, ...) INTERNAL_LOG(M, LOG_WARN, ##__VA_ARGS__) +#define INFO(M, ...) INTERNAL_LOG(M, LOG_INFO, ##__VA_ARGS__) +#define DEBUG(M, ...) INTERNAL_LOG(M, LOG_DEBUG, ##__VA_ARGS__) + +/* Prints an error message and returns if the pointer A is NULL */ +#define RETURN_IF_NULL(A, M, ...) \ + if (!(A)) { ERROR(M, ##__VA_ARGS__); return; } + +#endif // LOGGER_H_ diff --git a/gnome/src/main.c b/gnome/src/main.c index 7af50785b836d7f47a8f76828101f664a59b6296..7c5da73a9639c3530c9c79977b22fb5d0c952dd2 100644 --- a/gnome/src/main.c +++ b/gnome/src/main.c @@ -36,6 +36,7 @@ #include "mainwindow.h" #include "statusicon.h" #include "eel-gconf-extensions.h" +#include <glib/gi18n.h> #include <gtk/gtk.h> #include <stdlib.h> @@ -64,7 +65,7 @@ main(int argc, char *argv[]) gtk_init(&argc, &argv); g_print("%s %s\n", PACKAGE, VERSION); - g_print("\nCopyright (c) 2005 - 2011 Savoir-faire Linux Inc.\n\n"); + g_print("\nCopyright (c) 2005 - 2012 Savoir-faire Linux Inc.\n\n"); g_print("This is free software. You may redistribute copies of it under the terms of\n" \ "the GNU General Public License Version 3 <http://www.gnu.org/licenses/gpl.html>.\n" \ "There is NO WARRANTY, to the extent permitted by law.\n\n" \ @@ -85,7 +86,7 @@ main(int argc, char *argv[]) textdomain("sflphone-client-gnome"); if (!sflphone_init(&error)) { - ERROR(error->message); + ERROR("%s", error->message); GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(get_main_window()), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, @@ -111,12 +112,11 @@ main(int argc, char *argv[]) set_minimized(TRUE); } - status_bar_display_account(); sflphone_fill_history(); - sflphone_fill_call_list(); sflphone_fill_conference_list(); + sflphone_fill_call_list(); history_search_init(); // Update the GUI @@ -128,6 +128,7 @@ main(int argc, char *argv[]) shortcuts_destroy_bindings(); + eel_gconf_global_client_free(); OUT: #if !GTK_CHECK_VERSION(2,32,0) gdk_threads_leave(); diff --git a/gnome/src/mainwindow.c b/gnome/src/mainwindow.c index 176d0be62fa6095695e750c8fd9fcdb7384a8fc5..26c3118fa74f9cf75e9ebd89f75b2ad176920d95 100644 --- a/gnome/src/mainwindow.c +++ b/gnome/src/mainwindow.c @@ -30,7 +30,11 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif + +#include "gtk2_wrappers.h" #include "actions.h" #include "dbus.h" #include "calltree.h" @@ -47,9 +51,11 @@ #include "uimanager.h" #include "unused.h" #include "config/audioconf.h" +#include "str_utils.h" #include "eel-gconf-extensions.h" +#include <glib/gi18n.h> #include <sys/stat.h> #include <gtk/gtk.h> @@ -124,6 +130,7 @@ main_window_ask_quit() question = _("There is one call in progress."); else question = _("There are calls in progress."); + DEBUG("Currently %d calls in progress", calllist_get_size(current_calls_tab)); GtkWidget *dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s\n%s", @@ -242,15 +249,21 @@ create_main_window() gtk_box_pack_start(GTK_BOX(vbox), subvbox, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/); + speaker_control = create_slider("speaker"); + mic_control = create_slider("mic"); + g_object_ref(speaker_control); + g_object_ref(mic_control); + if (SHOW_VOLUME) { - speaker_control = create_slider("speaker"); gtk_box_pack_end(GTK_BOX(subvbox), speaker_control, FALSE /*expand*/, - TRUE /*fill*/, 0 /*padding*/); - gtk_widget_show_all(speaker_control); - mic_control = create_slider("mic"); + TRUE /*fill*/, 0 /*padding*/); gtk_box_pack_end(GTK_BOX(subvbox), mic_control, FALSE /*expand*/, TRUE /*fill*/, 0 /*padding*/); + gtk_widget_show_all(speaker_control); gtk_widget_show_all(mic_control); + } else { + gtk_widget_hide(speaker_control); + gtk_widget_hide(mic_control); } if (eel_gconf_get_boolean(CONF_SHOW_DIALPAD)) { @@ -315,11 +328,11 @@ void main_window_volume_controls(gboolean state) { if (state) { - speaker_control = create_slider("speaker"); + // speaker_control = create_slider("speaker"); gtk_box_pack_end(GTK_BOX(subvbox), speaker_control, FALSE /*expand*/, TRUE /*fill*/, 0 /*padding*/); gtk_widget_show_all(speaker_control); - mic_control = create_slider("mic"); + // mic_control = create_slider("mic"); gtk_box_pack_end(GTK_BOX(subvbox), mic_control, FALSE /*expand*/, TRUE /*fill*/, 0 /*padding*/); gtk_widget_show_all(mic_control); @@ -393,22 +406,22 @@ main_window_zrtp_not_supported(callable_obj_t * c) { gchar* warning_enabled = ""; - account_t *account_details = account_list_get_by_id(c->_accountID); + account_t *account = account_list_get_by_id(c->_accountID); - if (account_details != NULL) { - warning_enabled = g_hash_table_lookup(account_details->properties, - ACCOUNT_ZRTP_NOT_SUPP_WARNING); + if (account != NULL) { + warning_enabled = account_lookup(account, + ACCOUNT_ZRTP_NOT_SUPP_WARNING); DEBUG("Warning Enabled %s", warning_enabled); } else { DEBUG("Account is null callID %s", c->_callID); GHashTable * properties = sflphone_get_ip2ip_properties(); if (properties) - warning_enabled = g_hash_table_lookup (properties, - ACCOUNT_ZRTP_NOT_SUPP_WARNING); + warning_enabled = g_hash_table_lookup(properties, + ACCOUNT_ZRTP_NOT_SUPP_WARNING); } - if (g_strcasecmp(warning_enabled, "true") == 0) { + if (utf8_case_equal(warning_enabled, "true")) { PidginMiniDialog *mini_dialog; gchar *desc = g_markup_printf_escaped( _("ZRTP is not supported by peer %s\n"), c->_peer_number); diff --git a/gnome/src/sflnotify.c b/gnome/src/sflnotify.c index 8dd5ed0f0fdb58e1d57cb23f02ca5ab41776e1bc..7f8c19a9c1d0644b89ae61153a8840b70a2199f0 100644 --- a/gnome/src/sflnotify.c +++ b/gnome/src/sflnotify.c @@ -29,6 +29,9 @@ */ #include "config.h" +#include <glib.h> +#include <glib/gi18n.h> +#include "str_utils.h" #include "eel-gconf-extensions.h" #include "sflnotify.h" #include "logger.h" @@ -87,7 +90,7 @@ notify_incoming_message(const gchar *callID, const gchar *msg) create_new_gnome_notification(title, (gchar *)msg, NOTIFY_URGENCY_CRITICAL, - (g_strcasecmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -110,7 +113,7 @@ notify_incoming_call(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (g_strcasecmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -182,7 +185,7 @@ notify_secure_on(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (g_strcasecmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -195,7 +198,7 @@ notify_zrtp_not_supported(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (g_strcasecmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -208,7 +211,7 @@ notify_zrtp_negotiation_failed(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (g_strcasecmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -221,6 +224,6 @@ notify_secure_off(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (g_strcasecmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } diff --git a/gnome/src/sflphone_const.h b/gnome/src/sflphone_const.h index fd7cec91d20a169620047955d07a11c3451d739d..728b60dce5577922e0eef6fb4274a417dbcfd385 100644 --- a/gnome/src/sflphone_const.h +++ b/gnome/src/sflphone_const.h @@ -32,7 +32,7 @@ #define __SFLPHONE_CONST_H #include <libintl.h> -#include <glib/gi18n.h> +#include <glib.h> /* @file sflphone_const.h * @brief Contains the global variables for the client code @@ -48,31 +48,30 @@ #define CONTACTS "contacts" /** Locale */ -//#define _(STRING) gettext( STRING ) -//#define N_(STRING) (STRING) #define c_(COMMENT,STRING) gettext(STRING) #define n_(SING,PLUR,COUNT) ngettext(SING,PLUR,COUNT) -#define IP2IP "IP2IP" - #define IP2IP_PROFILE "IP2IP" #define ACCOUNT_ID "Account.id" #define ACCOUNT_TYPE "Account.type" -#define ACCOUNT_ALIAS "Account.alias" -#define ACCOUNT_ENABLED "Account.enable" -#define ACCOUNT_MAILBOX "Account.mailbox" -#define ACCOUNT_USERAGENT "useragent" -#define ACCOUNT_RESOLVE_ONCE "Account.resolveOnce" -#define ACCOUNT_REGISTRATION_EXPIRE "Account.expire" -#define ACCOUNT_SIP_STUN_SERVER "STUN.server" +#define ACCOUNT_ALIAS "Account.alias" +#define ACCOUNT_ENABLED "Account.enable" +#define ACCOUNT_MAILBOX "Account.mailbox" +#define ACCOUNT_USERAGENT "Account.useragent" +#define ACCOUNT_REGISTRATION_EXPIRE "Account.registrationExpire" +#define ACCOUNT_REGISTRATION_STATUS "Account.registrationStatus" +#define ACCOUNT_REGISTRATION_STATE_CODE "Account.registrationCode" +#define ACCOUNT_REGISTRATION_STATE_DESC "Account.registrationDescription" + +#define ACCOUNT_SIP_STUN_SERVER "STUN.server" #define ACCOUNT_SIP_STUN_ENABLED "STUN.enable" #define ACCOUNT_DTMF_TYPE "Account.dtmfType" -#define ACCOUNT_HOSTNAME "hostname" -#define ACCOUNT_USERNAME "username" -#define ACCOUNT_ROUTE "routeset" -#define ACCOUNT_PASSWORD "password" -#define ACCOUNT_REALM "realm" +#define ACCOUNT_HOSTNAME "Account.hostname" +#define ACCOUNT_USERNAME "Account.username" +#define ACCOUNT_ROUTE "Account.routeset" +#define ACCOUNT_PASSWORD "Account.password" +#define ACCOUNT_REALM "Account.realm" #define ACCOUNT_KEY_EXCHANGE "SRTP.keyExchange" #define ACCOUNT_SRTP_ENABLED "SRTP.enable" #define ACCOUNT_SRTP_RTP_FALLBACK "SRTP.rtpFallback" @@ -84,45 +83,41 @@ #define ZRTP "zrtp" #define SDES "sdes" -#define CONFIG_RINGTONE_PATH "Account.ringtonePath" -#define CONFIG_RINGTONE_ENABLED "Account.ringtoneEnabled" - -#define TLS_LISTENER_PORT "TLS.listenerPort" -#define TLS_ENABLE "TLS.enable" -#define TLS_PORT "TLS.port" -#define TLS_CA_LIST_FILE "TLS.certificateListFile" -#define TLS_CERTIFICATE_FILE "TLS.certificateFile" -#define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" -#define TLS_PASSWORD "TLS.password" -#define TLS_METHOD "TLS.method" -#define TLS_CIPHERS "TLS.ciphers" -#define TLS_SERVER_NAME "TLS.serverName" -#define TLS_VERIFY_SERVER "TLS.verifyServer" -#define TLS_VERIFY_CLIENT "TLS.verifyClient" -#define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" -#define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" -#define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" - -#define LOCAL_INTERFACE "Account.localInterface" -#define PUBLISHED_SAMEAS_LOCAL "Account.publishedSameAsLocal" -#define LOCAL_PORT "Account.localPort" -#define PUBLISHED_PORT "Account.publishedPort" -#define PUBLISHED_ADDRESS "Account.publishedAddress" - -#define REGISTRATION_STATUS "Status" -#define REGISTRATION_STATE_CODE "Registration.code" -#define REGISTRATION_STATE_DESCRIPTION "Registration.description" - -#define SHORTCUT_PICKUP "pickUp" -#define SHORTCUT_HANGUP "hangUp" -#define SHORTCUT_POPUP "popupWindow" -#define SHORTCUT_TOGGLEPICKUPHANGUP "togglePickupHangup" -#define SHORTCUT_TOGGLEHOLD "toggleHold" +#define CONFIG_RINGTONE_PATH "Account.ringtonePath" +#define CONFIG_RINGTONE_ENABLED "Account.ringtoneEnabled" + +#define TLS_LISTENER_PORT "TLS.listenerPort" +#define TLS_ENABLE "TLS.enable" +#define TLS_PORT "TLS.port" +#define TLS_CA_LIST_FILE "TLS.certificateListFile" +#define TLS_CERTIFICATE_FILE "TLS.certificateFile" +#define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" +#define TLS_PASSWORD "TLS.password" +#define TLS_METHOD "TLS.method" +#define TLS_CIPHERS "TLS.ciphers" +#define TLS_SERVER_NAME "TLS.serverName" +#define TLS_VERIFY_SERVER "TLS.verifyServer" +#define TLS_VERIFY_CLIENT "TLS.verifyClient" +#define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" +#define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" +#define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" + +#define LOCAL_INTERFACE "Account.localInterface" +#define PUBLISHED_SAMEAS_LOCAL "Account.publishedSameAsLocal" +#define LOCAL_PORT "Account.localPort" +#define PUBLISHED_PORT "Account.publishedPort" +#define PUBLISHED_ADDRESS "Account.publishedAddress" + +#define SHORTCUT_PICKUP "pickUp" +#define SHORTCUT_HANGUP "hangUp" +#define SHORTCUT_POPUP "popupWindow" +#define SHORTCUT_TOGGLEPICKUPHANGUP "togglePickupHangup" +#define SHORTCUT_TOGGLEHOLD "toggleHold" /** Error while opening capture device */ -#define ALSA_CAPTURE_DEVICE 0x0001 +#define ALSA_CAPTURE_DEVICE 0x0001 /** Error while opening playback device */ -#define ALSA_PLAYBACK_DEVICE 0x0010 +#define ALSA_PLAYBACK_DEVICE 0x0010 /** Error pulseaudio */ #define PULSEAUDIO_NOT_RUNNING 0x0100 /** Error codecs not loaded */ @@ -136,11 +131,11 @@ /** Tone to play when voice mails */ #define TONE_WITH_MESSAGE 1 /** Tells if the main window is reduced to the system tray or not */ -#define MINIMIZED TRUE +#define MINIMIZED TRUE /** Behaviour of the main window on incoming calls */ #define __POPUP_WINDOW (eel_gconf_get_integer (POPUP_ON_CALL)) /** Show/Hide the volume controls */ -#define SHOW_VOLUME (eel_gconf_get_integer (SHOW_VOLUME_CONTROLS) && must_show_alsa_conf()) +#define SHOW_VOLUME (eel_gconf_get_integer (SHOW_VOLUME_CONTROLS) && must_show_alsa_conf()) /** DTMF type */ #define OVERRTP "overrtp" @@ -154,7 +149,7 @@ /** Messages ID for the status bar - Incoming calls */ #define __MSG_INCOMING_CALL 0 /** Messages ID for the status bar - Calling */ -#define __MSG_CALLING 1 +#define __MSG_CALLING 1 /** Messages ID for the status bar - Voice mails notification */ #define __MSG_VOICE_MAILS 2 /** Messages ID for the status bar - Current account */ diff --git a/gnome/src/sliders.c b/gnome/src/sliders.c index 38e901a2d9dcbcf838faa0133fa77b84fcc33ab9..3ef545eb139b4c17aa4511c0649f8cf610b9f7ab 100644 --- a/gnome/src/sliders.c +++ b/gnome/src/sliders.c @@ -28,6 +28,8 @@ * as that of the covered work. */ +#include <glib/gi18n.h> +#include "gtk2_wrappers.h" #include "sliders.h" #include "dbus/dbus.h" #include "actions.h" @@ -41,22 +43,25 @@ static GtkWidget * button[2]; // icons static GtkWidget * images[2][4]; + enum device_t { - SPEAKER = 0, - MIKE, + DEVICE_SPEAKER = 0, + DEVICE_MIC, DEVICE_COUNT -} ; +}; enum volume_t { MUTED = 0, VOL25, VOL50, VOL75 -} ; +}; static guint toggledConnId[2]; // The button toggled signal connection ID static guint movedConnId[2]; // The slider_moved signal connection ID +static guint device_state = DEVICE_STATE_ACTIVE; + void update_icons(int dev) { @@ -86,20 +91,20 @@ slider_moved(GtkRange* range, gchar* device) dbus_set_volume(device, slider_value); if (g_strcmp0(device, "speaker") == 0) - update_icons(SPEAKER); + update_icons(DEVICE_SPEAKER); else - update_icons(MIKE); + update_icons(DEVICE_MIC); } -static void +void mute_cb(GtkWidget *widget, gchar* device) { int dev; if (g_strcmp0(device, "speaker") == 0) - dev = SPEAKER; + dev = DEVICE_SPEAKER; else - dev = MIKE; + dev = DEVICE_MIC; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { // Save value DEBUG("Save"); @@ -113,15 +118,46 @@ mute_cb(GtkWidget *widget, gchar* device) update_icons(dev); } -void -set_slider(const gchar * device, gdouble newval) +void set_slider_value(const gchar *device, gdouble newval) { - int dev; + int dev = 0; - if (g_strcmp0(device, "speaker") == 0) - dev = SPEAKER; - else - dev = MIKE; + if (g_strcmp0(device, "speaker") == 0) { + dev = DEVICE_SPEAKER; + DEBUG("Set value for speaker: %f\n", newval); + } + else if (g_strcmp0(device, "mic") == 0) { + dev = DEVICE_MIC; + DEBUG("Set value for mic: %f\n", newval); + } + else { + ERROR("Unknown device: %s", device); + return; + } + + gtk_range_set_value(GTK_RANGE(slider[dev]), newval); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button[dev]), (newval == 0 ? TRUE: FALSE)); + + update_icons(dev); +} + +void set_slider_no_update (const gchar * device, gdouble newval) +{ + int dev = 0; + + if (g_strcmp0(device, "speaker") == 0) { + dev = DEVICE_SPEAKER; + DEBUG("Set value no update for speaker: %f\n", newval); + } + else if (g_strcmp0(device, "mic") == 0) { + dev = DEVICE_MIC; + DEBUG("Set value no update for mic: %f\n", newval); + } + else { + ERROR("Unknown device: %s", device); + return; + } g_signal_handler_block(G_OBJECT(slider[dev]), movedConnId[dev]); gtk_range_set_value(GTK_RANGE(slider[dev]), newval); @@ -134,6 +170,29 @@ set_slider(const gchar * device, gdouble newval) update_icons(dev); } +void toggle_slider_mute_microphone(void) +{ + switch(device_state) { + case DEVICE_STATE_ACTIVE: + value[DEVICE_MIC] = gtk_range_get_value(GTK_RANGE(slider[DEVICE_MIC])); + dbus_set_volume("mic", 0.0); + device_state = DEVICE_STATE_MUTED; + break; + case DEVICE_STATE_MUTED: + dbus_set_volume("mic", value[DEVICE_MIC]); + device_state = DEVICE_STATE_ACTIVE; + break; + default: + ERROR("Unknown state"); + break; + } +} + +guint get_mute_unmute_audio_state(void) +{ + return device_state; +} + /** Generates the speaker slider and mute button */ GtkWidget * create_slider(const gchar * device) @@ -146,25 +205,25 @@ create_slider(const gchar * device) int dev=0; if (g_strcmp0(device, "speaker") == 0) { - dev = SPEAKER; - images[SPEAKER][MUTED] = gtk_image_new_from_file(ICONS_DIR "/speaker.svg"); - images[SPEAKER][VOL25] = gtk_image_new_from_file(ICONS_DIR "/speaker_25.svg"); - images[SPEAKER][VOL50] = gtk_image_new_from_file(ICONS_DIR "/speaker_50.svg"); - images[SPEAKER][VOL75] = gtk_image_new_from_file(ICONS_DIR "/speaker_75.svg"); - g_object_ref(images[SPEAKER][MUTED]); - g_object_ref(images[SPEAKER][VOL25]); - g_object_ref(images[SPEAKER][VOL50]); - g_object_ref(images[SPEAKER][VOL75]); + dev = DEVICE_SPEAKER; + images[DEVICE_SPEAKER][MUTED] = gtk_image_new_from_file(ICONS_DIR "/speaker.svg"); + images[DEVICE_SPEAKER][VOL25] = gtk_image_new_from_file(ICONS_DIR "/speaker_25.svg"); + images[DEVICE_SPEAKER][VOL50] = gtk_image_new_from_file(ICONS_DIR "/speaker_50.svg"); + images[DEVICE_SPEAKER][VOL75] = gtk_image_new_from_file(ICONS_DIR "/speaker_75.svg"); + g_object_ref(images[DEVICE_SPEAKER][MUTED]); + g_object_ref(images[DEVICE_SPEAKER][VOL25]); + g_object_ref(images[DEVICE_SPEAKER][VOL50]); + g_object_ref(images[DEVICE_SPEAKER][VOL75]); } else if (g_strcmp0(device, "mic") == 0) { - dev = MIKE; - images[MIKE][MUTED] = gtk_image_new_from_file(ICONS_DIR "/mic.svg"); - images[MIKE][VOL25] = gtk_image_new_from_file(ICONS_DIR "/mic_25.svg"); - images[MIKE][VOL50] = gtk_image_new_from_file(ICONS_DIR "/mic_50.svg"); - images[MIKE][VOL75] = gtk_image_new_from_file(ICONS_DIR "/mic_75.svg"); - g_object_ref(images[MIKE][MUTED]); - g_object_ref(images[MIKE][VOL25]); - g_object_ref(images[MIKE][VOL50]); - g_object_ref(images[MIKE][VOL75]); + dev = DEVICE_MIC; + images[DEVICE_MIC][MUTED] = gtk_image_new_from_file(ICONS_DIR "/mic.svg"); + images[DEVICE_MIC][VOL25] = gtk_image_new_from_file(ICONS_DIR "/mic_25.svg"); + images[DEVICE_MIC][VOL50] = gtk_image_new_from_file(ICONS_DIR "/mic_50.svg"); + images[DEVICE_MIC][VOL75] = gtk_image_new_from_file(ICONS_DIR "/mic_75.svg"); + g_object_ref(images[DEVICE_MIC][MUTED]); + g_object_ref(images[DEVICE_MIC][VOL25]); + g_object_ref(images[DEVICE_MIC][VOL50]); + g_object_ref(images[DEVICE_MIC][VOL75]); } ret = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5 /*spacing*/); @@ -185,7 +244,7 @@ create_slider(const gchar * device) G_CALLBACK(slider_moved), (gpointer) device); gtk_box_pack_start(GTK_BOX(ret), slider[dev], TRUE /*expand*/, TRUE /*fill*/, 0 /*padding*/); - set_slider(device, dbus_get_volume(device)); + set_slider_no_update(device, dbus_get_volume(device)); return ret; } diff --git a/gnome/src/sliders.h b/gnome/src/sliders.h index 738522c5847c010cba93ec5f249265e58a582d7a..dd48f8f85d464c27587112b429a4dfc3da88adeb 100644 --- a/gnome/src/sliders.h +++ b/gnome/src/sliders.h @@ -36,6 +36,12 @@ * @brief Volume sliders at the bottom of the main window. */ +enum device_state_t { + DEVICE_STATE_MUTED = 0, + DEVICE_STATE_ACTIVE, + DEVICE_STATE_COUNT +}; + /** * Build the sliders widget * @param device Mic or speaker @@ -43,6 +49,12 @@ */ GtkWidget * create_slider (const gchar * device); +/** + * Update the sliders sending the value to the server + * @param device The device slider to update + * @param value The value to set [0, 1.0] + */ +void set_slider_value(const gchar *device, gdouble value); /** * This function updates the sliders without sending the value to the server. @@ -51,6 +63,16 @@ GtkWidget * create_slider (const gchar * device); * @param device The device slider to update {speaker, mic} * @param value The value to set [0, 1.0] */ -void set_slider (const gchar * device, gdouble value); +void set_slider_no_update (const gchar * device, gdouble value); + +/** + * Mute the audio device setting the sliders to 0 + */ +void toggle_slider_mute_microphone(void); + +/** + * Returns the mute/unmute state + */ +guint get_mute_unmute_state(void); #endif diff --git a/gnome/src/statusicon.c b/gnome/src/statusicon.c index 2fe79ee9b61e5735d3aaf8f655dede4448c16107..b94864c3f0e73f97bac5d72f7e11ad25b683745e 100644 --- a/gnome/src/statusicon.c +++ b/gnome/src/statusicon.c @@ -29,6 +29,7 @@ * as that of the covered work. */ +#include <glib/gi18n.h> #include <gtk/gtk.h> #include "actions.h" #include "mainwindow.h" diff --git a/gnome/src/str_utils.c b/gnome/src/str_utils.c new file mode 100644 index 0000000000000000000000000000000000000000..2bbff79e159340e71fd2f65e888802d2d6cc8167 --- /dev/null +++ b/gnome/src/str_utils.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include "str_utils.h" + +gint utf8_case_cmp(const gchar *a, const gchar *b) +{ + gchar *l = g_utf8_casefold(a, -1); + gchar *r = g_utf8_casefold(b, -1); + gint result = g_utf8_collate(l, r); + g_free(l); + g_free(r); + return result; +} + +gboolean utf8_case_equal(const gchar *a, const gchar *b) +{ + if (a == NULL) { + if (b == NULL) + return TRUE; + else + return FALSE; + } else + return utf8_case_cmp(a, b) == 0; +} diff --git a/daemon/test/ringtonetest.cpp b/gnome/src/str_utils.h similarity index 71% rename from daemon/test/ringtonetest.cpp rename to gnome/src/str_utils.h index eaa0e90833a72162131407a83a58639de6ef60b6..bc9f7cc2780bc1e6f2410f699c3fe8e5d5c9e217 100644 --- a/daemon/test/ringtonetest.cpp +++ b/gnome/src/str_utils.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Savoir-Faire Linux Inc. - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,21 +28,15 @@ * as that of the covered work. */ -#include "ringtonetest.h" +#ifndef STR_UTILS_H_ +#define STR_UTILS_H_ -void RingtoneTest::testLoadWavefile() -{ - WavFile *wav = new WavFile(); +#include <glib.h> - // Test initial values - CPPUNIT_ASSERT(wav->isStarted() == false); - CPPUNIT_ASSERT(wav->getSize() == 0); +/* Case independent, local independent string comparison test */ +gint utf8_case_cmp(const gchar *a, const gchar *b); - // Test protection against wrong file name - CPPUNIT_ASSERT(wav->loadFile(std::string("wrongfilename.wav"), NULL, 44100) == false); +/* Case independent, local independent string equality test, NULL-safe */ +gint utf8_case_equal(const gchar *a, const gchar *b); - - - delete wav; - wav = NULL; -} +#endif /* STR_UTILS_H_ */ diff --git a/gnome/src/ui.xml b/gnome/src/ui.xml index 52058b4947b5fea98095d8f4f8435b447dcd0be8..6dadc1bd3e4dcf8e1ba12b5974e64afdd1251601 100644 --- a/gnome/src/ui.xml +++ b/gnome/src/ui.xml @@ -8,6 +8,7 @@ <menuitem name="OnHoldMenu" action="OnHold"/> <menuitem action="InstantMessaging"/> <menuitem action="Record"/> + <menuitem action="Mute"/> <separator/> <menuitem action="AccountAssistant"/> <separator/> @@ -49,8 +50,10 @@ <toolitem name="TransferToolbar" action="Transfer"/> <toolitem name="InstantMessagingToolbar" action="InstantMessaging"/> <toolitem name="RecordToolbar" action="Record"/> + <toolitem name="MuteToolbar" action="Mute"/> <!-- FIXME: commented out because it is responsible for #7495 --> <!-- separator/--> + <toolitem name="VoicemailToolbar" action="Voicemail"/> <toolitem name="HistoryToolbar" action="History"/> <toolitem name="StartPlaybackRecordToolbar" action="StartPlaybackRecord"/> diff --git a/gnome/src/uimanager.c b/gnome/src/uimanager.c index 3145a55ca6d2c1ec5e250e13747d5ea181557459..02768a7a8bd3e9ac64d54f3069fe538e6df2d8db 100644 --- a/gnome/src/uimanager.c +++ b/gnome/src/uimanager.c @@ -28,15 +28,21 @@ * as that of the covered work. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif + +#include "gtk2_wrappers.h" +#include "str_utils.h" #include "preferencesdialog.h" #include "logger.h" #include "dbus/dbus.h" #include "mainwindow.h" #include "assistant.h" +#include <glib.h> +#include <glib/gi18n.h> #include <gtk/gtk.h> #include <string.h> -#include <glib/gprintf.h> #include "uimanager.h" #include "statusicon.h" @@ -59,31 +65,39 @@ #include <sys/stat.h> +#include <sliders.h> + void show_edit_number(callable_obj_t *call); static GtkWidget *toolbar_; -static guint transferButtonConnId_; //The button toggled signal connection ID -static guint recordButtonConnId_; //The button toggled signal connection ID +// store the signal ID in case we need to +// intercept this signal +static guint transferButtonConnId_; +static guint recordButtonConnId_; static GtkAction * pickUpAction_; -static GtkWidget * pickUpWidget_; static GtkAction * newCallAction_; -static GtkWidget * newCallWidget_; static GtkAction * hangUpAction_; +static GtkAction * copyAction_; +static GtkAction * pasteAction_; +static GtkAction * recordAction_; +static GtkAction * muteAction_; +static GtkAction * voicemailAction_; +static GtkAction * imAction_; + +static GtkWidget * pickUpWidget_; +static GtkWidget * newCallWidget_; static GtkWidget * hangUpWidget_; static GtkWidget * holdMenu_; static GtkWidget * holdToolbar_; static GtkWidget * offHoldToolbar_; static GtkWidget * transferToolbar_; -static GtkAction * copyAction_; -static GtkAction * pasteAction_; -static GtkAction * recordAction_; static GtkWidget * recordWidget_; -static GtkAction * voicemailAction_; +static GtkWidget * muteWidget_; static GtkWidget * voicemailToolbar_; static GtkWidget * imToolbar_; -static GtkAction * imAction_; + static GtkWidget * playRecordWidget_; static GtkWidget * stopRecordWidget_; @@ -117,68 +131,355 @@ static void add_to_toolbar(GtkWidget *toolbar, GtkWidget *item, int pos) gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), pos); } +static void +call_mute(void) +{ + DEBUG("Mute call button pressed"); + sflphone_mute_call(); +} + + +static void +update_toolbar_for_call(callable_obj_t *selectedCall, gboolean instant_messaging_enabled) { + int pos = 0; + + DEBUG("Update actions for call %s", selectedCall->_callID); + + if(selectedCall == NULL) { + ERROR("Selected call is NULL while updating toolbar"); + return; + } + + // update icon in systray + show_status_hangup_icon(); + + gtk_action_set_sensitive(copyAction_, TRUE); + + switch (selectedCall->_state) { + case CALL_STATE_INCOMING: + { + DEBUG("Call State Incoming"); + // Make the button toolbar clickable + gtk_action_set_sensitive(pickUpAction_, TRUE); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + // Replace the dial button with the hangup button + g_object_ref(newCallWidget_); + remove_from_toolbar(newCallWidget_); + pos = 0; + add_to_toolbar(toolbar_, pickUpWidget_, pos++); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + case CALL_STATE_HOLD: + { + DEBUG("Call State Hold"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(offHoldToolbar_, TRUE); + gtk_widget_set_sensitive(newCallWidget_, TRUE); + + // Replace the hold button with the off-hold button + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, offHoldToolbar_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos++); + } + + break; + } + case CALL_STATE_RINGING: + { + DEBUG("Call State Ringing"); + gtk_action_set_sensitive(pickUpAction_, TRUE); + gtk_action_set_sensitive(hangUpAction_, TRUE); + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + case CALL_STATE_DIALING: + { + DEBUG("Call State Dialing"); + gtk_action_set_sensitive(pickUpAction_, TRUE); + + if (active_calltree_tab == current_calls_tab) + gtk_action_set_sensitive(hangUpAction_, TRUE); + + g_object_ref(newCallWidget_); + remove_from_toolbar(newCallWidget_); + pos = 0; + add_to_toolbar(toolbar_, pickUpWidget_, pos++); + + if (active_calltree_tab == current_calls_tab) + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + else if (active_calltree_tab == history_tab) { + if (is_non_empty(selectedCall->_recordfile)) { + if (selectedCall->_record_is_playing) + add_to_toolbar(toolbar_, stopRecordWidget_, pos++); + else + add_to_toolbar(toolbar_, playRecordWidget_, pos++); + } + } + break; + } + case CALL_STATE_CURRENT: + { + DEBUG("Call State Current"); + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + g_signal_handler_block(recordWidget_, recordButtonConnId_); + + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + if (instant_messaging_enabled) + gtk_action_set_sensitive(imAction_, TRUE); + + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + if (instant_messaging_enabled) { + add_to_toolbar(toolbar_, imToolbar_, pos++); + + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE); + + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + break; + } + + case CALL_STATE_RECORD: + { + DEBUG("Call State Record"); + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + g_signal_handler_block(recordWidget_, recordButtonConnId_); + + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + if (instant_messaging_enabled) + gtk_action_set_sensitive(imAction_, TRUE); + + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + if (instant_messaging_enabled) + add_to_toolbar(toolbar_, imToolbar_, pos++); + + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE); + + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + break; + } + case CALL_STATE_BUSY: + case CALL_STATE_FAILURE: + { + pos = 1; + DEBUG("Call State Busy/Failure"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + break; + } + case CALL_STATE_TRANSFER: + { + pos = 1; + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE); + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + default: + ERROR("Unknown state in action update!"); + break; + } + } +} + +static void +update_toolbar_for_conference(conference_obj_t * selectedConf, gboolean instant_messaging_enabled) { + int pos = 0; + + DEBUG("Update actions for conference"); + + // update icon in systray + show_status_hangup_icon(); + + switch (selectedConf->_state) { + + case CONFERENCE_STATE_ACTIVE_ATTACHED: + case CONFERENCE_STATE_ACTIVE_DETACHED: + DEBUG("Conference State Active"); + g_signal_handler_block(recordWidget_, recordButtonConnId_); + if (active_calltree_tab == current_calls_tab) { + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(recordWidget_, TRUE); + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + } else if (active_calltree_tab == history_tab) { + if (is_non_empty(selectedConf->_recordfile)) { + pos = 2; + if (selectedConf->_record_is_playing) + add_to_toolbar(toolbar_, stopRecordWidget_, pos); + else + add_to_toolbar(toolbar_, playRecordWidget_, pos); + } + } + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + break; + case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD: + case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: { + g_signal_handler_block(recordWidget_, recordButtonConnId_); + pos = 1; + DEBUG("Conference State Record"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(recordWidget_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + break; + } + case CONFERENCE_STATE_HOLD: + case CONFERENCE_STATE_HOLD_RECORD: { + DEBUG("Conference State Hold"); + g_signal_handler_block(recordWidget_, recordButtonConnId_); + pos = 1; + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(offHoldToolbar_, TRUE); + gtk_widget_set_sensitive(recordWidget_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, offHoldToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + + break; + } + default: + WARN("Should not happen in action update!"); + break; + } + +} + void update_actions() { gtk_action_set_sensitive(newCallAction_, TRUE); gtk_action_set_sensitive(pickUpAction_, FALSE); gtk_action_set_sensitive(hangUpAction_, FALSE); + gtk_action_set_sensitive(recordAction_, FALSE); + gtk_action_set_sensitive(muteAction_, FALSE); + gtk_action_set_sensitive(copyAction_, FALSE); gtk_action_set_sensitive(imAction_, FALSE); + gtk_widget_set_sensitive(holdMenu_, FALSE); + gtk_widget_set_sensitive(holdToolbar_, FALSE); + gtk_widget_set_sensitive(offHoldToolbar_, FALSE); + gtk_widget_set_sensitive(recordWidget_, FALSE); + gtk_widget_set_sensitive(muteWidget_, FALSE); + gtk_widget_set_sensitive(historyButton_, FALSE); + + // Increment the reference counter g_object_ref(hangUpWidget_); g_object_ref(recordWidget_); + g_object_ref(muteWidget_); g_object_ref(holdToolbar_); g_object_ref(offHoldToolbar_); - - if (addrbook) - g_object_ref(contactButton_); - g_object_ref(historyButton_); g_object_ref(transferToolbar_); g_object_ref(voicemailToolbar_); g_object_ref(imToolbar_); + if (addrbook) + g_object_ref(contactButton_); + + // Make sure the toolbar is reinitialized + // Widget will be added according to the state + // of the selected call remove_from_toolbar(hangUpWidget_); remove_from_toolbar(recordWidget_); + remove_from_toolbar(muteWidget_); remove_from_toolbar(transferToolbar_); remove_from_toolbar(historyButton_); - - if (addrbook) - remove_from_toolbar(contactButton_); - remove_from_toolbar(voicemailToolbar_); remove_from_toolbar(imToolbar_); - - gtk_widget_set_sensitive(holdMenu_, FALSE); - gtk_widget_set_sensitive(holdToolbar_, FALSE); - gtk_widget_set_sensitive(offHoldToolbar_, FALSE); - gtk_action_set_sensitive(recordAction_, FALSE); - gtk_widget_set_sensitive(recordWidget_, FALSE); - gtk_action_set_sensitive(copyAction_, FALSE); - - if (addrbook) - gtk_widget_set_sensitive(contactButton_, FALSE); - - gtk_widget_set_sensitive(historyButton_, FALSE); - - if (addrbook) - gtk_widget_set_tooltip_text(contactButton_, _("No address book selected")); - remove_from_toolbar(holdToolbar_); remove_from_toolbar(offHoldToolbar_); remove_from_toolbar(newCallWidget_); remove_from_toolbar(pickUpWidget_); - - add_to_toolbar(toolbar_, newCallWidget_, 0); - remove_from_toolbar(playRecordWidget_); remove_from_toolbar(stopRecordWidget_); + if (addrbook) { + remove_from_toolbar(contactButton_); + gtk_widget_set_sensitive(contactButton_, FALSE); + gtk_widget_set_tooltip_text(contactButton_, _("No address book selected")); + } + + // New call widget always present + add_to_toolbar(toolbar_, newCallWidget_, 0); + + // Add the history button and set it to sensitive if enabled if (eel_gconf_get_integer(HISTORY_ENABLED)) { add_to_toolbar(toolbar_, historyButton_, -1); gtk_widget_set_sensitive(historyButton_, TRUE); } + GtkToolItem *separator = gtk_separator_tool_item_new(); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), separator, -1); + + // If addressbook support has been enabled and all addressbooks are loaded, display the icon if (addrbook && addrbook->is_ready() && addressbook_config_load_parameters()->enable) { add_to_toolbar(toolbar_, contactButton_, -1); @@ -199,241 +500,9 @@ update_actions() instant_messaging_enabled = eel_gconf_get_integer(INSTANT_MESSAGING_ENABLED); if (selectedCall) { - DEBUG("UIManager: Update actions for call %s", selectedCall->_callID); - - // update icon in systray - show_status_hangup_icon(); - - gtk_action_set_sensitive(copyAction_, TRUE); - - switch (selectedCall->_state) { - case CALL_STATE_INCOMING: - { - DEBUG("UIManager: Call State Incoming"); - // Make the button toolbar clickable - gtk_action_set_sensitive(pickUpAction_, TRUE); - gtk_action_set_sensitive(hangUpAction_, TRUE); - // Replace the dial button with the hangup button - g_object_ref(newCallWidget_); - remove_from_toolbar(newCallWidget_); - int pos = 0; - add_to_toolbar(toolbar_, pickUpWidget_, pos++); - add_to_toolbar(toolbar_, hangUpWidget_, pos); - break; - } - case CALL_STATE_HOLD: - { - DEBUG("UIManager: Call State Hold"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(offHoldToolbar_, TRUE); - gtk_widget_set_sensitive(newCallWidget_, TRUE); - - // Replace the hold button with the off-hold button - int pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, offHoldToolbar_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - case CALL_STATE_RINGING: - { - DEBUG("UIManager: Call State Ringing"); - gtk_action_set_sensitive(pickUpAction_, TRUE); - gtk_action_set_sensitive(hangUpAction_, TRUE); - int pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos); - break; - } - case CALL_STATE_DIALING: - { - DEBUG("UIManager: Call State Dialing"); - gtk_action_set_sensitive(pickUpAction_, TRUE); - - if (active_calltree_tab == current_calls_tab) - gtk_action_set_sensitive(hangUpAction_, TRUE); - - g_object_ref(newCallWidget_); - remove_from_toolbar(newCallWidget_); - int pos = 0; - add_to_toolbar(toolbar_, pickUpWidget_, pos++); - - if (active_calltree_tab == current_calls_tab) - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - else if (active_calltree_tab == history_tab) { - if (is_non_empty(selectedCall->_recordfile)) { - if (selectedCall->_record_is_playing) - add_to_toolbar(toolbar_, stopRecordWidget_, pos); - else - add_to_toolbar(toolbar_, playRecordWidget_, pos); - } - } - break; - } - case CALL_STATE_CURRENT: - { - DEBUG("UIManager: Call State Current"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - int pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - g_signal_handler_block(recordWidget_, recordButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE); - g_signal_handler_unblock(recordWidget_, recordButtonConnId_); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - - case CALL_STATE_RECORD: - { - DEBUG("UIManager: Call State Record"); - int pos = 1; - gtk_action_set_sensitive(hangUpAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - g_signal_handler_block(recordWidget_, recordButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE); - g_signal_handler_unblock(recordWidget_, recordButtonConnId_); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - case CALL_STATE_BUSY: - case CALL_STATE_FAILURE: - { - int pos = 1; - DEBUG("UIManager: Call State Busy/Failure"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos); - break; - } - case CALL_STATE_TRANSFER: - { - int pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - break; - } - default: - ERROR("UIMAnager: Error: Unknown state in action update!"); - break; - } + update_toolbar_for_call(selectedCall, instant_messaging_enabled); } else if (selectedConf) { - - DEBUG("UIManager: Update actions for conference"); - - // update icon in systray - show_status_hangup_icon(); - - switch (selectedConf->_state) { - - case CONFERENCE_STATE_ACTIVE_ATTACHED: - case CONFERENCE_STATE_ACTIVE_DETACHED: - DEBUG("UIManager: Conference State Active"); - - if (active_calltree_tab == current_calls_tab) { - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - int pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - } else if (active_calltree_tab == history_tab) { - if (is_non_empty(selectedConf->_recordfile)) { - int pos = 2; - if (selectedConf->_record_is_playing) - add_to_toolbar(toolbar_, stopRecordWidget_, pos); - else - add_to_toolbar(toolbar_, playRecordWidget_, pos); - } - } - - break; - case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD: - case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: { - int pos = 1; - DEBUG("UIManager: Conference State Record"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - case CONFERENCE_STATE_HOLD: - case CONFERENCE_STATE_HOLD_RECORD: { - DEBUG("UIManager: Conference State Hold"); - int pos = 1; - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(offHoldToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, offHoldToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - default: - WARN("UIManager: Error: Should not happen in action update!"); - break; - } + update_toolbar_for_conference(selectedConf, instant_messaging_enabled); } else { // update icon in systray hide_status_hangup_icon(); @@ -528,7 +597,7 @@ help_about(void * foo UNUSED) "artists", artists, "authors", authors, "comments", _("SFLphone is a VoIP client compatible with SIP and IAX2 protocols."), - "copyright", "Copyright © 2004-2011 Savoir-faire Linux Inc.", + "copyright", "Copyright © 2004-2012 Savoir-faire Linux Inc.", "name", PACKAGE, "title", _("About SFLphone"), "version", VERSION, @@ -541,7 +610,7 @@ help_about(void * foo UNUSED) static void call_new_call(void * foo UNUSED) { - DEBUG("UIManager: New call button pressed"); + DEBUG("New call button pressed"); sflphone_new_call(); } @@ -576,7 +645,7 @@ call_hold(void* foo UNUSED) callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab); conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab); - DEBUG("UIManager: Hold button pressed"); + DEBUG("Hold button pressed"); if (selectedCall) { if (selectedCall->_state == CALL_STATE_HOLD) @@ -636,10 +705,10 @@ conference_hold(void* foo UNUSED) { conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab); - DEBUG("UIManager: Hold button pressed for conference"); + DEBUG("Hold button pressed for conference"); if (selectedConf == NULL) { - ERROR("UIManager: No conference selected"); + ERROR("No conference selected"); return; } @@ -669,7 +738,7 @@ conference_hold(void* foo UNUSED) static void call_pick_up(void * foo UNUSED) { - DEBUG("UIManager: Pick up"); + DEBUG("Pick up"); if (calllist_get_size(current_calls_tab) > 0) { sflphone_pick_up(); @@ -696,7 +765,7 @@ call_pick_up(void * foo UNUSED) static void call_hang_up(void) { - DEBUG("UIManager: Hang up button pressed(call)"); + DEBUG("Hang up button pressed(call)"); /* * [#3020] Restore the record toggle button * We set it to FALSE, as when we hang up a call, the recording is stopped. @@ -708,7 +777,7 @@ call_hang_up(void) static void conference_hang_up(void) { - DEBUG("UIManager: Hang up button pressed(conference)"); + DEBUG("Hang up button pressed(conference)"); conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab); if (selectedConf) @@ -718,23 +787,23 @@ conference_hang_up(void) static void call_record(void) { - DEBUG("UIManager: Record button pressed"); + DEBUG("Record button pressed"); sflphone_rec_call(); } static void start_playback_record_cb(void) { - DEBUG("UIManager: Start playback button pressed"); + DEBUG("Start playback button pressed"); callable_obj_t *selectedCall = calltab_get_selected_call(history_tab); if (selectedCall == NULL) { - ERROR("UIManager: Error: No selected object in playback record callback"); + ERROR("No selected object in playback record callback"); return; } - DEBUG("UIManager: Start selected call file playback %s", selectedCall->_recordfile); + DEBUG("Start selected call file playback %s", selectedCall->_recordfile); selectedCall->_record_is_playing = dbus_start_recorded_file_playback(selectedCall->_recordfile); update_actions(); @@ -743,23 +812,23 @@ start_playback_record_cb(void) static void stop_playback_record_cb(void) { - DEBUG("UIManager: Stop playback button pressed"); + DEBUG("Stop playback button pressed"); callable_obj_t *selectedCall = calltab_get_selected_call(history_tab); if (selectedCall == NULL) { - ERROR("UIManager: Error: No selected object in history treeview"); + ERROR("No selected object in history treeview"); return; } if (selectedCall) { if (selectedCall->_recordfile == NULL) { - ERROR("UIManager: Error: Record file is NULL"); + ERROR("Record file is NULL"); return; } dbus_stop_recorded_file_playback(selectedCall->_recordfile); - DEBUG("UIManager: Stop selected call file playback %s", selectedCall->_recordfile); + DEBUG("Stop selected call file playback %s", selectedCall->_recordfile); selectedCall->_record_is_playing = FALSE; } @@ -777,14 +846,15 @@ remove_from_history(void * foo UNUSED) { callable_obj_t* call = calltab_get_selected_call(history_tab); - DEBUG("UIManager: Remove the call from the history"); + DEBUG("Remove the call from the history"); if (call == NULL) { - ERROR("UIManager: Error: Call is NULL"); + ERROR("Call is NULL"); return; } calllist_remove_from_history(call); + update_actions(); } static void @@ -792,10 +862,10 @@ call_back(void * foo UNUSED) { callable_obj_t *selected_call = calltab_get_selected_call(active_calltree_tab); - DEBUG("UIManager: Call back"); + DEBUG("Call back"); if (selected_call == NULL) { - ERROR("UIManager: Error: No selected call"); + ERROR("No selected call"); return; } @@ -828,14 +898,14 @@ edit_copy(void * foo UNUSED) GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab); - DEBUG("UIManager: Edit/Copy"); + DEBUG("Edit/Copy"); if (selectedCall == NULL) { - ERROR("UIManager: Error: No selected call", selectedCall); + ERROR("No selected call", selectedCall); return; } - DEBUG("UIManager: Clipboard number: %s\n", selectedCall->_peer_number); + DEBUG("Clipboard number: %s\n", selectedCall->_peer_number); gtk_clipboard_set_text(clip, selectedCall->_peer_number, strlen(selectedCall->_peer_number)); } @@ -909,7 +979,7 @@ edit_paste(void * foo UNUSED) gchar * old = selectedCall->_peer_number; selectedCall->_peer_number = g_strconcat(old, no, NULL); g_free(old); - DEBUG("UIManager: TO: %s", selectedCall->_peer_number); + DEBUG("TO: %s", selectedCall->_peer_number); g_free(selectedCall->_peer_info); selectedCall->_peer_info = g_strconcat("\"\" <", @@ -1065,22 +1135,81 @@ static const GtkActionEntry menu_entries[] = { N_("About this application"), G_CALLBACK(help_about) } }; +static void register_custom_stock_icon(void) { + + static gboolean registered = FALSE; + + if (!registered) { + GdkPixbuf *pixbuf; + GtkIconFactory *factory; + + static GtkStockItem items[] = { + { "SFLPHONE_MUTE_CALL", + "_GTK!", + 0, 0, NULL } + }; + + registered = TRUE; + + /* Register our stock items */ + gtk_stock_add (items, G_N_ELEMENTS (items)); + + /* Add our custom icon factory to the list of defaults */ + factory = gtk_icon_factory_new (); + gtk_icon_factory_add_default (factory); + + /* demo_find_file() looks in the current directory first, + * so you can run gtk-demo without installing GTK, then looks + * in the location where the file is installed. + */ + pixbuf = NULL; + pixbuf = gdk_pixbuf_new_from_file (ICONS_DIR "/mic.svg", NULL); + if (pixbuf == NULL) { + DEBUG("Error could not create mic.svg pixbuf"); + } + + /* Register icon to accompany stock item */ + if (pixbuf != NULL) { + GtkIconSet *icon_set; + GdkPixbuf *transparent; + + /* The gtk-logo-rgb icon has a white background, make it transparent */ + transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff); + + icon_set = gtk_icon_set_new_from_pixbuf (transparent); + gtk_icon_factory_add (factory, "SFLPHONE_MUTE_CALL", icon_set); + gtk_icon_set_unref (icon_set); + g_object_unref (pixbuf); + g_object_unref (transparent); + } + else + g_warning ("failed to load GTK logo for toolbar"); + + /* Drop our reference to the factory, GTK will hold a reference. */ + g_object_unref (factory); + } +} + static const GtkToggleActionEntry toggle_menu_entries[] = { { "Transfer", GTK_STOCK_TRANSFER, N_("_Transfer"), "<control>T", N_("Transfer the call"), NULL, TRUE }, { "Record", GTK_STOCK_MEDIA_RECORD, N_("_Record"), "<control>R", N_("Record the current conversation"), NULL, TRUE }, + { "Mute", "SFLPHONE_MUTE_CALL", N_("_Mute"), "<control>M", N_("Mute microphone for this call"), G_CALLBACK(call_mute), FALSE }, { "Toolbar", NULL, N_("_Show toolbar"), "<control>T", N_("Show the toolbar"), NULL, TRUE }, { "Dialpad", NULL, N_("_Dialpad"), "<control>D", N_("Show the dialpad"), G_CALLBACK(dialpad_bar_cb), TRUE }, { "VolumeControls", NULL, N_("_Volume controls"), "<control>V", N_("Show the volume controls"), G_CALLBACK(volume_bar_cb), TRUE }, { "History", "appointment-soon", N_("_History"), NULL, N_("Calls history"), G_CALLBACK(toggle_history_cb), FALSE }, - { "Addressbook", GTK_STOCK_ADDRESSBOOK, N_("_Address book"), NULL, N_("Address book"), G_CALLBACK(toggle_addressbook_cb), FALSE } + { "Addressbook", GTK_STOCK_ADDRESSBOOK, N_("_Address book"), NULL, N_("Address book"), G_CALLBACK(toggle_addressbook_cb), FALSE }, }; GtkUIManager *uimanager_new(void) { - gint nb_entries = addrbook ? 7 : 6; + gint nb_entries = addrbook ? 8 : 7; GtkWidget *window = get_main_window(); - GtkUIManager *ui_manager = gtk_ui_manager_new(); + GtkUIManager *ui = gtk_ui_manager_new(); + + /* Register new icons as GTK_STOCK_ITEMS */ + register_custom_stock_icon(); /* Create an accel group for window's shortcuts */ gchar *path = g_build_filename(SFLPHONE_UIDIR_UNINSTALLED, "./ui.xml", NULL); @@ -1088,7 +1217,7 @@ GtkUIManager *uimanager_new(void) GError *error = NULL; if (g_file_test(path, G_FILE_TEST_EXISTS)) - manager_id = gtk_ui_manager_add_ui_from_file(ui_manager, path, &error); + manager_id = gtk_ui_manager_add_ui_from_file(ui, path, &error); else { g_free(path); path = g_build_filename(SFLPHONE_UIDIR, "./ui.xml", NULL); @@ -1096,7 +1225,7 @@ GtkUIManager *uimanager_new(void) if (!g_file_test(path, G_FILE_TEST_EXISTS)) goto fail; - manager_id = gtk_ui_manager_add_ui_from_file(ui_manager, path, &error); + manager_id = gtk_ui_manager_add_ui_from_file(ui, path, &error); } if (error) @@ -1106,11 +1235,11 @@ GtkUIManager *uimanager_new(void) if (addrbook) { // These actions must be loaded dynamically and is not specified in the xml description - gtk_ui_manager_add_ui(ui_manager, manager_id, "/ViewMenu", + gtk_ui_manager_add_ui(ui, manager_id, "/ViewMenu", "Addressbook", "Addressbook", GTK_UI_MANAGER_MENUITEM, FALSE); - gtk_ui_manager_add_ui(ui_manager, manager_id, "/ToolbarActions", + gtk_ui_manager_add_ui(ui, manager_id, "/ToolbarActions", "AddressbookToolbar", "Addressbook", GTK_UI_MANAGER_TOOLITEM, FALSE); @@ -1122,9 +1251,9 @@ GtkUIManager *uimanager_new(void) gtk_action_group_add_actions(action_group, menu_entries, G_N_ELEMENTS(menu_entries), window); gtk_action_group_add_toggle_actions(action_group, toggle_menu_entries, nb_entries, window); //gtk_action_group_add_radio_actions(action_group, radio_menu_entries, G_N_ELEMENTS(radio_menu_entries), CALLTREE_CALLS, G_CALLBACK(calltree_switch_cb), window); - gtk_ui_manager_insert_action_group(ui_manager, action_group, 0); + gtk_ui_manager_insert_action_group(ui, action_group, 0); - return ui_manager; + return ui; fail: @@ -1152,8 +1281,8 @@ add_registered_accounts_to_menu(GtkWidget *menu) account_t *acc = account_list_get_nth(i); // Display only the registered accounts - if (g_strcasecmp(account_state_name(acc->state), account_state_name( - ACCOUNT_STATE_REGISTERED)) == 0) { + if (utf8_case_equal(account_state_name(acc->state), + account_state_name(ACCOUNT_STATE_REGISTERED))) { gchar *alias = g_strconcat(g_hash_table_lookup(acc->properties, ACCOUNT_ALIAS), " - ", g_hash_table_lookup(acc->properties, ACCOUNT_TYPE), @@ -1166,7 +1295,7 @@ add_registered_accounts_to_menu(GtkWidget *menu) if (current) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_items), - g_strcasecmp(acc->accountID, current->accountID) == 0); + utf8_case_equal(acc->accountID, current->accountID)); } g_signal_connect(G_OBJECT(menu_items), "activate", @@ -1193,7 +1322,7 @@ void show_popup_menu(GtkWidget *my_widget, GdkEventButton *event) { // TODO update the selection to make sure the call under the mouse is the call selected - gboolean pickup = FALSE, hangup = FALSE, hold = FALSE, copy = FALSE, record = FALSE, im = FALSE; + gboolean pickup = FALSE, hangup = FALSE, hold = FALSE, copy = FALSE, record = FALSE, im = FALSE, mute = FALSE; gboolean accounts = FALSE; // conference type boolean @@ -1203,7 +1332,7 @@ show_popup_menu(GtkWidget *my_widget, GdkEventButton *event) conference_obj_t * selectedConf = NULL; if (calltab_get_selected_type(current_calls_tab) == A_CALL) { - DEBUG("UIManager: Menus: Selected a call"); + DEBUG("Menus: Selected a call"); selectedCall = calltab_get_selected_call(current_calls_tab); if (selectedCall) { @@ -1232,19 +1361,20 @@ show_popup_menu(GtkWidget *my_widget, GdkEventButton *event) hold = TRUE; record = TRUE; im = TRUE; + mute = TRUE; break; case CALL_STATE_BUSY: case CALL_STATE_FAILURE: hangup = TRUE; break; default: - WARN("UIManager: Should not happen in show_popup_menu for calls!") + WARN("Should not happen in show_popup_menu for calls!") ; break; } } } else { - DEBUG("UIManager: Menus: selected a conf"); + DEBUG("Menus: selected a conf"); selectedConf = calltab_get_selected_conf(active_calltree_tab); if (selectedConf) { @@ -1261,7 +1391,7 @@ show_popup_menu(GtkWidget *my_widget, GdkEventButton *event) hangup_or_hold_conf = TRUE; break; default: - WARN("UIManager: Should not happen in show_popup_menu for conferences!") + WARN("Should not happen in show_popup_menu for conferences!") ; break; } @@ -1271,7 +1401,7 @@ show_popup_menu(GtkWidget *my_widget, GdkEventButton *event) GtkWidget *menu = gtk_menu_new(); if (calltab_get_selected_type(current_calls_tab) == A_CALL) { - DEBUG("UIManager: Build call menu"); + DEBUG("Build call menu"); if (copy) { GtkWidget *menu_items = gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY, get_accel_group()); @@ -1340,6 +1470,20 @@ show_popup_menu(GtkWidget *my_widget, GdkEventButton *event) gtk_widget_show(menu_items); } + if (mute) { + GtkWidget *menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Mute")); + GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_MEDIA_RECORD, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_items), image); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_items); + g_signal_connect(G_OBJECT(menu_items), "activate", + G_CALLBACK(call_mute), + NULL); + gtk_widget_show(menu_items); + } + + + if (im) { // do not display message if instant messaging is disabled gboolean instant_messaging_enabled = TRUE; @@ -1364,7 +1508,7 @@ show_popup_menu(GtkWidget *my_widget, GdkEventButton *event) } } else { - DEBUG("UIManager: Build conf menus"); + DEBUG("Build conf menus"); if (hangup_or_hold_conf) { GtkWidget *menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Hang up")); @@ -1560,25 +1704,43 @@ create_waiting_icon() return waiting_icon; } -GtkWidget * -create_menus(GtkUIManager *ui_manager) +static GtkWidget * +get_widget(GtkUIManager *ui, const gchar *ui_path) +{ + GtkWidget *result = gtk_ui_manager_get_widget(ui, ui_path); + if (result == NULL) + ERROR("Could not get %s widget", ui_path); + return result; +} + +static GtkAction* +get_action(GtkUIManager *ui, const gchar *ui_path) { - GtkWidget *menu_bar = gtk_ui_manager_get_widget(ui_manager, "/MenuBar"); - pickUpAction_ = gtk_ui_manager_get_action(ui_manager, "/MenuBar/CallMenu/PickUp"); - newCallAction_ = gtk_ui_manager_get_action(ui_manager, "/MenuBar/CallMenu/NewCall"); - hangUpAction_ = gtk_ui_manager_get_action(ui_manager, "/MenuBar/CallMenu/HangUp"); - holdMenu_ = gtk_ui_manager_get_widget(ui_manager, "/MenuBar/CallMenu/OnHoldMenu"); - recordAction_ = gtk_ui_manager_get_action(ui_manager, "/MenuBar/CallMenu/Record"); - imAction_ = gtk_ui_manager_get_action(ui_manager, "/MenuBar/CallMenu/InstantMessaging"); - copyAction_ = gtk_ui_manager_get_action(ui_manager, "/MenuBar/EditMenu/Copy"); - pasteAction_ = gtk_ui_manager_get_action(ui_manager, "/MenuBar/EditMenu/Paste"); - volumeToggle_ = gtk_ui_manager_get_action(ui_manager, "/MenuBar/ViewMenu/VolumeControls"); + GtkAction *result = gtk_ui_manager_get_action(ui, ui_path); + if (result == NULL) + ERROR("Could not get %s action", ui_path); + return result; +} +GtkWidget * +create_menus(GtkUIManager *ui) +{ + GtkWidget *menu_bar = get_widget(ui, "/MenuBar"); + pickUpAction_ = get_action(ui, "/MenuBar/CallMenu/PickUp"); + newCallAction_ = get_action(ui, "/MenuBar/CallMenu/NewCall"); + hangUpAction_ = get_action(ui, "/MenuBar/CallMenu/HangUp"); + holdMenu_ = get_widget(ui, "/MenuBar/CallMenu/OnHoldMenu"); + recordAction_ = get_action(ui, "/MenuBar/CallMenu/Record"); + muteAction_ = get_action(ui, "/MenuBar/CallMenu/Mute"); + imAction_ = get_action(ui, "/MenuBar/CallMenu/InstantMessaging"); + copyAction_ = get_action(ui, "/MenuBar/EditMenu/Copy"); + pasteAction_ = get_action(ui, "/MenuBar/EditMenu/Paste"); + volumeToggle_ = get_action(ui, "/MenuBar/ViewMenu/VolumeControls"); // Set the toggle buttons - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(ui_manager, "/MenuBar/ViewMenu/Dialpad")), eel_gconf_get_boolean(CONF_SHOW_DIALPAD)); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(ui, "/MenuBar/ViewMenu/Dialpad")), eel_gconf_get_boolean(CONF_SHOW_DIALPAD)); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(volumeToggle_),(gboolean) SHOW_VOLUME); gtk_action_set_sensitive(volumeToggle_, must_show_alsa_conf()); - gtk_action_set_sensitive(gtk_ui_manager_get_action(ui_manager, "/MenuBar/ViewMenu/Toolbar"), FALSE); + gtk_action_set_sensitive(gtk_ui_manager_get_action(ui, "/MenuBar/ViewMenu/Toolbar"), FALSE); /* Add the loading icon at the right of the toolbar. It is used for addressbook searches. */ waitingLayer = create_waiting_icon(); @@ -1588,42 +1750,30 @@ create_menus(GtkUIManager *ui_manager) } GtkWidget * -create_toolbar_actions(GtkUIManager *ui_manager) +create_toolbar_actions(GtkUIManager *ui) { - toolbar_ = gtk_ui_manager_get_widget(ui_manager, "/ToolbarActions"); - - holdToolbar_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/OnHoldToolbar"); - offHoldToolbar_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/OffHoldToolbar"); - transferToolbar_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/TransferToolbar"); - voicemailAction_ = gtk_ui_manager_get_action(ui_manager, - "/ToolbarActions/Voicemail"); - voicemailToolbar_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/VoicemailToolbar"); - newCallWidget_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/NewCallToolbar"); - pickUpWidget_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/PickUpToolbar"); - hangUpWidget_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/HangUpToolbar"); - recordWidget_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/RecordToolbar"); - imToolbar_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/InstantMessagingToolbar"); - historyButton_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/HistoryToolbar"); - playRecordWidget_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/StartPlaybackRecordToolbar"); - stopRecordWidget_ = gtk_ui_manager_get_widget(ui_manager, - "/ToolbarActions/StopPlaybackRecordToolbar"); - + toolbar_ = get_widget(ui, "/ToolbarActions"); + holdToolbar_ = get_widget(ui, "/ToolbarActions/OnHoldToolbar"); + offHoldToolbar_ = get_widget(ui, "/ToolbarActions/OffHoldToolbar"); + transferToolbar_ = get_widget(ui, "/ToolbarActions/TransferToolbar"); + voicemailAction_ = get_action(ui, "/ToolbarActions/Voicemail"); + voicemailToolbar_ = get_widget(ui, "/ToolbarActions/VoicemailToolbar"); + newCallWidget_ = get_widget(ui, "/ToolbarActions/NewCallToolbar"); + pickUpWidget_ = get_widget(ui, "/ToolbarActions/PickUpToolbar"); + hangUpWidget_ = get_widget(ui, "/ToolbarActions/HangUpToolbar"); + recordWidget_ = get_widget(ui, "/ToolbarActions/RecordToolbar"); + muteWidget_ = get_widget(ui, "/ToolbarActions/MuteToolbar"); + imToolbar_ = get_widget(ui, "/ToolbarActions/InstantMessagingToolbar"); + historyButton_ = get_widget(ui, "/ToolbarActions/HistoryToolbar"); + playRecordWidget_ = get_widget(ui, "/ToolbarActions/StartPlaybackRecordToolbar"); + stopRecordWidget_ = get_widget(ui, "/ToolbarActions/StopPlaybackRecordToolbar"); if (addrbook) - contactButton_ = gtk_ui_manager_get_widget(ui_manager, "/ToolbarActions/AddressbookToolbar"); + contactButton_ = get_widget(ui, "/ToolbarActions/AddressbookToolbar"); // Set the handler ID for the transfer + g_assert(transferToolbar_); transferButtonConnId_ = g_signal_connect(G_OBJECT(transferToolbar_), "toggled", G_CALLBACK(call_transfer_cb), NULL); + g_assert(recordWidget_); recordButtonConnId_ = g_signal_connect(G_OBJECT(recordWidget_), "toggled", G_CALLBACK(call_record), NULL); active_calltree_tab = current_calls_tab; diff --git a/gnome/src/widget/imwidget.c b/gnome/src/widget/imwidget.c index ec7a686168c73a77f42542a29dd244477bf253b1..bf03d843106ceaa699ff2434c4fa23654bf39711 100644 --- a/gnome/src/widget/imwidget.c +++ b/gnome/src/widget/imwidget.c @@ -29,12 +29,14 @@ #include "imwindow.h" #include "logger.h" +#include "gtk2_wrappers.h" #include "imwidget.h" #include "dbus.h" #include "unused.h" #include "icons/icon_factory.h" #include "contacts/calltab.h" #include "contacts/conferencelist.h" +#include <string.h> #include <JavaScriptCore/JavaScript.h> #include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> diff --git a/gnome/src/widget/minidialog.c b/gnome/src/widget/minidialog.c index 46de0379601c3fa128dbf11716d039d7260b6f31..c844bc28e1b524f59f325b098a30ad71641658a7 100644 --- a/gnome/src/widget/minidialog.c +++ b/gnome/src/widget/minidialog.c @@ -26,6 +26,7 @@ #include <gtk/gtk.h> #include "unused.h" #include "sflphone_const.h" +#include "gtk2_wrappers.h" #include "minidialog.h" #define HIG_BOX_SPACE 6 diff --git a/gnome/tests/Makefile.am b/gnome/tests/Makefile.am index fe5a5190ce90d15fd481aff0f6a9bc365c6fb8d1..62f04b0892f2ad01b5760ed3b7adbdfbcd424229 100644 --- a/gnome/tests/Makefile.am +++ b/gnome/tests/Makefile.am @@ -3,14 +3,32 @@ include ../globals.mak TESTS = check_global check_contacts check_config check_dbus check_PROGRAMS = check_global check_contacts check_config check_dbus -SFLPHONE_LIBS = $(top_builddir)/src/contacts/libcontacts.la \ - $(top_builddir)/src/dbus/libdbus.la \ - $(top_builddir)/src/config/libconfig.la +SFLPHONE_LIBS= $(top_builddir)/src/contacts/libcontacts.la \ + $(top_builddir)/src/config/libconfig.la \ + $(top_builddir)/src/dbus/libdbus.la \ + $(top_builddir)/src/widget/libwidget.la \ + $(top_builddir)/src/icons/libicons.la ########################################################### -check_global_SOURCES = check_global.c $(top_srcdir)/src/accountlist.c $(top_srcdir)/src/logger.c -check_global_CFLAGS = @CHECK_CFLAGS@ @GTK_CFLAGS@ @GLIB_CFLAGS@ @DBUSGLIB_CFLAGS@ @GCONF_CFLAGS@ +check_global_SOURCES = check_global.c $(top_srcdir)/src/codeclist.c \ + $(top_srcdir)/src/eel-gconf-extensions.c \ + $(top_srcdir)/src/statusicon.c \ + $(top_srcdir)/src/dialpad.c \ + $(top_srcdir)/src/actions.c \ + $(top_srcdir)/src/uimanager.c \ + $(top_srcdir)/src/shortcuts.c \ + $(top_srcdir)/src/reqaccount.c \ + $(top_srcdir)/src/sflnotify.c \ + $(top_srcdir)/src/imwindow.c \ + $(top_srcdir)/src/callable_obj.c \ + $(top_srcdir)/src/conference_obj.c \ + $(top_srcdir)/src/mainwindow.c \ + $(top_srcdir)/src/sliders.c \ + $(top_srcdir)/src/accountlist.c \ + $(top_srcdir)/src/logger.c \ + $(top_srcdir)/src/str_utils.c +check_global_CFLAGS = @CHECK_CFLAGS@ @GTK_CFLAGS@ @GLIB_CFLAGS@ @DBUSGLIB_CFLAGS@ @GCONF_CFLAGS@ @WEBKIT_CFLAGS@ check_global_LDADD = $(SFLPHONE_LIBS) @CHECK_LIBS@ @GLIB_LIBS@ @GTK_LIBS@ @DBUSGLIB_LIBS@ @GCONF_LIBS@ ########################################################### @@ -42,9 +60,14 @@ check_dbus_SOURCES = check_dbus.c $(top_srcdir)/src/logger.c \ $(top_srcdir)/src/uimanager.c \ $(top_srcdir)/src/conference_obj.c \ $(top_srcdir)/src/shortcuts.c \ - $(top_srcdir)/src/imwindow.c + $(top_srcdir)/src/imwindow.c \ + $(top_srcdir)/src/str_utils.c + check_dbus_CFLAGS = @CHECK_CFLAGS@ @GTK_CFLAGS@ @DBUSGLIB_CFLAGS@ @GCONF_CFLAGS@ @WEBKIT_CFLAGS@ -check_dbus_LDADD = $(SFLPHONE_LIBS) @CHECK_LIBS@ @GCONF_LIBS@ $(top_builddir)/src/widget/libwidget.la $(top_builddir)/src/icons/libicons.la +check_dbus_LDADD = $(SFLPHONE_LIBS) @CHECK_LIBS@ @GCONF_LIBS@ \ + $(top_builddir)/src/widget/libwidget.la \ + $(top_builddir)/src/icons/libicons.la @X11_LIBS@ \ + @JAVASCRIPT_CORE_GTK_LIBS@ -ldl ########################################################### diff --git a/gnome/tests/check_global.c b/gnome/tests/check_global.c index aa3f1bb1569f92f3a7ab1cec9b8e6c0d7219a7ca..09ead1053e987e9b6ffc3d24b8d3d4d96ad9e56d 100644 --- a/gnome/tests/check_global.c +++ b/gnome/tests/check_global.c @@ -34,6 +34,7 @@ #include "../src/accountlist.h" #include "../src/sflphone_const.h" +#include "../src/str_utils.h" account_t* create_test_account(gchar *alias) { @@ -47,15 +48,15 @@ account_t* create_test_account(gchar *alias) test->properties = g_hash_table_new(NULL, g_str_equal); // Populate the properties - g_hash_table_replace(test->properties, ACCOUNT_ENABLED, "1"); - g_hash_table_replace(test->properties, ACCOUNT_ALIAS, alias); - g_hash_table_replace(test->properties, ACCOUNT_TYPE, "SIP"); - g_hash_table_replace(test->properties, ACCOUNT_HOSTNAME, "sflphone.org"); - g_hash_table_replace(test->properties, ACCOUNT_USERNAME, "1260"); - g_hash_table_replace(test->properties, ACCOUNT_PASSWORD, "NIPAgmLo"); - g_hash_table_replace(test->properties, ACCOUNT_MAILBOX, ""); - g_hash_table_replace(test->properties, ACCOUNT_SIP_STUN_SERVER, ""); - g_hash_table_replace(test->properties, ACCOUNT_SIP_STUN_ENABLED, "0"); + account_replace(test, ACCOUNT_ENABLED, "1"); + account_replace(test, ACCOUNT_ALIAS, alias); + account_replace(test, ACCOUNT_TYPE, "SIP"); + account_replace(test, ACCOUNT_HOSTNAME, "sflphone.org"); + account_replace(test, ACCOUNT_USERNAME, "1260"); + account_replace(test, ACCOUNT_PASSWORD, "NIPAgmLo"); + account_replace(test, ACCOUNT_MAILBOX, ""); + account_replace(test, ACCOUNT_SIP_STUN_SERVER, ""); + account_replace(test, ACCOUNT_SIP_STUN_ENABLED, "0"); return test; } @@ -78,7 +79,7 @@ START_TEST(test_ordered_list) account_list_init(); account_list_add(test); account_list_add(test); - fail_unless(g_strcasecmp(account_list_get_ordered_list(), list) == 0, "ERROR - BAD ACCOUNT LIST SERIALIZING"); + fail_unless(utf8_case_equal(account_list_get_ordered_list(), list), "ERROR - BAD ACCOUNT LIST SERIALIZING"); g_free(list); } END_TEST @@ -91,7 +92,7 @@ START_TEST(test_get_by_id) account_list_init(); account_list_add(test); tmp = account_list_get_by_id(test->accountID); - fail_unless(g_strcasecmp(tmp->accountID, test->accountID) == 0, "ERROR - ACCOUNTLIST_GET_BY_ID"); + fail_unless(utf8_case_equal(tmp->accountID, test->accountID), "ERROR - ACCOUNTLIST_GET_BY_ID"); } END_TEST @@ -109,8 +110,8 @@ START_TEST(test_get_current_account) // The current account must be the first we add if (current) { - fail_unless(g_strcasecmp(g_hash_table_lookup(current->properties, ACCOUNT_ALIAS) , - g_hash_table_lookup(test->properties, ACCOUNT_ALIAS)) == 0, + fail_unless(utf8_case_equal(account_lookup(current, ACCOUNT_ALIAS), + account_lookup(test, ACCOUNT_ALIAS)), "ERROR - BAD CURRENT ACCOUNT"); } @@ -121,8 +122,8 @@ START_TEST(test_get_current_account) // The current account must be the first we add if (current) { - fail_unless(g_strcasecmp(g_hash_table_lookup(current->properties, ACCOUNT_ALIAS) , - g_hash_table_lookup(test2->properties, ACCOUNT_ALIAS)) == 0, + fail_unless(utf8_case_equal(account_lookup(current, ACCOUNT_ALIAS), + account_lookup(test2, ACCOUNT_ALIAS)), "ERROR - BAD CURRENT ACCOUNT"); } } diff --git a/hudson-sflphone-script.sh b/hudson-sflphone-script.sh index a76090f155d567d36c64127971bce3800bdb3e49..699bff42b77e6e99d6ab683b57a13dd90c02c9e0 100755 --- a/hudson-sflphone-script.sh +++ b/hudson-sflphone-script.sh @@ -4,52 +4,181 @@ # # Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> -git clean -f -d -x XML_RESULTS="cppunitresults.xml" +TEST=0 +BUILD= +CODE_ANALYSIS=0 +DOXYGEN=0 + +CONFIGDIR=~/.config +SFLCONFDIR=${CONFIGDIR}/sflphone + +function run_code_analysis { + # Check if cppcheck is installed on the system + if [ `which cppcheck &>/dev/null ; echo $?` -ne 1 ] ; then + pushd src + cppcheck . --enable=all --xml --inline-suppr 2> cppcheck-report.xml + popd + fi +} + + +function gen_doxygen { + # Check if doxygen is installed on the system + if [ `which doxygen &>/dev/null ; echo $?` -ne 1 ] ; then + pushd doc/doxygen + doxygen core-doc.cfg.in + popd + fi +} + + +function launch_unit_test_daemon { + # Run the unit tests for the daemon + pushd daemon/test + # Remove the previous XML test file + rm -rf $XML_RESULTS + ./run_tests.sh || exit 1 + popd +} + + +function launch_functional_test_daemon { + # Run the python functional tests for the daemon + + # make sure no other instance are currently running + killall sflphoned + killall sipp + + # make sure the configuration directory created + CONFDIR=~/.config + SFLCONFDIR=${CONFDIR}/sflphone + + eval `dbus-launch --auto-syntax` + + if [ ! -d ${CONFDIR} ]; then + mkdir ${CONFDIR} + fi + + if [ ! -d ${SFLCONFDIR} ]; then + mkdir ${SFLCONFDIR} + fi + + # make sure the most recent version of the configuration + # is installed + pushd tools/pysflphone + cp -f sflphoned.functest.yml ${SFLCONFDIR} + popd + + # launch sflphone daemon, wait some time for + # dbus registration to complete + pushd daemon + ./src/sflphoned & + sleep 3 + popd + + # launch the test script + pushd tools/pysflphone + nosetests --with-xunit test_sflphone_dbus_interface.py + popd +} + + +function build_daemon { + # Compile the daemon + pushd daemon + # Run static analysis code tool + if [ $CODE_ANALYSIS == 1 ]; then + run_code_analysis + fi + make distclean + ./autogen.sh + # Compile pjproject first + pushd libs/pjproject + ./autogen.sh + ./configure + make && make dep + popd + ./configure --prefix=/usr + make clean + # Compile src code + make -j + # Generate documentation + make doc + if [ $DOXYGEN == 1 ]; then + gen_doxygen + fi + # Compile unit tests + make check + popd +} + +function build_gnome { + # Compile the plugins + pushd plugins + make distclean + ./autogen.sh + ./configure --prefix=/usr + make -j + popd + + # Compile the client + pushd gnome + make distclean + ./autogen.sh + ./configure --prefix=/usr + make clean + make -j 1 + make check + popd +} + + +if [ "$#" -eq 0 ]; then # Script needs at least one command-line argument. + echo "Usage $0 -b select which one to build: daemon or gnome + -t enable unit tests after build" + exit $E_OPTERR +fi + + +git clean -f -d -x + +while getopts ":b: t a d" opt; do + case $opt in + b) + echo "-b was triggered. Parameter: $OPTARG" >&2 + BUILD=$OPTARG + ;; + t) + echo "-t was triggered. Tests will be run" >&2 + TEST=1 + ;; + a) + echo "-a was triggered. Static code analysis will be run" >&2 + CODE_ANALYSIS=1 + ;; + d) + echo "-d was triggered. Doxygen documentation will be generated" >&2 + DOXYGEN=1 + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +# Call appropriate build function, with parameters if needed +build_$BUILD -set -x - -# Compile the plugins -pushd plugins -make distclean -./autogen.sh -./configure --prefix=/usr -make -j -popd - -# Compile the daemon -pushd daemon -make distclean -./autogen.sh -# Compile pjproject first -pushd libs/pjproject -./autogen.sh -./configure -make && make dep -popd -./configure --prefix=/usr -make clean -make -j -make doc -make check -popd - -# Run the unit tests for the daemon -pushd daemon/test -# Remove the previous XML test file -rm -rf $XML_RESULTS -./run_tests.sh || exit 1 -popd - -# Compile the client -pushd gnome -make distclean -./autogen.sh -./configure --prefix=/usr -make clean -make -j 1 -make check -popd +if [ $TEST == 1 ]; then + # launch_unit_test_daemon + launch_functional_test_daemon +fi # SUCCESS exit 0 diff --git a/kde/CMakeLists.txt b/kde/CMakeLists.txt index 30f36bf1dae0a93c8181e8b12468615689cf232c..5c3b446632407f536d1980aaaa57f5d9d43f61c7 100755 --- a/kde/CMakeLists.txt +++ b/kde/CMakeLists.txt @@ -14,6 +14,9 @@ FIND_PACKAGE ( KdepimLibs REQUIRED ) FIND_PACKAGE ( KDE4 REQUIRED ) FIND_PACKAGE ( Qt4 REQUIRED ) +set(AKONADI_MIN_VERSION 1.0) +find_package(Akonadi QUIET NO_MODULE ${AKONADI_MIN_VERSION}) + INCLUDE ( KDE4Defaults ) MESSAGE("cmake install prefix is : ${CMAKE_INSTALL_PREFIX}") @@ -31,9 +34,7 @@ add_subdirectory(man) add_subdirectory(po) add_subdirectory(plasma) -# make dist target, see: -# https://agateau.wordpress.com/2009/08/09/cmake-and-make-dist-the-simple-version/ -set(PROJECT_VERSION "1.0.0") +set(PROJECT_VERSION "1.1.0") set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}) add_custom_target(dist COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD diff --git a/kde/data/sflphone-client-kdeui.rc b/kde/data/sflphone-client-kdeui.rc index c91fd23094c0203c46ec6d287136dfd297983f12..ca0c824b3215b4c7aa3261b4c4ccaf3ee8d50b30 100755 --- a/kde/data/sflphone-client-kdeui.rc +++ b/kde/data/sflphone-client-kdeui.rc @@ -1,44 +1,45 @@ <?xml version="1.0" encoding="UTF-8"?> -<!--<gui name="tutorial3" - version="1" - xmlns="http://www.kde.org/standards/kxmlgui/1.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0 - http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" > - --> + <!--<gui name="tutorial3" + version="1" + xmlns="http://www.kde.org/standards/kxmlgui/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0 + http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" > + --> <gui name="sflphone-client-kde" version="1"> - <MenuBar> - <Menu name="Actions" > - <text>Actions</text> - <Action name="action_accept" /> - <Action name="action_refuse" /> - <Action name="action_hold" /> - <Action name="action_transfer" /> - <Action name="action_record" /> - <Action name="action_mailBox" /> - <Separator /> - <Action name="action_close" /> - <Separator /> - <Action name="action_quit" /> - </Menu> - <Menu name="Settings" > - <text>Settings</text> - <Action name="action_displayVolumeControls" /> - <Action name="action_displayDialpad" /> - <Separator /> - <Action name="action_configureShortcut" /> - <Action name="action_configureSflPhone" /> - <Separator /> - <Action name="action_accountCreationWizard" /> - </Menu> - </MenuBar> - - <ToolBar name="mainToolBar" iconText="icononly" position="Top" noMerge="1" fullWidth="false" newline="true" > - <Action name="action_accept" /> - <Action name="action_mailBox" /> - <Action name="action_refuse" /> - <Action name="action_hold" /> - <Action name="action_transfer" /> - <Action name="action_record" /> - </ToolBar> + <MenuBar> + <Menu name="Actions" > + <text>Actions</text> + <Action name="action_accept" /> + <Action name="action_refuse" /> + <Action name="action_hold" /> + <Action name="action_transfer" /> + <Action name="action_record" /> + <Action name="action_mailBox" /> + <Separator /> + <Action name="action_close" /> + <Separator /> + <Action name="action_quit" /> + </Menu> + <Menu name="Settings" > + <text>Settings</text> + <Action name="action_displayVolumeControls" /> + <Action name="action_displayDialpad" /> + <Action name="action_displayMessageBox" /> + <Separator /> + <Action name="action_configureShortcut" /> + <Action name="action_configureSflPhone" /> + <Separator /> + <Action name="action_accountCreationWizard" /> + </Menu> + </MenuBar> + + <ToolBar name="mainToolBar" iconText="icononly" position="Top" noMerge="1" fullWidth="false" newline="true" > + <Action name="action_accept" /> + <Action name="action_mailBox" /> + <Action name="action_refuse" /> + <Action name="action_hold" /> + <Action name="action_transfer" /> + <Action name="action_record" /> + </ToolBar> </gui> diff --git a/kde/doc/index.docbook b/kde/doc/index.docbook index dc19819589eceb5c8c86a917e99865f633555f2c..e33d6fe411a6f965d51d8a64750484fb55108974 100755 --- a/kde/doc/index.docbook +++ b/kde/doc/index.docbook @@ -2,7 +2,7 @@ <!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [ <!ENTITY sflphone-client-kde "SFLPhone KDE Client"> <!ENTITY kappname "&sflphone-client-kde;"> - <!ENTITY sflphonerelease "0.9.6"> + <!ENTITY sflphonerelease "1.1.0"> <!ENTITY current-w "Current calls window"> <!ENTITY history-w "Call history window"> <!ENTITY address-w "Address book window"> diff --git a/kde/plasma/CMakeLists.txt b/kde/plasma/CMakeLists.txt index a671e1337faf25196de17f2aa45689c860d7090a..f1eba1ab0f0017cc2c809b71822b40bf461bce54 100644 --- a/kde/plasma/CMakeLists.txt +++ b/kde/plasma/CMakeLists.txt @@ -1,4 +1,3 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -add_subdirectory(dataengine) add_subdirectory(plasmoid) diff --git a/kde/plasma/dataengine/sflphonEngine.cpp b/kde/plasma/dataengine/sflphonEngine.cpp deleted file mode 100644 index 4c7c51c90c4d4a4ccb464cece20ccbc1963e76f8..0000000000000000000000000000000000000000 --- a/kde/plasma/dataengine/sflphonEngine.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "sflphonEngine.h" - -#include <Plasma/DataContainer> - -#include "../../src/lib/Call.h" -#include "../../src/lib/dbus/metatypes.h" -#include "../../src/lib/instance_interface_singleton.h" -#include "../../src/lib/configurationmanager_interface_singleton.h" -#include "../../src/lib/callmanager_interface_singleton.h" -#include "../../src/lib/sflphone_const.h" - -SFLPhoneEngine::SFLPhoneEngine(QObject* parent, const QVariantList& args) - : Plasma::DataEngine(parent, args) -{ - Q_UNUSED(args) - m_pModel = new CallModelConvenience(CallModelConvenience::ActiveCall); - m_pModel->initCall(); - m_pModel->initHistory(); - - CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); - - connect(m_pModel , SIGNAL( callStateChanged(Call*)) , this , SLOT(callStateChangedSignal(Call*) )); - connect(&callManager , SIGNAL( incomingCall(Call*)) , this , SLOT(incomingCallSignal(Call*) )); - connect(&callManager , SIGNAL( conferenceCreated(Call*)) , this , SLOT(conferenceCreatedSignal(Call*) )); - connect(&callManager , SIGNAL( conferenceChanged(Call*)) , this , SLOT(conferenceChangedSignal(Call*) )); -} - -bool SFLPhoneEngine::sourceRequestEvent(const QString &name) -{ - if ( name == "history" ) { - updateHistory(); - } - else if ( name == "calls" ) { - updateCallList(); - } - else if ( name == "conferences" ) { - updateConferenceList(); - } - else if ( name == "info" ) { - updateInfo(); - } - return true;//updateSourceEvent(name); -} - -bool SFLPhoneEngine::updateSourceEvent(const QString &name) -{ - Q_UNUSED(name) - return true; -} - -QStringList SFLPhoneEngine::sources() const { - QStringList toReturn; - toReturn << "calls" << "history" << "conferences" << "info"; - return toReturn; -} - -QString SFLPhoneEngine::getCallStateName(call_state state) -{ - if (state == CALL_STATE_INCOMING) { - return I18N_NOOP("Ringing (in)"); - } else if (state == CALL_STATE_RINGING) { - return I18N_NOOP("Ringing (out)"); - } else if (state == CALL_STATE_CURRENT) { - return I18N_NOOP("Talking"); - } else if (state == CALL_STATE_DIALING) { - return I18N_NOOP("Dialing"); - } else if (state == CALL_STATE_HOLD) { - return I18N_NOOP("Hold"); - } else if (state == CALL_STATE_FAILURE) { - return I18N_NOOP("Failed"); - } else if (state == CALL_STATE_BUSY) { - return I18N_NOOP("Busy"); - } else if (state == CALL_STATE_TRANSFER) { - return I18N_NOOP("Transfer"); - } else if (state == CALL_STATE_TRANSF_HOLD) { - return I18N_NOOP("Transfer hold"); - } else if (state == CALL_STATE_OVER) { - return I18N_NOOP("Over"); - } else if (state == CALL_STATE_ERROR) { - return I18N_NOOP("Error"); - } - return ""; -} - -void SFLPhoneEngine::updateHistory() -{ - foreach (Call* oldCall, m_pModel->getHistory()) { - historyCall[oldCall->getCallId()][ "Name" ] = oldCall->getPeerName(); - historyCall[oldCall->getCallId()][ "Number" ] = oldCall->getPeerPhoneNumber(); - historyCall[oldCall->getCallId()][ "Date" ] = oldCall->getStopTimeStamp(); - setData("history", I18N_NOOP(oldCall->getCallId()), historyCall[oldCall->getCallId()]); - } -} - -void SFLPhoneEngine::updateCallList() -{ - foreach (Call* call, m_pModel->getCalls()) { - if ((!m_pModel->isConference(call)) && (call->getState() != CALL_STATE_OVER)) { - currentCall[call->getCallId()][ "Name" ] = call->getPeerName(); - currentCall[call->getCallId()][ "Number" ] = call->getPeerPhoneNumber(); - currentCall[call->getCallId()][ "StateName" ] = getCallStateName(call->getState()); - currentCall[call->getCallId()][ "State" ] = call->getState(); - setData("calls", call->getCallId(), currentCall[call->getCallId()]); - } - } -} - -void SFLPhoneEngine::updateConferenceList() -{ - foreach (Call* call, m_pModel->getCalls()) { - if (m_pModel->isConference(call)) { - CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); - currentConferences[call->getConfId()] = callManager.getParticipantList(call->getConfId()); - setData("conferences", call->getConfId(), currentConferences[call->getConfId()]); - } - } -} - -void SFLPhoneEngine::updateContacts() -{ - -} - -void SFLPhoneEngine::updateInfo() -{ - qDebug() << "Currentaccount: " << m_pModel->getCurrentAccountId(); - setData("info", I18N_NOOP("Account"), m_pModel->getCurrentAccountId()); -} - -void SFLPhoneEngine::callStateChangedSignal(Call* call) -{ - Q_UNUSED(call) - updateCallList(); -} - -void SFLPhoneEngine::incomingCallSignal(Call* call) -{ - Q_UNUSED(call) - updateCallList(); -} - -void SFLPhoneEngine::conferenceCreatedSignal(Call* conf) -{ - Q_UNUSED(conf) - updateConferenceList(); -} - -void SFLPhoneEngine::conferenceChangedSignal(Call* conf) -{ - Q_UNUSED(conf) - updateConferenceList(); -} - -void SFLPhoneEngine::incomingMessageSignal(const QString& accountId, const QString& message) -{ - Q_UNUSED(accountId) - Q_UNUSED(message) - //TODO -} - -void SFLPhoneEngine::voiceMailNotifySignal(const QString& accountId, int count) -{ - Q_UNUSED(accountId) - Q_UNUSED(count) - //TODO -} - -void SFLPhoneEngine::accountChanged() -{ - -} - -K_EXPORT_PLASMA_DATAENGINE(sflphone, SFLPhoneEngine) diff --git a/kde/plasma/plasmoid/MainWidget.cpp b/kde/plasma/plasmoid/MainWidget.cpp index ff3a9567c57950ff54d3a236312257faba64f090..305bf42a2c1ce4fed17d15324d7eae563d5a0dbc 100644 --- a/kde/plasma/plasmoid/MainWidget.cpp +++ b/kde/plasma/plasmoid/MainWidget.cpp @@ -71,14 +71,14 @@ void MainWidget::dataUpdated(const QString& source, const Plasma::DataEngine::Da { if ((source == "calls") && (frmCalls)) { QHash<QString, QVariant> value = data; - bool modified = false; + //bool modified = false; foreach(QVariant call, value) { if (!callWidgetList[value.key(call)]) { callWidgetList[ value.key(call) ] = new CallItem(); callWidgetList[ value.key(call) ]->setCallId(value.key(call)); callLayout->insertItem(0,callWidgetList[value.key(call)]); mainTabs->setCurrentIndex(CALL); - modified = true; + //modified = true; } callWidgetList[value.key(call)]->setCallerName(call.toHash() [ "Name" ].toString()); callWidgetList[value.key(call)]->setCallerNumber(call.toHash()[ "Number" ].toString()); diff --git a/kde/plasma/plasmoid/SFLPhonePlasmoid.cpp b/kde/plasma/plasmoid/SFLPhonePlasmoid.cpp index 293df0fa9ab29501536eb13062dbb9a25388d780..8f5a5b6fc5bd9ebc25ee94f1ef7b54a01309e2f0 100644 --- a/kde/plasma/plasmoid/SFLPhonePlasmoid.cpp +++ b/kde/plasma/plasmoid/SFLPhonePlasmoid.cpp @@ -13,7 +13,7 @@ SFLPhonePlasmoid::SFLPhonePlasmoid(QObject* parent, const QVariantList& args) //m_svg.setImagePath("widgets/background"); setBackgroundHints(DefaultBackground); - CallModelConvenience::init(); + CallModel<>::init(); setMinimumSize(24,24); } diff --git a/kde/src/AccountView.cpp b/kde/src/AccountView.cpp index eee3f689ff0a5b1dd3706888454ae1e7a4650892..0e20a83ffc924a03744df65a701e2554ec3779cd 100644 --- a/kde/src/AccountView.cpp +++ b/kde/src/AccountView.cpp @@ -55,14 +55,14 @@ void AccountView::initItemWidget() if(m_pWidget != NULL) delete m_pWidget; - bool enabled = getAccountDetail(ACCOUNT_ENABLED) == ACCOUNT_ENABLED_TRUE; + bool enabled = getAccountDetail(ACCOUNT_ENABLED) == REGISTRATION_ENABLED_TRUE; m_pWidget = new AccountItemWidget(); m_pWidget->setEnabled(enabled); m_pWidget->setAccountText(getAccountDetail(ACCOUNT_ALIAS)); if(isNew() || !enabled) m_pWidget->setState(AccountItemWidget::Unregistered); - else if(getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED || getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_READY) + else if(getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED || getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_READY) m_pWidget->setState(AccountItemWidget::Registered); else m_pWidget->setState(AccountItemWidget::NotWorking); @@ -91,9 +91,9 @@ AccountItemWidget* AccountView::getItemWidget() ///Return the state color QColor AccountView::getStateColor() { - if(getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_UNREGISTERED) + if(getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_UNREGISTERED) return Qt::black; - if(getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED || getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_READY) + if(getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED || getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_READY) return Qt::darkGreen; return Qt::red; } @@ -104,9 +104,9 @@ const QString& AccountView::getStateColorName() static const QString black ( "black" ); static const QString darkGreen( "darkGreen" ); static const QString red ( "red" ); - if(getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_UNREGISTERED) + if(getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_UNREGISTERED) return black; - if(getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED || getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_READY) + if(getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED || getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_READY) return darkGreen; return red; } @@ -154,11 +154,11 @@ void AccountView::updateState() Account::updateState(); AccountItemWidget * m_pWidget = getItemWidget(); - if(getAccountDetail(ACCOUNT_ENABLED) != ACCOUNT_ENABLED_TRUE ) { + if(getAccountDetail(ACCOUNT_ENABLED) != REGISTRATION_ENABLED_TRUE ) { kDebug() << "Changing account state to Unregistered"; m_pWidget->setState(AccountItemWidget::Unregistered); } - else if(getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED || getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_READY) { + else if(getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED || getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_READY) { kDebug() << "Changing account state to Registered"; m_pWidget->setState(AccountItemWidget::Registered); } diff --git a/kde/src/AccountWizard.cpp b/kde/src/AccountWizard.cpp index 6fdfd3dae5bd1de850074e27198ac6ec674c63b6..79069cc142f81872ed382e2b34c498849778641a 100755 --- a/kde/src/AccountWizard.cpp +++ b/kde/src/AccountWizard.cpp @@ -246,7 +246,7 @@ void AccountWizard::accept() server = QString( SFL_ACCOUNT_HOST ); password = QString( acc.passwd ); user = QString( acc.user ); - enabled = QString( ACCOUNT_ENABLED_TRUE ); + enabled = QString( REGISTRATION_ENABLED_TRUE ); is_create_account = true; is_using_sip = true; @@ -260,7 +260,7 @@ void AccountWizard::accept() ret += i18n("This assistant is now finished.") + "\n"; alias = field ( FIELD_SIP_ALIAS ).toString(); - enabled = QString ( ACCOUNT_ENABLED_TRUE ); + enabled = QString ( REGISTRATION_ENABLED_TRUE ); mailbox = field ( FIELD_SIP_VOICEMAIL ).toString(); protocol = QString ( ACCOUNT_TYPE_SIP ); server = field ( FIELD_SIP_SERVER ).toString(); @@ -275,7 +275,7 @@ void AccountWizard::accept() ret += i18n("This assistant is now finished.") + "\n"; alias = field ( FIELD_IAX_ALIAS ).toString(); - enabled = QString ( ACCOUNT_ENABLED_TRUE ); + enabled = QString ( REGISTRATION_ENABLED_TRUE ); mailbox = field ( FIELD_IAX_VOICEMAIL ).toString(); protocol = QString ( ACCOUNT_TYPE_IAX ); server = field ( FIELD_IAX_SERVER ).toString(); @@ -290,21 +290,21 @@ void AccountWizard::accept() // common sip paramaters if(is_using_sip) { if(field(FIELD_SIP_ENABLE_STUN).toBool()) { - stun_enabled = QString(ACCOUNT_ENABLED_TRUE); + stun_enabled = QString(REGISTRATION_ENABLED_TRUE); stun_server = field(FIELD_SIP_STUN_SERVER).toString(); } else { - stun_enabled = QString(ACCOUNT_ENABLED_FALSE); + stun_enabled = QString(REGISTRATION_ENABLED_FALSE); stun_server = QString(); } if(field(FIELD_ZRTP_ENABLED).toBool()) { - srtp_enabled = QString( ACCOUNT_ENABLED_TRUE ); + srtp_enabled = QString( REGISTRATION_ENABLED_TRUE ); key_exchange = QString( ZRTP ); - zrtp_display_sas = QString( ACCOUNT_ENABLED_TRUE ); - zrtp_not_supp_warning = QString( ACCOUNT_ENABLED_TRUE ); - zrtp_hello_hash = QString( ACCOUNT_ENABLED_TRUE ); - display_sas_once = QString( ACCOUNT_ENABLED_FALSE ); + zrtp_display_sas = QString( REGISTRATION_ENABLED_TRUE ); + zrtp_not_supp_warning = QString( REGISTRATION_ENABLED_TRUE ); + zrtp_hello_hash = QString( REGISTRATION_ENABLED_TRUE ); + display_sas_once = QString( REGISTRATION_ENABLED_FALSE ); } QStringList ifaceList = configurationManager.getAllIpInterface(); diff --git a/kde/src/CMakeLists.txt b/kde/src/CMakeLists.txt index 7ca4c1ec0f8b762a28822751b497c4bb16f231d1..2e1af6b3ffe31a053534b0fa9c4ec1d7442f7a49 100755 --- a/kde/src/CMakeLists.txt +++ b/kde/src/CMakeLists.txt @@ -1,54 +1,60 @@ ADD_DEFINITIONS( - ${KDE4_DEFINITIONS} - ${QT_DEFINITIONS} - -fexceptions - -DDATA_INSTALL_DIR="\\\"${DATA_INSTALL_DIR}\\\"" - -DSHARE_INSTALL_PREFIX="\\\"${SHARE_INSTALL_PREFIX}\\\"" + ${KDE4_DEFINITIONS} + ${QT_DEFINITIONS} + -fexceptions + -DDATA_INSTALL_DIR="\\\"${DATA_INSTALL_DIR}\\\"" + -DSHARE_INSTALL_PREFIX="\\\"${SHARE_INSTALL_PREFIX}\\\"" ) -add_subdirectory(lib) +ADD_DEFINITIONS("-std=c++0x") + +add_subdirectory( lib ) +add_subdirectory( klib ) + +find_package(Phonon) MESSAGE("CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") IF(${CMAKE_BUILD_TYPE} MATCHES Release) - MESSAGE("NO DEBUG OUTPUT") - ADD_DEFINITIONS( -DQT_NO_DEBUG_OUTPUT) + MESSAGE("NO DEBUG OUTPUT") + ADD_DEFINITIONS( -DQT_NO_DEBUG_OUTPUT) ENDIF(${CMAKE_BUILD_TYPE} MATCHES Release) SET ( KDE4_KABC_LIBS -lkabc ) -SET( sflphone_client_kde_SRCS - SFLPhoneView.cpp - SFLPhone.cpp - SFLPhoneapplication.cpp - widgets/SFLPhoneTray.cpp - main.cpp - AccountWizard.cpp - widgets/AccountItemWidget.cpp - widgets/CallTreeItem.cpp - widgets/HistoryTreeItem.cpp - ActionSetAccountFirst.cpp - conf/ConfigurationDialog.cpp - conf/dlggeneral.cpp - conf/dlgdisplay.cpp - conf/dlgaccounts.cpp - conf/dlgaudio.cpp - conf/dlgaddressbook.cpp - conf/dlghooks.cpp - conf/ConfigurationSkeleton.cpp - conf/ConfigAccountList.cpp - widgets/Dialpad.cpp - widgets/ContactItemWidget.cpp - widgets/ContactDock.cpp - widgets/HistoryDock.cpp - widgets/BookmarkDock.cpp - widgets/TranslucentButtons.cpp - Codec.cpp - AccountListModel.cpp - AkonadiBackend.cpp - CallView.cpp - AccountView.cpp +SET( + sflphone_client_kde_SRCS + SFLPhoneView.cpp + SFLPhone.cpp + SFLPhoneapplication.cpp + widgets/SFLPhoneTray.cpp + main.cpp + AccountWizard.cpp + widgets/AccountItemWidget.cpp + widgets/CallTreeItem.cpp + widgets/HistoryTreeItem.cpp + ActionSetAccountFirst.cpp + conf/ConfigurationDialog.cpp + conf/dlggeneral.cpp + conf/dlgdisplay.cpp + conf/dlgaccounts.cpp + conf/dlgaudio.cpp + conf/dlgaddressbook.cpp + conf/dlghooks.cpp + conf/ConfigAccountList.cpp + widgets/Dialpad.cpp + widgets/ContactItemWidget.cpp + widgets/ContactDock.cpp + widgets/HistoryDock.cpp + widgets/BookmarkDock.cpp + widgets/TranslucentButtons.cpp + widgets/CategoryDrawer.cpp + widgets/CategorizedTreeWidget.cpp + Codec.cpp + AccountListModel.cpp + CallView.cpp + AccountView.cpp ) @@ -59,27 +65,26 @@ QT4_ADD_RESOURCES(QtApp_RCC_SRCS ${QtApp_RCCS}) # kde4_automoc(${sflphone_client_kde_SRCS}) -SET( config_ui_files - conf/dlggeneralbase.ui - conf/dlgdisplaybase.ui - conf/dlgaccountsbase.ui - conf/dlgaudiobase.ui - conf/dlgaddressbookbase.ui - conf/dlghooksbase.ui +SET( + config_ui_files + conf/dlggeneralbase.ui + conf/dlgdisplaybase.ui + conf/dlgaccountsbase.ui + conf/dlgaudiobase.ui + conf/dlgaddressbookbase.ui + conf/dlghooksbase.ui ) KDE4_ADD_UI_FILES(sflphone_client_kde_SRCS ui/SFLPhoneView_base.ui ${config_ui_files} ) -KDE4_ADD_KCFG_FILES(sflphone_client_kde_SRCS conf/kcfg_settings.kcfgc) -INSTALL(FILES conf/sflphone-client-kde.kcfg DESTINATION ${KCFG_INSTALL_DIR}) KDE4_ADD_EXECUTABLE(sflphone-client-kde ${sflphone_client_kde_SRCS} ${QtApp_RCC_SRCS}) -TARGET_LINK_LIBRARIES(sflphone-client-kde qtsflphone ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDEPIMLIBS_AKONADI_KMIME_LIBS} ${KDEPIMLIBS_AKONADI_LIBS} ${KDEPIMLIBS_AKONADI_CONTACT_LIBS} ) +TARGET_LINK_LIBRARIES(sflphone-client-kde ksflphone qtsflphone ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDEPIMLIBS_AKONADI_KMIME_LIBS} ${KDEPIMLIBS_AKONADI_LIBS} ${KDEPIMLIBS_AKONADI_CONTACT_LIBS} ${KDE4_PHONON_LIBS} ) ########### install files ############### -INSTALL(TARGETS sflphone-client-kde DESTINATION ${BIN_INSTALL_DIR}) +INSTALL(TARGETS sflphone-client-kde DESTINATION ${BIN_INSTALL_DIR} ) INSTALL( FILES icons/transferarraw.png DESTINATION ${DATA_INSTALL_DIR}/sflphone-client-kde ) INSTALL( FILES icons/transfertarrow.svg DESTINATION ${DATA_INSTALL_DIR}/sflphone-client-kde ) INSTALL( FILES icons/confBlackWhite.svg DESTINATION ${DATA_INSTALL_DIR}/sflphone-client-kde ) diff --git a/kde/src/CallView.cpp b/kde/src/CallView.cpp index 5c912479f30e307bdc444d676e6a69e82e983b8d..de0b5dfc42fbb365419ee88b70d7e9347135d8e3 100644 --- a/kde/src/CallView.cpp +++ b/kde/src/CallView.cpp @@ -44,7 +44,7 @@ #include "widgets/CallTreeItem.h" #include "SFLPhone.h" #include "SFLPhoneView.h" -#include "AkonadiBackend.h" +#include "klib/AkonadiBackend.h" ///Retrieve current and older calls from the daemon, fill history and the calls TreeView and enable drag n' drop @@ -258,33 +258,9 @@ bool CallView::contactToCall(QTreeWidgetItem *parent, int index, const QMimeData if (!QString(encodedContact).isEmpty()) { Contact* contact = AkonadiBackend::getInstance()->getContactByUid(encodedContact); if (contact) { - Call* call2; - if (contact->getPhoneNumbers().count() == 1) { - call2 = SFLPhone::model()->addDialingCall(contact->getFormattedName(), SFLPhone::model()->getCurrentAccountId()); - call2->appendText(contact->getPhoneNumbers()[0]->getNumber()); - } - else if (contact->getPhoneNumbers().count() > 1) { - bool ok = false; - QHash<QString,QString> map; - QStringList list; - foreach (Contact::PhoneNumber* number, contact->getPhoneNumbers()) { - map[number->getType()+" ("+number->getNumber()+")"] = number->getNumber(); - list << number->getType()+" ("+number->getNumber()+")"; - } - QString result = QInputDialog::getItem (this, QString("Select phone number"), QString("This contact have many phone number, please select the one you wish to call"), list, 0, false, &ok); - if (ok) { - call2 = SFLPhone::model()->addDialingCall(contact->getFormattedName(), SFLPhone::model()->getCurrentAccountId()); - call2->appendText(map[result]); - } - else { - kDebug() << "Operation cancelled"; - return false; - } - } - else { - kDebug() << "This contact have no valid phone number"; + Call* call2 = NULL; + if (!SFLPhone::app()->view()->selectCallPhoneNumber(call2,contact)) return false; - } if (!parent) { //Dropped on free space kDebug() << "Adding new dialing call"; @@ -382,12 +358,13 @@ Call* CallView::addCall(Call* call, Call* parent) ///Transfer a call void CallView::transfer() { - if (m_pCallPendingTransfer) { + if (m_pCallPendingTransfer && !m_pTransferLE->text().isEmpty()) { SFLPhone::model()->transfer(m_pCallPendingTransfer,m_pTransferLE->text()); - m_pCallPendingTransfer = 0; - m_pTransferLE->clear(); - m_pTransferOverlay->setVisible(false); } + + m_pCallPendingTransfer = 0; + m_pTransferLE->clear(); + m_pTransferOverlay->setVisible(false); } /***************************************************************************** @@ -421,6 +398,13 @@ void CallView::hideOverlay() if (m_pActiveOverlay) m_pActiveOverlay->setVisible(false); m_pActiveOverlay = 0; + + if (m_pCallPendingTransfer && m_pCallPendingTransfer->getState() == CALL_STATE_TRANSFER ) { + m_pCallPendingTransfer->actionPerformed(CALL_ACTION_TRANSFER); + } + + m_pCallPendingTransfer = 0; + m_pTransferLE->clear(); } ///Be sure the size of the overlay stay the same @@ -635,6 +619,7 @@ Call* CallView::addConference(Call* conf) ///Executed when the daemon signal a modification in an existing conference. Update the call list and update the TreeView bool CallView::conferenceChanged(Call* conf) { + if (!dynamic_cast<Call*>(conf)) return false; kDebug() << "Conference changed"; //if (!SFLPhone::model()->conferenceChanged(confId, state)) // return false; @@ -721,8 +706,9 @@ void CallViewOverlay::setVisible(bool enabled) { if (m_pTimer) { m_pTimer->stop(); disconnect(m_pTimer); + delete m_pTimer; } - m_pTimer = new QTimer(this); //TODO LEAK? + m_pTimer = new QTimer(this); connect(m_pTimer, SIGNAL(timeout()), this, SLOT(changeVisibility())); m_step = 0; m_black.setAlpha(0); diff --git a/kde/src/SFLPhone.cpp b/kde/src/SFLPhone.cpp index 21b03330c878e0b2d6e959d910a024f3001e8b2a..adaf9693d80bc6f7308443a796fb89b855f78ddb 100755 --- a/kde/src/SFLPhone.cpp +++ b/kde/src/SFLPhone.cpp @@ -47,14 +47,14 @@ #include "lib/Contact.h" //SFLPhone -#include "AkonadiBackend.h" +#include "klib/AkonadiBackend.h" #include "AccountWizard.h" #include "SFLPhoneView.h" #include "widgets/SFLPhoneTray.h" #include "widgets/ContactDock.h" #include "widgets/HistoryDock.h" #include "widgets/BookmarkDock.h" -#include "conf/ConfigurationSkeleton.h" +#include "klib/ConfigurationSkeleton.h" SFLPhone* SFLPhone::m_sApp = NULL; TreeWidgetCallModel* SFLPhone::m_pModel = NULL; @@ -187,6 +187,11 @@ void SFLPhone::setupActions() action_displayDialpad = new KAction(KIcon(QIcon(ICON_DISPLAY_DIALPAD)), i18n("Display dialpad"), this); action_displayDialpad->setCheckable( true ); action_displayDialpad->setChecked ( ConfigurationSkeleton::displayDialpad() ); + action_configureSflPhone->setText(i18n("Configure SFLphone")); + + action_displayMessageBox = new KAction(KIcon("mail-message-new"), i18n("Display text message box"), this); + action_displayMessageBox->setCheckable( true ); + action_displayMessageBox->setChecked ( ConfigurationSkeleton::displayMessageBox() ); action_displayVolumeControls = new KAction(KIcon(QIcon(ICON_DISPLAY_VOLUME_CONSTROLS)), i18n("Display volume controls"), this); action_displayVolumeControls->setCheckable( true ); @@ -205,6 +210,7 @@ void SFLPhone::setupActions() /**/connect(action_mailBox, SIGNAL(triggered()), m_pView , SLOT(mailBox() )); /**/connect(action_displayVolumeControls, SIGNAL(toggled(bool)), m_pView , SLOT(displayVolumeControls(bool) )); /**/connect(action_displayDialpad, SIGNAL(toggled(bool)), m_pView , SLOT(displayDialpad(bool) )); + /**/connect(action_displayMessageBox, SIGNAL(toggled(bool)), m_pView , SLOT(displayMessageBox(bool) )); /**/connect(action_accountCreationWizard, SIGNAL(triggered()), m_pView , SLOT(accountCreationWizard() )); /**/connect(action_configureShortcut, SIGNAL(triggered()), this , SLOT(showShortCutEditor() )); /* */ @@ -220,6 +226,7 @@ void SFLPhone::setupActions() actionCollection()->addAction("action_quit" , action_quit ); actionCollection()->addAction("action_displayVolumeControls" , action_displayVolumeControls ); actionCollection()->addAction("action_displayDialpad" , action_displayDialpad ); + actionCollection()->addAction("action_displayMessageBox" , action_displayMessageBox ); actionCollection()->addAction("action_configureSflPhone" , action_configureSflPhone ); actionCollection()->addAction("action_accountCreationWizard" , action_accountCreationWizard ); actionCollection()->addAction("action_configureShortcut" , action_configureShortcut ); @@ -397,8 +404,8 @@ void SFLPhone::on_m_pView_recordCheckStateChangeAsked(bool recordCheckState) void SFLPhone::on_m_pView_incomingCall(const Call * call) { Contact* contact = AkonadiBackend::getInstance()->getContactByPhone(call->getPeerPhoneNumber()); - if (contact) { - KNotification::event(KNotification::Notification, "New incomming call", "New call from: \n" + call->getPeerName().isEmpty() ? call->getPeerPhoneNumber() : call->getPeerName(),*contact->getPhoto()); + if (contact && call) { + KNotification::event(KNotification::Notification, "New incomming call", "New call from: \n" + call->getPeerName().isEmpty() ? call->getPeerPhoneNumber() : call->getPeerName(),(contact->getPhoto())?*contact->getPhoto():NULL); } KNotification::event(KNotification::Notification, "New incomming call", "New call from: \n" + call->getPeerName().isEmpty() ? call->getPeerPhoneNumber() : call->getPeerName()); } diff --git a/kde/src/SFLPhone.h b/kde/src/SFLPhone.h index 030a2292433b591696ce50770ef6f4b6667c0a01..c8a7cd3386b81fbe6b9a6d67afdc6f58bfed6648 100755 --- a/kde/src/SFLPhone.h +++ b/kde/src/SFLPhone.h @@ -57,7 +57,7 @@ typedef CallModel<CallTreeItem*,QTreeWidgetItem*> TreeWidgetCallModel; * * @short Main window * @author Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> - * @version 0.9.6 + * @version 1.1.0 **/ class SFLPhone : public KXmlGuiWindow { @@ -87,6 +87,7 @@ private: KAction* action_quit ; KAction* action_displayVolumeControls ; KAction* action_displayDialpad ; + KAction* action_displayMessageBox ; KAction* action_configureSflPhone ; KAction* action_configureShortcut ; KAction* action_accountCreationWizard ; diff --git a/kde/src/SFLPhoneView.cpp b/kde/src/SFLPhoneView.cpp index dadf805c4b5ffaafce1809aff635bde537f5b1ec..88309f36ace92e9d4054efc8c49106b2b0122826 100755 --- a/kde/src/SFLPhoneView.cpp +++ b/kde/src/SFLPhoneView.cpp @@ -38,7 +38,7 @@ //SFLPhone #include "conf/ConfigurationDialog.h" -#include "conf/ConfigurationSkeleton.h" +#include "klib/ConfigurationSkeleton.h" #include "AccountWizard.h" #include "ActionSetAccountFirst.h" #include "SFLPhone.h" @@ -49,6 +49,7 @@ #include "lib/callmanager_interface_singleton.h" #include "lib/instance_interface_singleton.h" #include "lib/sflphone_const.h" +#include "lib/Contact.h" //ConfigurationDialog* SFLPhoneView::configDialog; @@ -68,6 +69,8 @@ SFLPhoneView::SFLPhoneView(QWidget *parent) pal.setColor(QPalette::AlternateBase, Qt::lightGray); setPalette(pal); + m_pMessageBoxW->setVisible(ConfigurationSkeleton::displayMessageBox()); + // SENDER SIGNAL RECEIVER SLOT / /**/connect(SFLPhone::model() , SIGNAL(incomingCall(Call*)) , this , SLOT(on1_incomingCall(Call*) )); /**/connect(SFLPhone::model() , SIGNAL(voiceMailNotify(const QString &, int)) , this , SLOT(on1_voiceMailNotify(const QString &, int) )); @@ -77,6 +80,8 @@ SFLPhoneView::SFLPhoneView(QWidget *parent) /**/connect(TreeWidgetCallModel::getAccountList() , SIGNAL(accountListUpdated()) , this , SLOT(updateStatusMessage() )); /**/connect(TreeWidgetCallModel::getAccountList() , SIGNAL(accountListUpdated()) , this , SLOT(updateWindowCallState() )); /**/connect(&configurationManager , SIGNAL(accountsChanged()) , TreeWidgetCallModel::getAccountList() , SLOT(updateAccounts() )); + /**/connect(m_pSendMessageLE , SIGNAL(returnPressed()) , this , SLOT(sendMessage() )); + /**/connect(m_pSendMessagePB , SIGNAL(clicked()) , this , SLOT(sendMessage() )); /* */ TreeWidgetCallModel::getAccountList()->updateAccounts(); @@ -140,10 +145,10 @@ void SFLPhoneView::typeString(QString str) } foreach (Call* call2, SFLPhone::model()->getCallList()) { - if(currentCall != call2 && call2->getState() == CALL_STATE_CURRENT) { + if(dynamic_cast<Call*>(call2) && currentCall != call2 && call2->getState() == CALL_STATE_CURRENT) { action(call2, CALL_ACTION_HOLD); } - else if(call2->getState() == CALL_STATE_DIALING) { + else if(dynamic_cast<Call*>(call2) && call2->getState() == CALL_STATE_DIALING) { candidate = call2; } } @@ -239,6 +244,37 @@ void SFLPhoneView::action(Call* call, call_action action) } } +///Select a phone number when calling using a contact +bool SFLPhoneView::selectCallPhoneNumber(Call* call2,Contact* contact) +{ + if (contact->getPhoneNumbers().count() == 1) { + call2 = SFLPhone::model()->addDialingCall(contact->getFormattedName(), SFLPhone::model()->getCurrentAccountId()); + call2->appendText(contact->getPhoneNumbers()[0]->getNumber()); + } + else if (contact->getPhoneNumbers().count() > 1) { + bool ok = false; + QHash<QString,QString> map; + QStringList list; + foreach (Contact::PhoneNumber* number, contact->getPhoneNumbers()) { + map[number->getType()+" ("+number->getNumber()+")"] = number->getNumber(); + list << number->getType()+" ("+number->getNumber()+")"; + } + QString result = QInputDialog::getItem (this, QString("Select phone number"), QString("This contact have many phone number, please select the one you wish to call"), list, 0, false, &ok); + if (ok) { + call2 = SFLPhone::model()->addDialingCall(contact->getFormattedName(), SFLPhone::model()->getCurrentAccountId()); + call2->appendText(map[result]); + } + else { + kDebug() << "Operation cancelled"; + return false; + } + } + else { + kDebug() << "This contact have no valid phone number"; + return false; + } + return true; +} /***************************************************************************** * * @@ -269,6 +305,7 @@ void SFLPhoneView::updateWindowCallState() enabledActions[ SFLPhone::Hold ] = false; enabledActions[ SFLPhone::Transfer ] = false; enabledActions[ SFLPhone::Record ] = false; + m_pMessageBoxW->setVisible(false); } else { call_state state = call->getState(); @@ -289,6 +326,7 @@ void SFLPhoneView::updateWindowCallState() break; case CALL_STATE_CURRENT: buttonIconFiles [ SFLPhone::Record ] = ICON_REC_DEL_ON ; + m_pMessageBoxW->setVisible(true); break; case CALL_STATE_DIALING: enabledActions [ SFLPhone::Hold ] = false ; @@ -300,6 +338,7 @@ void SFLPhoneView::updateWindowCallState() case CALL_STATE_HOLD: buttonIconFiles [ SFLPhone::Hold ] = ICON_UNHOLD ; actionTexts [ SFLPhone::Hold ] = ACTION_LABEL_UNHOLD ; + m_pMessageBoxW->setVisible(true); break; case CALL_STATE_FAILURE: enabledActions [ SFLPhone::Accept ] = false ; @@ -495,6 +534,12 @@ void SFLPhoneView::displayDialpad(bool checked) updateDialpad(); } +void SFLPhoneView::displayMessageBox(bool checked) +{ + ConfigurationSkeleton::setDisplayMessageBox(checked); + m_pMessageBoxW->setVisible(checked); +} + ///Input grabber void SFLPhoneView::on_widget_dialpad_typed(QString text) { @@ -755,4 +800,12 @@ void SFLPhoneView::on1_volumeChanged(const QString & /*device*/, double value) updateVolumeBar(value); } +void SFLPhoneView::sendMessage() +{ + Call* call = callTreeModel->getCurrentItem(); + if (dynamic_cast<Call*>(call) && !m_pSendMessageLE->text().isEmpty()) { + call->sendTextMessage(m_pSendMessageLE->text()); + } +} + #include "SFLPhoneView.moc" diff --git a/kde/src/SFLPhoneView.h b/kde/src/SFLPhoneView.h index 3f444acd6a37be1ab5f882178ebb8a426f0cae36..deda7b8907b25f4b4725b64f8cb73e631f7cfc14 100755 --- a/kde/src/SFLPhoneView.h +++ b/kde/src/SFLPhoneView.h @@ -47,7 +47,7 @@ class CallView; * * @short Main view * @author Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> - * @version 0.9.6 + * @version 1.1.0 */ class SFLPhoneView : public QWidget, public Ui::SFLPhone_view { @@ -93,6 +93,9 @@ public: */ int phoneNumberTypesDisplayed(); + + bool selectCallPhoneNumber(Call* call,Contact* contact); + private slots: /** * Performs the action action on the call call, then updates window. @@ -161,6 +164,8 @@ private slots: void updateVolumeBar (double _value = -1); void updateVolumeControls (); void updateDialpad (); + void sendMessage(); + public slots: @@ -201,6 +206,7 @@ public slots: void displayVolumeControls(bool checked = true); void displayDialpad(bool checked = true); + void displayMessageBox(bool checked = true); void configureSflPhone(); void accountCreationWizard(); void accept (); diff --git a/kde/src/conf/ConfigAccountList.cpp b/kde/src/conf/ConfigAccountList.cpp index 9de04ed73a3c60f3a012895e19e1fda800b7a91e..7f7572904864fc82c575ae7e5cb1582beb201676 100644 --- a/kde/src/conf/ConfigAccountList.cpp +++ b/kde/src/conf/ConfigAccountList.cpp @@ -79,7 +79,7 @@ QVector<AccountView*> ConfigAccountList::getAccountByState(QString & state) { QVector<AccountView*> v; for (int i = 0; i < accounts->size(); ++i) { - if ((*accounts)[i]->getAccountDetail(ACCOUNT_STATUS) == state) + if ((*accounts)[i]->getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == state) v += (*accounts)[i]; } return v; @@ -167,7 +167,7 @@ QVector<AccountView*> ConfigAccountList::registeredAccounts() const AccountView* current; for (int i = 0; i < accounts->count(); ++i) { current = (*accounts)[i]; - if(current->getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED) { + if(current->getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED) { kDebug() << current->getAlias() << " : " << current; registeredAccounts.append(current); } @@ -180,7 +180,7 @@ AccountView* ConfigAccountList::firstRegisteredAccount() const AccountView* current; for (int i = 0; i < accounts->count(); ++i) { current = (*accounts)[i]; - if(current->getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED) + if(current->getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED) { return current; } diff --git a/kde/src/conf/ConfigurationDialog.cpp b/kde/src/conf/ConfigurationDialog.cpp index c24fd3433d74c05e3a34ddf89d0b39afd564cbb0..3c65966eb867514b2f7efb54daf7407131432e76 100755 --- a/kde/src/conf/ConfigurationDialog.cpp +++ b/kde/src/conf/ConfigurationDialog.cpp @@ -24,7 +24,7 @@ #include <KDebug> -#include "conf/ConfigurationSkeleton.h" +#include "klib/ConfigurationSkeleton.h" #include "dlggeneral.h" #include "dlgdisplay.h" @@ -69,12 +69,16 @@ void ConfigurationDialog::updateWidgets() { dlgAudio->updateWidgets(); dlgAccounts->updateWidgets(); + dlgGeneral->updateWidgets(); + dlgAddressBook->updateWidgets(); } void ConfigurationDialog::updateSettings() { dlgAudio->updateSettings(); dlgAccounts->updateSettings(); + dlgGeneral->updateSettings(); + dlgAddressBook->updateSettings(); } bool ConfigurationDialog::hasChanged() diff --git a/kde/src/conf/ConfigurationDialog.h b/kde/src/conf/ConfigurationDialog.h index 06bc43c9ae9c398982f6116a9047ff38849fe644..4669efc65408ea650499eb6dda19a9d29ce70cb9 100755 --- a/kde/src/conf/ConfigurationDialog.h +++ b/kde/src/conf/ConfigurationDialog.h @@ -24,7 +24,7 @@ #include <kconfigdialog.h> -#include "kcfg_settings.h" +#include "klib/kcfg_settings.h" #include "SFLPhoneView.h" diff --git a/kde/src/conf/dlgaccounts.cpp b/kde/src/conf/dlgaccounts.cpp index 5f300b648060b1f392682824949aa8616c826ab0..0b1876a525cea409afe6f60d54ece59f36d13617 100755 --- a/kde/src/conf/dlgaccounts.cpp +++ b/kde/src/conf/dlgaccounts.cpp @@ -81,10 +81,13 @@ DlgAccounts::DlgAccounts(KConfigDialog* parent) setupUi(this); disconnect(keditlistbox_codec->addButton(),SIGNAL(clicked())); ConfigurationManagerInterface & configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); - button_accountUp->setIcon ( KIcon( "go-up" ) ); - button_accountDown->setIcon ( KIcon( "go-down" ) ); - button_accountAdd->setIcon ( KIcon( "list-add" ) ); - button_accountRemove->setIcon ( KIcon( "list-remove" ) ); + button_accountUp->setIcon ( KIcon( "go-up" ) ); + button_accountDown->setIcon ( KIcon( "go-down" ) ); + button_accountAdd->setIcon ( KIcon( "list-add" ) ); + button_accountRemove->setIcon ( KIcon( "list-remove" ) ); + button_add_credential->setIcon ( KIcon( "list-add" ) ); + button_remove_credential->setIcon ( KIcon( "list-remove" ) ); + accountList = new ConfigAccountList(false); loadAccountList(); loadCodecList(); @@ -101,7 +104,6 @@ DlgAccounts::DlgAccounts(KConfigDialog* parent) /**/connect(edit6_mailbox, SIGNAL(textEdited(const QString &)) , this , SLOT(changedAccountList() )); /**/connect(spinbox_regExpire, SIGNAL(editingFinished()) , this , SLOT(changedAccountList() )); /**/connect(comboBox_ni_local_address, SIGNAL(currentIndexChanged (int)) , this , SLOT(changedAccountList() )); - /**/connect(checkBox_conformRFC, SIGNAL(clicked(bool)) , this , SLOT(changedAccountList() )); /**/connect(button_accountUp, SIGNAL(clicked()) , this , SLOT(changedAccountList() )); /**/connect(button_accountDown, SIGNAL(clicked()) , this , SLOT(changedAccountList() )); /**/connect(button_accountAdd, SIGNAL(clicked()) , this , SLOT(changedAccountList() )); @@ -224,7 +226,8 @@ void DlgAccounts::saveAccount(QListWidgetItem * item) /**/account->setAccountDetail( ACCOUNT_USERNAME , edit4_user->text() ); /**/account->setAccountDetail( ACCOUNT_PASSWORD , edit5_password->text() ); /**/account->setAccountDetail( ACCOUNT_MAILBOX , edit6_mailbox->text() ); - /**/account->setAccountDetail( ACCOUNT_ENABLED , account->isChecked() ? ACCOUNT_ENABLED_TRUE : ACCOUNT_ENABLED_FALSE ); + /**/account->setAccountDetail( ACCOUNT_ENABLED , account->isChecked()?REGISTRATION_ENABLED_TRUE:REGISTRATION_ENABLED_FALSE); + /**/account->setAccountDetail( ACCOUNT_REGISTRATION_EXPIRE , QString::number(spinbox_regExpire->value()) ); /**/ /**/ /* Security */ /**/account->setAccountDetail( TLS_PASSWORD , edit_tls_private_key_password->text() ); @@ -301,14 +304,15 @@ void DlgAccounts::loadAccount(QListWidgetItem * item) loadCredentails(account->getAccountDetail(ACCOUNT_ID)); - bool ok; - int val = account->getAccountDetail(ACCOUNT_EXPIRE).toInt(&ok); - spinbox_regExpire->setValue(ok ? val : ACCOUNT_EXPIRE_DEFAULT); - - if (credentialList.size()) - edit5_password->setText( credentialList[0].password ); - +// bool ok; +// int val = account->getAccountDetail(ACCOUNT_REGISTRATION_STATUS).toInt(&ok); +// spinbox_regExpire->setValue(ok ? val : REGISTRATION_EXPIRE_DEFAULT); + foreach(CredentialData data,credentialList) { + if (data.name == account->getAccountDetail(ACCOUNT_USERNAME)) { + edit5_password->setText( data.password ); + } + } switch (account->getAccountDetail(TLS_METHOD ).toInt()) { @@ -339,7 +343,6 @@ void DlgAccounts::loadAccount(QListWidgetItem * item) /**/edit3_server->setText ( account->getAccountDetail( ACCOUNT_HOSTNAME ) ); /**/edit4_user->setText ( account->getAccountDetail( ACCOUNT_USERNAME ) ); /**/edit6_mailbox->setText ( account->getAccountDetail( ACCOUNT_MAILBOX ) ); - /**/checkBox_conformRFC->setChecked ( account->getAccountDetail( ACCOUNT_RESOLVE_ONCE ) != "TRUE" ); /**/checkbox_ZRTP_Ask_user->setChecked ( (account->getAccountDetail( ACCOUNT_DISPLAY_SAS_ONCE ) == "true")?1:0 ); /**/checkbox_SDES_fallback_rtp->setChecked ( (account->getAccountDetail( ACCOUNT_SRTP_RTP_FALLBACK ) == "true")?1:0 ); /**/checkbox_ZRTP_display_SAS->setChecked ( (account->getAccountDetail( ACCOUNT_ZRTP_DISPLAY_SAS ) == "true")?1:0 ); @@ -347,6 +350,7 @@ void DlgAccounts::loadAccount(QListWidgetItem * item) /**/checkbox_ZTRP_send_hello->setChecked ( (account->getAccountDetail( ACCOUNT_ZRTP_HELLO_HASH ) == "true")?1:0 ); /**/checkbox_stun->setChecked ( (account->getAccountDetail( ACCOUNT_SIP_STUN_ENABLED ) == "true")?1:0 ); /**/line_stun->setText ( account->getAccountDetail( ACCOUNT_SIP_STUN_SERVER ) ); + /**/spinbox_regExpire->setValue ( account->getAccountDetail( ACCOUNT_REGISTRATION_EXPIRE ).toInt() ); /**/radioButton_pa_same_as_local->setChecked ( (account->getAccountDetail( PUBLISHED_SAMEAS_LOCAL ) == "true")?1:0 ); /**/radioButton_pa_custom->setChecked ( !(account->getAccountDetail( PUBLISHED_SAMEAS_LOCAL ) == "true")?1:0 ); /**/lineEdit_pa_published_address->setText ( account->getAccountDetail( PUBLISHED_ADDRESS ) ); @@ -368,9 +372,24 @@ void DlgAccounts::loadAccount(QListWidgetItem * item) /**/combo_security_STRP->setCurrentIndex ( account->getAccountDetail( TLS_METHOD ).toInt() ); /* */ + if (account->getAccountDetail(ACCOUNT_USERNAME).isEmpty()) { + frame2_editAccounts->setTabEnabled(0,false); + frame2_editAccounts->setTabEnabled(1,false); + frame2_editAccounts->setTabEnabled(3,false); + frame2_editAccounts->setTabEnabled(4,false); + } + else { + frame2_editAccounts->setTabEnabled(0,true); + frame2_editAccounts->setTabEnabled(1,true); + frame2_editAccounts->setTabEnabled(3,true); + frame2_editAccounts->setTabEnabled(4,true); + frame2_editAccounts->setCurrentIndex(0); + } + combo_tls_method->setCurrentIndex ( combo_tls_method->findText(account->getAccountDetail(TLS_METHOD ))); ConfigurationManagerInterface & configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); + comboBox_ni_local_address->clear(); QStringList interfaceList = configurationManager.getAllIpInterfaceByName(); comboBox_ni_local_address->addItems(interfaceList); @@ -390,9 +409,9 @@ void DlgAccounts::loadAccount(QListWidgetItem * item) if(protocolIndex == 0) { // if sip selected - checkbox_stun->setChecked(account->getAccountDetail(ACCOUNT_SIP_STUN_ENABLED) == ACCOUNT_ENABLED_TRUE); + checkbox_stun->setChecked(account->getAccountDetail(ACCOUNT_SIP_STUN_ENABLED) == REGISTRATION_ENABLED_TRUE); line_stun->setText( account->getAccountDetail(ACCOUNT_SIP_STUN_SERVER) ); - //checkbox_zrtp->setChecked(account->getAccountDetail(ACCOUNT_SRTP_ENABLED) == ACCOUNT_ENABLED_TRUE); + //checkbox_zrtp->setChecked(account->getAccountDetail(ACCOUNT_SRTP_ENABLED) == REGISTRATION_ENABLED_TRUE); tab_advanced->setEnabled(true); line_stun->setEnabled(checkbox_stun->isChecked()); @@ -558,7 +577,7 @@ void DlgAccounts::updateStatusLabel(AccountView* account) if(! account ) { return; } - QString status = account->getAccountDetail(ACCOUNT_STATUS); + QString status = account->getAccountDetail(ACCOUNT_REGISTRATION_STATUS); edit7_state->setText( "<FONT COLOR=\"" + account->getStateColorName() + "\">" + status + "</FONT>" ); } @@ -692,12 +711,12 @@ void DlgAccounts::loadCredentails(QString accountId) { VectorMapStringString credentials = configurationManager.getCredentials(accountId); for (int i=0; i < credentials.size(); i++) { QListWidgetItem* newItem = new QListWidgetItem(); - newItem->setText(credentials[i][ "username" ]); + newItem->setText(credentials[i][ CONFIG_ACCOUNT_USERNAME ]); CredentialData data; data.pointer = newItem ; - data.name = credentials[i][ "username" ] ; - data.password = credentials[i][ "password" ] ; - data.realm = credentials[i][ "realm" ] ; + data.name = credentials[i][ CONFIG_ACCOUNT_USERNAME ] ; + data.password = credentials[i][ CONFIG_ACCOUNT_PASSWORD ] ; + data.realm = credentials[i][ CONFIG_ACCOUNT_REALM ] ; credentialInfo[newItem] = data; credentialList << data; list_credential->addItem(newItem); @@ -712,9 +731,9 @@ void DlgAccounts::saveCredential(QString accountId) { for (int i=0; i < list_credential->count();i++) { QListWidgetItem* currentItem = list_credential->item(i); MapStringString credentialData; - credentialData["username"] = credentialInfo[currentItem].name ; - credentialData["password"] = credentialInfo[currentItem].password ; - credentialData["realm"] = credentialInfo[currentItem].realm ; + credentialData[CONFIG_ACCOUNT_USERNAME] = credentialInfo[currentItem].name ; + credentialData[CONFIG_ACCOUNT_PASSWORD] = credentialInfo[currentItem].password ; + credentialData[CONFIG_ACCOUNT_REALM] = credentialInfo[currentItem].realm ; toReturn << credentialData; } configurationManager.setCredentials(accountId,toReturn); diff --git a/kde/src/conf/dlgaccountsbase.ui b/kde/src/conf/dlgaccountsbase.ui index 94f5f4c68cb83d067708c9d301ba76ca53571ccc..8359b8f4f91c2ea1d459d7b48db5a22284d16110 100755 --- a/kde/src/conf/dlgaccountsbase.ui +++ b/kde/src/conf/dlgaccountsbase.ui @@ -29,7 +29,7 @@ <item> <widget class="QFrame" name="frame1_accountList"> <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -62,7 +62,7 @@ <item> <widget class="QListWidget" name="listWidget_accountList"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -392,15 +392,18 @@ <string>Resgistration</string> </property> <layout class="QGridLayout" name="gridLayout_8"> - <item row="0" column="0"> - <widget class="QLabel" name="label_regExpire"> - <property name="text"> - <string>Registration expire</string> + <item row="0" column="2"> + <spacer name="horizontalSpacer_7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - <property name="buddy"> - <cstring>spinbox_regExpire</cstring> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> </property> - </widget> + </spacer> </item> <item row="0" column="1"> <widget class="KIntSpinBox" name="spinbox_regExpire"> @@ -409,25 +412,15 @@ </property> </widget> </item> - <item row="1" column="0" colspan="2"> - <widget class="QCheckBox" name="checkBox_conformRFC"> + <item row="0" column="0"> + <widget class="QLabel" name="label_regExpire"> <property name="text"> - <string>Conform to RFC 3263</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer_7"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> + <string>Registration expire</string> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> + <property name="buddy"> + <cstring>spinbox_regExpire</cstring> </property> - </spacer> + </widget> </item> </layout> </widget> @@ -738,6 +731,9 @@ <property name="enabled"> <bool>false</bool> </property> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> </widget> </item> </layout> @@ -1158,6 +1154,11 @@ <extends>QGroupBox</extends> <header>keditlistbox.h</header> </customwidget> + <customwidget> + <class>KLineEdit</class> + <extends>QLineEdit</extends> + <header>klineedit.h</header> + </customwidget> <customwidget> <class>KIntSpinBox</class> <extends>QSpinBox</extends> @@ -1168,11 +1169,6 @@ <extends>QFrame</extends> <header>kurlrequester.h</header> </customwidget> - <customwidget> - <class>KLineEdit</class> - <extends>QLineEdit</extends> - <header>klineedit.h</header> - </customwidget> </customwidgets> <resources> <include location="../qrc/resources.qrc"/> diff --git a/kde/src/conf/dlgaddressbook.cpp b/kde/src/conf/dlgaddressbook.cpp index 0766769b28ed417db1d76052112fa9546fca4452..f568fa645203908c14e5910f201ebfef0b3ba5d1 100755 --- a/kde/src/conf/dlgaddressbook.cpp +++ b/kde/src/conf/dlgaddressbook.cpp @@ -20,15 +20,52 @@ ***************************************************************************/ #include "dlgaddressbook.h" +#include "klib/ConfigurationSkeleton.h" + DlgAddressBook::DlgAddressBook(QWidget *parent) : QWidget(parent) { setupUi(this); -} + + m_pPhoneTypeList->addItem( m_mNumbertype["Work"] = new QListWidgetItem("Work" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Home"] = new QListWidgetItem("Home" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Messenger"] = new QListWidgetItem("Messenger" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Prefered number"] = new QListWidgetItem("Prefered number" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Voice"] = new QListWidgetItem("Voice" )); +// m_pPhoneTypeList->addItem( m_mNumbertype["Fax"] = new QListWidgetItem("Fax" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Mobile"] = new QListWidgetItem("Mobile" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Video"] = new QListWidgetItem("Video" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Mailbox"] = new QListWidgetItem("Mailbox" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Modem"] = new QListWidgetItem("Modem" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Car"] = new QListWidgetItem("Car" )); + m_pPhoneTypeList->addItem( m_mNumbertype["ISDN"] = new QListWidgetItem("ISDN" )); + m_pPhoneTypeList->addItem( m_mNumbertype["PCS"] = new QListWidgetItem("PCS" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Pager"] = new QListWidgetItem("Pager" )); + m_pPhoneTypeList->addItem( m_mNumbertype["Other..."] = new QListWidgetItem("Other..." )); + QStringList list = ConfigurationSkeleton::phoneTypeList(); + foreach(QListWidgetItem* i,m_mNumbertype) { + i->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + i->setCheckState((list.indexOf(m_mNumbertype.key(i)) != -1)?Qt::Checked:Qt::Unchecked); + } +} DlgAddressBook::~DlgAddressBook() { } +void DlgAddressBook::updateWidgets() +{ + +} + +void DlgAddressBook::updateSettings() +{ + QStringList list; + foreach(QListWidgetItem* i,m_mNumbertype) { + if (i->checkState() == Qt::Checked) + list << m_mNumbertype.key(i); + } + ConfigurationSkeleton::setPhoneTypeList(list); +} diff --git a/kde/src/conf/dlgaddressbook.h b/kde/src/conf/dlgaddressbook.h index 94ec8a671e161434fb5a841342c39fd959feb70a..f46dee3bd0dc61cf4a700b3c8642420a567f5d0d 100755 --- a/kde/src/conf/dlgaddressbook.h +++ b/kde/src/conf/dlgaddressbook.h @@ -21,7 +21,10 @@ #ifndef DLGADDRESSBOOK_H #define DLGADDRESSBOOK_H -#include <QWidget> +#include <QtCore/QHash> +#include <QtCore/QString> +#include <QtGui/QWidget> +#include <QtGui/QListWidgetItem> #include "ui_dlgaddressbookbase.h" @@ -36,6 +39,14 @@ public: ~DlgAddressBook(); +private: + QHash<QString,QListWidgetItem*> m_mNumbertype; + +public slots: + void updateWidgets(); + void updateSettings(); + + }; #endif diff --git a/kde/src/conf/dlgaddressbookbase.ui b/kde/src/conf/dlgaddressbookbase.ui index e7f4964bf3500761158f832f10a800c4d9d4ba7e..245f8a17132ff4aae99b7c382f2f3af426052020 100755 --- a/kde/src/conf/dlgaddressbookbase.ui +++ b/kde/src/conf/dlgaddressbookbase.ui @@ -22,178 +22,27 @@ </widget> </item> <item> - <widget class="QWidget" name="widget_configAddressBookGeneral" native="true"> - <property name="enabled"> - <bool>false</bool> + <widget class="QLabel" name="m_pPhonetypeL"> + <property name="text"> + <string>Use contact from the following phone number category:</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <property name="leftMargin"> - <number>0</number> - </property> - <item> - <widget class="QWidget" name="widget_maxResults" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <property name="spacing"> - <number>-1</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>5</number> - </property> - <property name="rightMargin"> - <number>5</number> - </property> - <property name="bottomMargin"> - <number>5</number> - </property> - <item> - <widget class="QLabel" name="label_maxResults"> - <property name="text"> - <string>Maximum results</string> - </property> - <property name="buddy"> - <cstring>horizontalSlider_maxResults</cstring> - </property> - </widget> - </item> - <item> - <widget class="QSlider" name="horizontalSlider_maxResults"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimum"> - <number>25</number> - </property> - <property name="maximum"> - <number>50</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="KIntSpinBox" name="kcfg_maxResults"/> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QCheckBox" name="kcfg_displayPhoto"> - <property name="text"> - <string>Display photo if available</string> - </property> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_displayTypes"> - <property name="title"> - <string>Display phone numbers of these types :</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_7"> - <item> - <widget class="QCheckBox" name="kcfg_business"> - <property name="text"> - <string>Work</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="kcfg_mobile"> - <property name="text"> - <string>Mobile</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="kcfg_home"> - <property name="text"> - <string>Home</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> </widget> </item> <item> - <spacer name="verticalSpacer_configAddressBook"> - <property name="orientation"> - <enum>Qt::Vertical</enum> + <widget class="QListWidget" name="m_pPhoneTypeList"> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>72</height> - </size> + <property name="sortingEnabled"> + <bool>true</bool> </property> - </spacer> + </widget> </item> </layout> </widget> - <customwidgets> - <customwidget> - <class>KIntSpinBox</class> - <extends>QSpinBox</extends> - <header>knuminput.h</header> - </customwidget> - </customwidgets> <resources/> - <connections> - <connection> - <sender>horizontalSlider_maxResults</sender> - <signal>valueChanged(int)</signal> - <receiver>kcfg_maxResults</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>265</x> - <y>67</y> - </hint> - <hint type="destinationlabel"> - <x>326</x> - <y>70</y> - </hint> - </hints> - </connection> - <connection> - <sender>kcfg_maxResults</sender> - <signal>valueChanged(int)</signal> - <receiver>horizontalSlider_maxResults</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>326</x> - <y>70</y> - </hint> - <hint type="destinationlabel"> - <x>265</x> - <y>67</y> - </hint> - </hints> - </connection> - <connection> - <sender>kcfg_enableAddressBook</sender> - <signal>toggled(bool)</signal> - <receiver>widget_configAddressBookGeneral</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>92</x> - <y>25</y> - </hint> - <hint type="destinationlabel"> - <x>91</x> - <y>39</y> - </hint> - </hints> - </connection> - </connections> + <connections/> </ui> diff --git a/kde/src/conf/dlgaudio.cpp b/kde/src/conf/dlgaudio.cpp index ae9bbd966f15f5b8f3dce3c9969cac1adb318800..95a77beb2d5cd860da3b144f41cce17ff382af7c 100755 --- a/kde/src/conf/dlgaudio.cpp +++ b/kde/src/conf/dlgaudio.cpp @@ -22,9 +22,10 @@ #include <KLineEdit> #include "lib/configurationmanager_interface_singleton.h" -#include "conf/ConfigurationSkeleton.h" +#include "klib/ConfigurationSkeleton.h" #include "conf/ConfigurationDialog.h" #include <QtGui/QHeaderView> +#include <KStandardDirs> #include "lib/sflphone_const.h" @@ -36,9 +37,13 @@ DlgAudio::DlgAudio(KConfigDialog *parent) KUrlRequester_ringtone->setMode(KFile::File | KFile::ExistingOnly); KUrlRequester_ringtone->lineEdit()->setObjectName("kcfg_ringtone"); KUrlRequester_ringtone->lineEdit()->setReadOnly(true); + KUrlRequester_ringtone->setUrl( KStandardDirs::realFilePath(ConfigurationSkeleton::ringtone())); + + + ConfigurationManagerInterface& configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); KUrlRequester_destinationFolder->setMode(KFile::Directory|KFile::ExistingOnly|KFile::LocalOnly); - KUrlRequester_destinationFolder->setUrl(KUrl(QDir::home().path())); + KUrlRequester_destinationFolder->setUrl(KUrl(configurationManager.getRecordPath())); KUrlRequester_destinationFolder->lineEdit()->setObjectName("kcfg_destinationFolder"); KUrlRequester_destinationFolder->lineEdit()->setReadOnly(true); @@ -63,8 +68,10 @@ void DlgAudio::updateSettings() //alsaPlugin ConfigurationSkeleton * skeleton = ConfigurationSkeleton::self(); skeleton->setAlsaPlugin(box_alsaPlugin->currentText()); - - //codecTableHasChanged = false; + skeleton->setRingtone(KUrlRequester_ringtone->lineEdit()->text()); + + ConfigurationManagerInterface& configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); + configurationManager.setRecordPath(KUrlRequester_destinationFolder->lineEdit()->text()); } bool DlgAudio::hasChanged() diff --git a/kde/src/conf/dlgaudio.h b/kde/src/conf/dlgaudio.h index 5b9a9885e3f41c5ed6539c38c011761e65b0d774..c3d7fa7e326beabcf5403b5d5c8978fc6de074ed 100755 --- a/kde/src/conf/dlgaudio.h +++ b/kde/src/conf/dlgaudio.h @@ -25,7 +25,7 @@ #include <kconfigdialog.h> #include "ui_dlgaudiobase.h" -#include "conf/ConfigurationSkeleton.h" +#include "klib/ConfigurationSkeleton.h" /** @author Jérémy Quentin <jeremy.quentin@gmail.com> diff --git a/kde/src/conf/dlggeneral.cpp b/kde/src/conf/dlggeneral.cpp index c99d01b61ca550f36c8e875ed72051a9993f7700..3424327b6c31b004a7b8becad403eb9979221b44 100755 --- a/kde/src/conf/dlggeneral.cpp +++ b/kde/src/conf/dlggeneral.cpp @@ -22,15 +22,28 @@ #include <QToolButton> #include <QAction> +#include "klib/ConfigurationSkeleton.h" +#include "conf/ConfigurationDialog.h" + DlgGeneral::DlgGeneral(QWidget *parent) : QWidget(parent) { setupUi(this); connect(toolButton_historyClear, SIGNAL(clicked()), this, SIGNAL(clearCallHistoryAsked())); -} + kcfg_historyMax->setValue(ConfigurationSkeleton::historyMax()); +} DlgGeneral::~DlgGeneral() { } +void DlgGeneral::updateWidgets() +{ + +} + +void DlgGeneral::updateSettings() +{ + ConfigurationSkeleton::setHistoryMax(kcfg_historyMax->value()); +} \ No newline at end of file diff --git a/kde/src/conf/dlggeneral.h b/kde/src/conf/dlggeneral.h index 26719ac2cc06fd510d0dcf3f698a00db06dbad80..92a6c002a906d4ed297ec6bb991a7fcbad85d425 100755 --- a/kde/src/conf/dlggeneral.h +++ b/kde/src/conf/dlggeneral.h @@ -38,6 +38,11 @@ public: //Destructor ~DlgGeneral(); +public slots: + //Mutator + void updateWidgets(); + void updateSettings(); + signals: void clearCallHistoryAsked(); diff --git a/kde/src/dbus/configurationmanager-introspec.xml b/kde/src/dbus/configurationmanager-introspec.xml index 926ff774de75a99636920b3dc711ab6914695cb9..50c93ca1355a2c402799407034c4e44343886730 100755 --- a/kde/src/dbus/configurationmanager-introspec.xml +++ b/kde/src/dbus/configurationmanager-introspec.xml @@ -37,9 +37,9 @@ <li>DISPLAY_NAMEL: The display name</li> <li>STUN_ENABLE: True or False (Default: False)</li> <li>STUN_SERVER: The STUN server address</li> - <li>REGISTRATION_STATUS: The account registration status. Should be Registered to make calls.</li> - <li>REGISTRATION_STATE_CODE</li> - <li>REGISTRATION_STATE_DESCRIPTION</li> + <li>ACCOUNT_REGISTRATION_STATUS: The account registration status. Should be Registered to make calls.</li> + <li>ACCOUNT_REGISTRATION_STATE_CODE</li> + <li>ACCOUNT_REGISTRATION_STATE_DESC</li> <li>SRTP_KEY_EXCHANGE</li> <li>SRTP_ENABLE: Whether or not voice communication are encrypted - True or False (Default: False)</li> <li>SRTP_RTP_FALLBACK</li> @@ -447,6 +447,21 @@ <signal name="accountsChanged" tp:name-for-bindings="accountsChanged"> </signal> + <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged"> + <arg type="s" name="accountID"/> + <arg type="i" name="registration_state"/> + </signal> + + <signal name="stunStatusFailure" tp:name-for_bindings="stunStatusFailure"> + <arg type="s" name="reason"> + </arg> + </signal> + + <signal name="stunStatusSuccess" tp:name-for_bindings="stunStatusSuccess"> + <arg type="s" name="message"> + </arg> + </signal> + <signal name="errorAlert" tp:name-for-bindings="errorAlert"> <arg type="i" name="code"> </arg> diff --git a/kde/src/AkonadiBackend.cpp b/kde/src/klib/AkonadiBackend.cpp similarity index 77% rename from kde/src/AkonadiBackend.cpp rename to kde/src/klib/AkonadiBackend.cpp index 7677746d4f05f29761b19a4491c609818da18e44..f47c793f6d494feee856dbd428ebc1e65c44ffed 100644 --- a/kde/src/AkonadiBackend.cpp +++ b/kde/src/klib/AkonadiBackend.cpp @@ -43,14 +43,17 @@ #include <kabc/phonenumber.h> //SFLPhone library -#include "lib/Contact.h" +#include "../lib/Contact.h" +#include "../lib/AccountList.h" +#include "../lib/Account.h" //SFLPhone -#include "SFLPhone.h" -#include "SFLPhoneView.h" +//#include "SFLPhone.h" +//#include "SFLPhoneView.h" ///Init static attributes AkonadiBackend* AkonadiBackend::m_pInstance = 0; +CallModel<>* AkonadiBackend::m_pModel = 0; ///Constructor AkonadiBackend::AkonadiBackend(QObject* parent) : ContactBackend(parent) @@ -58,6 +61,12 @@ AkonadiBackend::AkonadiBackend(QObject* parent) : ContactBackend(parent) //QTimer::singleShot( 0, this, SLOT( delayedInit() ) ); m_pSession = new Akonadi::Session( "SFLPhone::instance" ); + if ( not m_pModel ) { + m_pModel = new CallModel<>(CallModel<>::ActiveCall); + m_pModel->initCall(); + m_pModel->initHistory(); + } + // fetching all collections containing emails recursively, starting at the root collection Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob( Akonadi::Collection::root(), Akonadi::CollectionFetchJob::Recursive, this ); job->fetchScope().setContentMimeTypes( QStringList() << "text/directory" ); @@ -86,10 +95,19 @@ ContactBackend* AkonadiBackend::getInstance() return m_pInstance; } -///Find contact using a phone number -Contact* AkonadiBackend::getContactByPhone(const QString& phoneNumber) +///Find contact using a phone number, +///@param resolveDNS check if the DNS is used by an account, then assume contact with that phone number / extension is the same as the caller +Contact* AkonadiBackend::getContactByPhone(const QString& phoneNumber,bool resolveDNS) { - return m_ContactByPhone[phoneNumber]; + if (!resolveDNS || phoneNumber.indexOf("@") == -1) + return m_ContactByPhone[phoneNumber]; + else if (!getHostNameFromPhone(phoneNumber).isEmpty() && m_ContactByPhone[getUserFromPhone(phoneNumber)]) { + foreach (Account* a, m_pModel->getAccountList()->getAccounts()) { + if (a->getAccountDetail(ACCOUNT_HOSTNAME) == getHostNameFromPhone(phoneNumber)) + return m_ContactByPhone[getUserFromPhone(phoneNumber)]; + } + } + return nullptr; } ///Find contact by UID @@ -109,10 +127,9 @@ Contact* AkonadiBackend::getContactByUid(const QString& uid) ContactList AkonadiBackend::update(Akonadi::Collection collection) { m_Collection = collection; - ContactList contacts; if ( !collection.isValid() ) { kDebug() << "The current collection is not valid"; - return contacts; + return ContactList(); } Akonadi::RecursiveItemFetchJob *job = new Akonadi::RecursiveItemFetchJob( collection, QStringList() << KABC::Addressee::mimeType() << KABC::ContactGroup::mimeType()); @@ -145,6 +162,7 @@ ContactList AkonadiBackend::update(Akonadi::Collection collection) aContact->setFamilyName (tmp.familyName() ); aContact->setOrganization (tmp.organization() ); aContact->setPreferredEmail (tmp.preferredEmail() ); + aContact->setDepartment (tmp.department() ); aContact->setUid (tmp.uid() ); aContact->setPhoneNumbers (newNumbers ); @@ -152,32 +170,32 @@ ContactList AkonadiBackend::update(Akonadi::Collection collection) aContact->setPhoto(new QPixmap(QPixmap::fromImage( tmp.photo().data()).scaled(QSize(48,48)))); else aContact->setPhoto(0); - contacts << aContact; } } + m_pContacts = m_ContactByUid.values(); } - return contacts; + return m_ContactByUid.values(); } ///Edit backend value using an updated frontend contact -void AkonadiBackend::editContact(Contact* contact) +void AkonadiBackend::editContact(Contact* contact,QWidget* parent) { KABC::Addressee ct = m_AddrHash[contact->getUid()]; if (ct.uid() != contact->getUid()) { kDebug() << "Contact not found"; return; } - Akonadi::ContactEditor *editor = new Akonadi::ContactEditor( Akonadi::ContactEditor::EditMode, SFLPhone::app()->view() ); + Akonadi::ContactEditor *editor = new Akonadi::ContactEditor( Akonadi::ContactEditor::EditMode, parent ); Akonadi::Item item; item.setPayload<KABC::Addressee>(ct); editor->loadContact(item); - KDialog* dlg = new KDialog(SFLPhone::app()->view()); + KDialog* dlg = new KDialog(parent); dlg->setMainWidget(editor); dlg->exec(); } ///Add a new contact -void AkonadiBackend::addNewContact(Contact* contact) +void AkonadiBackend::addNewContact(Contact* contact,QWidget* parent) { KABC::Addressee newContact; newContact.setNickName ( contact->getNickName() ); @@ -185,6 +203,7 @@ void AkonadiBackend::addNewContact(Contact* contact) newContact.setGivenName ( contact->getFirstName() ); newContact.setFamilyName ( contact->getSecondName() ); newContact.setOrganization ( contact->getOrganization() ); + newContact.setDepartment ( contact->getDepartment() ); //newContact.setPreferredEmail ( contact->getPreferredEmail() );//TODO foreach (Contact::PhoneNumber* nb, contact->getPhoneNumbers()) { @@ -208,14 +227,13 @@ void AkonadiBackend::addNewContact(Contact* contact) newContact.insertPhoneNumber(pn); } - //aContact->setPhoneNumbers (newNumbers );//TODO - Akonadi::ContactEditor *editor = new Akonadi::ContactEditor( Akonadi::ContactEditor::CreateMode, SFLPhone::app()->view() ); + Akonadi::ContactEditor *editor = new Akonadi::ContactEditor( Akonadi::ContactEditor::CreateMode, parent ); editor->setContactTemplate(newContact); - KDialog* dlg = new KDialog(SFLPhone::app()->view()); + KDialog* dlg = new KDialog(parent); dlg->setMainWidget(editor); dlg->exec(); @@ -225,6 +243,18 @@ void AkonadiBackend::addNewContact(Contact* contact) } } +///Implement virtual pure method +void AkonadiBackend::editContact(Contact* contact) +{ + editContact(contact,0); +} + +///Implement virtual pure method +void AkonadiBackend::addNewContact(Contact* contact) +{ + addNewContact(contact,0); +} + /***************************************************************************** * * @@ -244,5 +274,35 @@ void AkonadiBackend::collectionsReceived( const Akonadi::Collection::List& list ///Update the contact list even without a new collection ContactList AkonadiBackend::update_slot() { - return update(m_Collection); + return m_pContacts;//update(m_Collection); +} + +/***************************************************************************** + * * + * Helpers * + * * + ****************************************************************************/ + +///Return the extension/user of an URI (<sip:12345@exemple.com>) +QString AkonadiBackend::getUserFromPhone(QString phoneNumber) +{ + if (phoneNumber.indexOf("@") != -1) { + QString user = phoneNumber.split("@")[0]; + if (user.indexOf(":") != -1) { + return user.split(":")[1]; + } + else { + return user; + } + } + return phoneNumber; +} + +///Return the domaine of an URI (<sip:12345@exemple.com>) +QString AkonadiBackend::getHostNameFromPhone(QString phoneNumber) +{ + if (phoneNumber.indexOf("@") != -1) { + return phoneNumber.split("@")[1].left(phoneNumber.split("@")[1].size()-1); + } + return ""; } \ No newline at end of file diff --git a/kde/src/AkonadiBackend.h b/kde/src/klib/AkonadiBackend.h similarity index 72% rename from kde/src/AkonadiBackend.h rename to kde/src/klib/AkonadiBackend.h index a0494d9633201414fb595d4f8ad2183b3366e0ee..e2d9a57c2204a1b2d544b20bf9952bb0cd42f55f 100644 --- a/kde/src/AkonadiBackend.h +++ b/kde/src/klib/AkonadiBackend.h @@ -20,7 +20,9 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * **************************************************************************/ -#include <lib/ContactBackend.h> +#include "../lib/ContactBackend.h" +#include "../lib/CallModel.h" +#include "../lib/typedefs.h" #include <akonadi/collectionmodel.h> //Qt @@ -41,27 +43,34 @@ namespace Akonadi { //SFLPhone class Contact; -typedef QList<Contact*> ContactList; - ///@class AkonadiBackend Implement a backend for Akonadi -class AkonadiBackend : public ContactBackend { +class LIB_EXPORT AkonadiBackend : public ContactBackend { Q_OBJECT public: static ContactBackend* getInstance(); - Contact* getContactByPhone ( const QString& phoneNumber ); - Contact* getContactByUid ( const QString& uid ); - void editContact ( Contact* contact ); - void addNewContact ( Contact* contact ); + Contact* getContactByPhone ( const QString& phoneNumber ,bool resolveDNS = false ); + Contact* getContactByUid ( const QString& uid ); + void editContact ( Contact* contact , QWidget* parent = 0 ); + void addNewContact ( Contact* contact , QWidget* parent = 0 ); + + virtual void editContact ( Contact* contact ); + virtual void addNewContact ( Contact* contact ); private: AkonadiBackend(QObject* parent); virtual ~AkonadiBackend(); + //Helper + QString getUserFromPhone(QString phoneNumber); + QString getHostNameFromPhone(QString phoneNumber); + //Attributes static AkonadiBackend* m_pInstance ; + static CallModel<>* m_pModel ; Akonadi::Session* m_pSession ; Akonadi::Collection m_Collection ; QHash<QString,KABC::Addressee> m_AddrHash ; + ContactList m_pContacts ; protected: ContactList update_slot(); diff --git a/kde/src/klib/CMakeLists.txt b/kde/src/klib/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ac2581263fb133df34b900ee27bd2db3b9dadb98 --- /dev/null +++ b/kde/src/klib/CMakeLists.txt @@ -0,0 +1,67 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +ADD_DEFINITIONS("-std=c++0x") + +ADD_DEFINITIONS( + ${QT_DEFINITIONS} + -fexceptions +) + +PROJECT(ksflphone) + +SET ( KDE4_KABC_LIBS -lkabc ) + + +add_subdirectory(dataengine) + +SET(LOCAL_CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/") +SET(CMAKE_MODULE_PATH "${LOCAL_CMAKE_MODULE_PATH}") + +FIND_PACKAGE ( KDE4 REQUIRED ) +FIND_PACKAGE ( Qt4 REQUIRED ) + +INCLUDE ( KDE4Defaults ) + +set(GENERIC_LIB_VERSION "1.1.0") + +INCLUDE_DIRECTORIES ( ${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) + +#File to compile +set( ksflphone_LIB_SRCS + HelperFunctions.cpp + AkonadiBackend.cpp + SortableDockCommon.cpp + ConfigurationSkeleton.cpp +) + +KDE4_ADD_KCFG_FILES(ksflphone_LIB_SRCS kcfg_settings.kcfgc) + +kde4_add_library( ksflphone SHARED ${ksflphone_LIB_SRCS} ) + +target_link_libraries( ksflphone + qtsflphone + ${QT_QTCORE_LIBRARY} + ${KDEPIMLIBS_AKONADI_KMIME_LIBS} + ${KDEPIMLIBS_AKONADI_LIBS} + ${KDEPIMLIBS_AKONADI_CONTACT_LIBS} + ${KDE4_KDEUI_LIBS} +) + +set_target_properties( ksflphone + PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} +) + +set( ksflphone_LIB_HDRS + AkonadiBackend.h + HelperFunctions.h + SortableDockCommon.h +) + +INSTALL(FILES sflphone-client-kde.kcfg DESTINATION ${KCFG_INSTALL_DIR}) + +install( FILES ${ksflphone_LIB_HDRS} + DESTINATION ${INCLUDE_INSTALL_DIR}/ksflphone + COMPONENT Devel +) + +install( TARGETS ksflphone ${INSTALL_TARGETS_DEFAULT_ARGS} ) diff --git a/kde/src/conf/ConfigurationSkeleton.cpp b/kde/src/klib/ConfigurationSkeleton.cpp similarity index 76% rename from kde/src/conf/ConfigurationSkeleton.cpp rename to kde/src/klib/ConfigurationSkeleton.cpp index 3fadaea56a68bc8417ba73df0ce67027d86d4c1d..c7d07ef85067a9293f81c62b43ca0c3f5e02b2ae 100755 --- a/kde/src/conf/ConfigurationSkeleton.cpp +++ b/kde/src/klib/ConfigurationSkeleton.cpp @@ -20,8 +20,8 @@ ***************************************************************************/ #include "ConfigurationSkeleton.h" -#include "lib/configurationmanager_interface_singleton.h" -#include "lib/sflphone_const.h" +#include "../lib/configurationmanager_interface_singleton.h" +#include "../lib/sflphone_const.h" //KDE #include <KDebug> @@ -66,19 +66,19 @@ void ConfigurationSkeleton::readConfig() //Call history settings //setEnableHistory(true); - setHistoryMax(1000);//configurationManager.getHistoryLimit()); + setHistoryMax(configurationManager.getHistoryLimit()); //////////////////////// ////Display settings//// //////////////////////// //Notification settings - setNotifOnCalls(true); - setNotifOnMessages(true);//configurationManager.getMailNotify()); + //setNotifOnCalls(true); + setNotifOnMessages(configurationManager.getMailNotify()); //Window display settings - setDisplayOnStart(true); - setDisplayOnCalls(true); + //setDisplayOnStart(true); + //setDisplayOnCalls(true); ///////////////////////// ////Accounts settings//// @@ -98,12 +98,9 @@ void ConfigurationSkeleton::readConfig() //ringtones settings setEnableRingtones(true); - QString ringtone = ""; - if(ringtone.isEmpty()) { - setRingtone(QString(SHARE_INSTALL_PREFIX) + "sflphone/ringtones/konga.ul"); - } - else { - setRingtone(ringtone); + //QString ringtone = ""; + if(ringtone().isEmpty()) { + setRingtone(QString(SHARE_INSTALL_PREFIX) + "/sflphone/ringtones/konga.ul"); } //codecs settings @@ -131,31 +128,17 @@ void ConfigurationSkeleton::readConfig() //if(!ok) kDebug() << "outputDevice is not a number"; //setAlsaOutputDevice(outputDevice); - /////////////////////// - ////Record settings//// - /////////////////////// - - QString recordPath = configurationManager.getRecordPath(); - if(! recordPath.isEmpty()) { - setDestinationFolder(recordPath); - } - else { - setDestinationFolder(QDir::home().path()); - } - - - ///////////////////////////// ////Address book settings//// ///////////////////////////// MapStringInt addressBookSettings = configurationManager.getAddressbookSettings().value(); setEnableAddressBook(addressBookSettings[ADDRESSBOOK_ENABLE]); - setMaxResults(addressBookSettings[ADDRESSBOOK_MAX_RESULTS]); - setDisplayPhoto(addressBookSettings[ADDRESSBOOK_DISPLAY_CONTACT_PHOTO]); - setBusiness(addressBookSettings[ADDRESSBOOK_DISPLAY_BUSINESS]); - setMobile(addressBookSettings[ADDRESSBOOK_DISPLAY_MOBILE]); - setHome(addressBookSettings[ADDRESSBOOK_DISPLAY_HOME]); +// setMaxResults(addressBookSettings[ADDRESSBOOK_MAX_RESULTS]); +// setDisplayPhoto(addressBookSettings[ADDRESSBOOK_DISPLAY_CONTACT_PHOTO]); +// setBusiness(addressBookSettings[ADDRESSBOOK_DISPLAY_BUSINESS]); +// setMobile(addressBookSettings[ADDRESSBOOK_DISPLAY_MOBILE]); +// setHome(addressBookSettings[ADDRESSBOOK_DISPLAY_HOME]); ///////////////////////////// ///////Hooks settings//////// @@ -176,7 +159,7 @@ void ConfigurationSkeleton::writeConfig() { //ConfigurationSkeleton::writeConfig(); kDebug() << "Writing config"; - /*ConfigurationManagerInterface & configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); + ConfigurationManagerInterface & configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); //////////////////////// @@ -200,7 +183,8 @@ void ConfigurationSkeleton::writeConfig() //Notification settings //if(notifOnCalls() != configurationManager.getNotify()) configurationManager.setNotify(); - //if(notifOnMessages() != configurationManager.getMailNotify()) configurationManager.setMailNotify(); +// if(notifOnMessages() != configurationManager.getMailNotify()) configurationManager.setMailNotify(); + //configurationManager.setMailNotify(notifOnMessages()); //Window display settings //WARNING états inversés @@ -222,15 +206,15 @@ void ConfigurationSkeleton::writeConfig() kDebug() << "Writing Audio settings"; //Audio Interface settings - int prevManager = configurationManager.getAudioManager(); - int newManager = interface(); - if(prevManager != newManager) { - configurationManager.setAudioManager(newManager); - } +// int prevManager = configurationManager.getAudioManager(); +// int newManager = interface(); +// if(prevManager != newManager) { +// configurationManager.setAudioManager(newManager); +// } //ringtones settings - if(enableRingtones() != configurationManager.isRingtoneEnabled()) configurationManager.ringtoneEnabled(); - configurationManager.setRingtoneChoice(ringtone()); +// if(enableRingtones() != configurationManager.isRingtoneEnabled()) configurationManager.ringtoneEnabled(); +// configurationManager.setRingtoneChoice(ringtone()); //codecs settings //kDebug() << "activeCodecList = " << activeCodecList(); @@ -238,12 +222,12 @@ void ConfigurationSkeleton::writeConfig() //alsa settings - if(prevManager == CONST_ALSA && newManager == EnumInterface::ALSA) { - kDebug() << "setting alsa settings"; - configurationManager.setOutputAudioPlugin(alsaPlugin()); - configurationManager.setAudioInputDevice(alsaInputDevice()); - configurationManager.setAudioOutputDevice(alsaOutputDevice()); - } +// if(prevManager == CONST_ALSA && newManager == EnumInterface::ALSA) { +// kDebug() << "setting alsa settings"; +// configurationManager.setOutputAudioPlugin(alsaPlugin()); +// configurationManager.setAudioInputDevice(alsaInputDevice()); +// configurationManager.setAudioOutputDevice(alsaOutputDevice()); +// } /////////////////////// @@ -252,8 +236,8 @@ void ConfigurationSkeleton::writeConfig() kDebug() << "Writing Record settings"; - QString destination = destinationFolder(); - configurationManager.setRecordPath(destination); +// QString destination = destinationFolder(); +// configurationManager.setRecordPath(destination); ///////////////////////////// @@ -264,11 +248,11 @@ void ConfigurationSkeleton::writeConfig() MapStringInt addressBookSettings = MapStringInt(); addressBookSettings[ADDRESSBOOK_ENABLE] = enableAddressBook(); - addressBookSettings[ADDRESSBOOK_MAX_RESULTS] = maxResults(); - addressBookSettings[ADDRESSBOOK_DISPLAY_CONTACT_PHOTO] = displayPhoto(); - addressBookSettings[ADDRESSBOOK_DISPLAY_BUSINESS] = business(); - addressBookSettings[ADDRESSBOOK_DISPLAY_MOBILE] = mobile(); - addressBookSettings[ADDRESSBOOK_DISPLAY_HOME] = home(); +// addressBookSettings[ADDRESSBOOK_MAX_RESULTS] = maxResults(); +// addressBookSettings[ADDRESSBOOK_DISPLAY_CONTACT_PHOTO] = displayPhoto(); +// addressBookSettings[ADDRESSBOOK_DISPLAY_BUSINESS] = business(); +// addressBookSettings[ADDRESSBOOK_DISPLAY_MOBILE] = mobile(); +// addressBookSettings[ADDRESSBOOK_DISPLAY_HOME] = home(); configurationManager.setAddressbookSettings(addressBookSettings); ///////////////////////////// @@ -286,7 +270,7 @@ void ConfigurationSkeleton::writeConfig() hooksSettings[HOOKS_COMMAND] = hooksCommand(); configurationManager.setHookSettings(hooksSettings); - kDebug() << "Finished to write config\n";*/ + kDebug() << "Finished to write config\n"; ConfigurationSkeletonBase::writeConfig(); } diff --git a/kde/src/conf/ConfigurationSkeleton.h b/kde/src/klib/ConfigurationSkeleton.h similarity index 95% rename from kde/src/conf/ConfigurationSkeleton.h rename to kde/src/klib/ConfigurationSkeleton.h index cd99acd48a1770c1f31181f2677f399355c01fd2..389535463c510deb5b91dc2fc250888d917522a8 100755 --- a/kde/src/conf/ConfigurationSkeleton.h +++ b/kde/src/klib/ConfigurationSkeleton.h @@ -22,10 +22,10 @@ #define CONFIGURATIONSKELETON_H #include <QWidget> +#include "../lib/typedefs.h" -#include "kcfg_settings.h" +#include "src/klib/kcfg_settings.h" //#include "CodecListModel.h" -#include "AccountListModel.h" /** @author Jérémy Quentin <jeremy.quentin@gmail.com> @@ -38,7 +38,7 @@ This class reimplements the writeConfig and readConfig functions to ask the daemon instead of the normal behavior (read and write in a kconfig file). */ -class ConfigurationSkeleton : public ConfigurationSkeletonBase +class LIB_EXPORT ConfigurationSkeleton : public ConfigurationSkeletonBase { Q_OBJECT diff --git a/kde/src/klib/HelperFunctions.cpp b/kde/src/klib/HelperFunctions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ef9f2f9320d076ac8be7839494a38180c5e861e --- /dev/null +++ b/kde/src/klib/HelperFunctions.cpp @@ -0,0 +1,27 @@ +#include "HelperFunctions.h" + +//Qt +#include <QtCore/QString> +#include <QtCore/QVariant> + +//SFLPhone +#include "../lib/Contact.h" + +ContactHash HelperFunctions::toHash(QList<Contact*> contacts) { + QHash<QString,QHash<QString,QVariant> > hash; + for (int i=0;i<contacts.size();i++) { + Contact* cont = contacts[i]; + QHash<QString,QVariant> conth = cont->toHash(); + conth["phoneCount"] = cont->getPhoneNumbers().size(); + if (cont->getPhoneNumbers().size() == 1) { + conth["phoneNumber"] = cont->getPhoneNumbers()[0]->getNumber(); + conth["phoneType" ] = cont->getPhoneNumbers()[0]->getType(); + } + else { + conth["phoneNumber"] = QString::number(cont->getPhoneNumbers().size())+" numbers"; + conth["phoneType" ] = ""; + } + hash[contacts[i]->getUid()] = conth; + } + return hash; +} \ No newline at end of file diff --git a/kde/src/klib/HelperFunctions.h b/kde/src/klib/HelperFunctions.h new file mode 100644 index 0000000000000000000000000000000000000000..2ff2dff4475067edc853f149b15ef4d33ba3e34f --- /dev/null +++ b/kde/src/klib/HelperFunctions.h @@ -0,0 +1,22 @@ +#ifndef HELPER_FUNCTIONS +#define HELPER_FUNCTIONS + +//Qt +#include <QtCore/QString> +#include <QtCore/QVariant> +#include <QtCore/QHash> +#include <QtCore/QList> + +//SFLPhone +#include "../lib/Contact.h" + +//Typedef +typedef QHash<QString,QHash<QString,QVariant> > ContactHash; + +///@class HelperFunctions little visitor not belonging to libqtsflphone +///Ramdom mix of dynamic property and transtypping +class LIB_EXPORT HelperFunctions { +public: + static ContactHash toHash(QList<Contact*> contacts); +}; +#endif \ No newline at end of file diff --git a/kde/src/klib/SortableDockCommon.cpp b/kde/src/klib/SortableDockCommon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc33fd17ae5298456ade30a8c7ee9475def89454 --- /dev/null +++ b/kde/src/klib/SortableDockCommon.cpp @@ -0,0 +1,53 @@ +#include "SortableDockCommon.h" + +//Qt +#include <QtCore/QDateTime> +#include <QtCore/QStringList> +#include <QtCore/QTimer> + +//SFLPhone +#include "../lib/Call.h" +#include "../lib/Contact.h" +#include "../lib/CallModel.h" +#include "AkonadiBackend.h" + +///StaticEventHandler constructor +StaticEventHandler::StaticEventHandler(QObject* parent, QStringList* list) : QObject(parent),m_pList(list) +{ + QTimer* timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(update())); + timer->start(86400000); //1 day + update(); +} + +///Update the days constant, necessary to cycle after midnight +void StaticEventHandler::update() +{ + (*m_pList)= { + "Today" ,//0 + "Yesterday" ,//1 + QDate::currentDate().addDays(-2).toString("dddd"),//2 + QDate::currentDate().addDays(-3).toString("dddd"),//3 + QDate::currentDate().addDays(-4).toString("dddd"),//4 + QDate::currentDate().addDays(-5).toString("dddd"),//5 + QDate::currentDate().addDays(-6).toString("dddd"),//6 + "Last week" ,//7 + "Two weeks ago" ,//8 + "Three weeks ago" ,//9 + "Last month" ,//10 + "Two months ago" ,//11 + "Three months ago" ,//12 + "Four months ago" ,//13 + "Five months ago" ,//14 + "Six months ago" ,//15 + "Seven months ago" ,//16 + "Eight months ago" ,//17 + "Nine months ago" ,//18 + "Ten months ago" ,//19 + "Eleven months ago" ,//20 + "Twelve months ago" ,//21 + "Last year" ,//22 + "Very long time ago" ,//23 + "Never" //24 + }; +} diff --git a/kde/src/klib/SortableDockCommon.h b/kde/src/klib/SortableDockCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..7e873d7787a313d00e5a0d26722f9d003d428620 --- /dev/null +++ b/kde/src/klib/SortableDockCommon.h @@ -0,0 +1,108 @@ +#ifndef SORTABLE_DOCK_COMMON +#define SORTABLE_DOCK_COMMON + +#include <QtCore/QObject> +#include <QtCore/QHash> +#include <QtCore/QModelIndex> +#include <QtGui/QWidget> + +#include "HelperFunctions.h" + +//Qt +class QString; +class QStringList; +class QDate; +class QDateTime; + +//SFLPhone +class StaticEventHandler; +class Contact; +class Call; + +///@enum ContactSortingMode Available sorting mode +enum ContactSortingMode { + Name , + Organisation , + Recently_used , + Group , + Department +}; + +///@enum HistorySortingMode +enum HistorySortingMode { + Date = 0, + Name2 = 1, + Popularity = 2, + Length = 3 +}; + +template <typename CallWidget = QWidget*, typename Index = QModelIndex*> +class LIB_EXPORT SortableDockCommon { + public: + friend class StaticEventHandler; + + //Helpers + static QString getIdentity(Call* item); + static int usableNumberCount(Contact* cont); + static void setHistoryCategory ( QList<Call*>& calls , HistorySortingMode mode ); + static void setContactCategory ( QList<Contact*> contacts , ContactSortingMode mode ); + + protected: + SortableDockCommon(); + //Helpers + static QString timeToHistoryCategory ( QDate date ); + static QHash<Contact*, QDateTime> getContactListByTime ( /*ContactList list*/ ); + + //Attributes + static QStringList m_slHistoryConst; + + ///@enum HistoryConst match m_slHistoryConst + enum HistoryConst { + Today = 0 , + Yesterday = 1 , + Two_days_ago = 2 , + Three_days_ago = 3 , + Four_days_ago = 4 , + Five_days_ago = 5 , + Six_days_ago = 6 , + Last_week = 7 , + Two_weeks_ago = 8 , + Three_weeks_ago = 9 , + Last_month = 10 , + Two_months_ago = 11 , + Three_months_ago = 12 , + Four_months_ago = 13 , + Five_months_ago = 14 , + Six_months_ago = 15 , + Seven_months_ago = 16 , + Eight_months_ago = 17 , + Nine_months_ago = 18 , + Ten_months_ago = 19 , + Eleven_months_ago = 20 , + Twelve_months_ago = 21 , + Last_year = 22 , + Very_long_time_ago= 23 , + Never = 24 + }; + + private: + static StaticEventHandler* m_spEvHandler ; +}; + + +///@class StaticEventHandler "cron jobs" for static member; +class LIB_EXPORT StaticEventHandler : public QObject +{ + Q_OBJECT + public: + StaticEventHandler(QObject* parent, QStringList* list); + + public slots: + void update(); + private: + QStringList* m_pList; +}; + +#include "SortableDockCommon.hpp" + +#endif \ No newline at end of file diff --git a/kde/src/klib/SortableDockCommon.hpp b/kde/src/klib/SortableDockCommon.hpp new file mode 100644 index 0000000000000000000000000000000000000000..213752e004640d78cac3cf4b296eed16dbda68b3 --- /dev/null +++ b/kde/src/klib/SortableDockCommon.hpp @@ -0,0 +1,211 @@ +//Qt +#include <QtCore/QDateTime> +#include <QtCore/QStringList> +#include <QtCore/QTimer> + +//SFLPhone +#include "../lib/Call.h" +#include "../lib/Contact.h" +#include "../lib/CallModel.h" +#include "AkonadiBackend.h" +#include "HelperFunctions.h" +#include "ConfigurationSkeleton.h" + +//Define +#define CALLMODEL_TEMPLATE template<typename CallWidget, typename Index> +#define SORTABLE_T SortableDockCommon<CallWidget,Index> + +CALLMODEL_TEMPLATE QStringList SORTABLE_T::m_slHistoryConst = QStringList(); +CALLMODEL_TEMPLATE StaticEventHandler* SORTABLE_T::m_spEvHandler = new StaticEventHandler(0,&(SORTABLE_T::m_slHistoryConst)); + +CALLMODEL_TEMPLATE SORTABLE_T::SortableDockCommon() +{ + /*if (not m_spEvHandler) { + m_spEvHandler = new StaticEventHandler(0,&(SORTABLE_T::m_slHistoryConst)); + }*/ +} + + +/***************************************************************************** + * * + * Helpers * + * * + ****************************************************************************/ + +CALLMODEL_TEMPLATE QString SORTABLE_T::timeToHistoryCategory(QDate date) +{ + if (m_slHistoryConst.size() < 10) + m_spEvHandler->update(); + + //m_spEvHandler->update(); + if (QDate::currentDate() == date || QDate::currentDate() < date) //The future case would be a bug, but it have to be handled anyway or it will appear in "very long time ago" + return m_slHistoryConst[HistoryConst::Today]; + + //Check for last week + for (int i=1;i<7;i++) { + if (QDate::currentDate().addDays(-i) == date) + return m_slHistoryConst[i]; //Yesterday to Six_days_ago + } + + //Check for last month + for (int i=1;i<4;i++) { + if (QDate::currentDate().addDays(-(i*7)) >= date && QDate::currentDate().addDays(-(i*7) -7) < date) + return m_slHistoryConst[i+Last_week-1]; //Last_week to Three_weeks_ago + } + + //Check for last year + for (int i=1;i<12;i++) { + if (QDate::currentDate().addMonths(-i) >= date && QDate::currentDate().addMonths((-i) - 1) < date) + return m_slHistoryConst[i+Last_month-1]; //Last_month to Twelve_months ago + } + + if (QDate::currentDate().addYears(-1) >= date && QDate::currentDate().addYears(-2) < date) + return m_slHistoryConst[Last_year]; + + //Every other senario + return m_slHistoryConst[Very_long_time_ago]; +} + +///Return the list of contact from history (in order, most recently used first) +CALLMODEL_TEMPLATE QHash<Contact*, QDateTime> SORTABLE_T::getContactListByTime(/*ContactList list*/) +{ + const CallMap& history= CallModel<CallWidget,Index>::getHistory(); + QHash<Contact*, QDateTime> toReturn; + QSet<QString> alreadyUsed; + QMapIterator<QString, Call*> i(history); + i.toBack(); + while (i.hasPrevious()) { //Iterate from the end up + i.previous(); + (alreadyUsed.find(i.value()->getPeerPhoneNumber()) == alreadyUsed.constEnd()); //Don't ask, leave it there Elv13(2012) + if (alreadyUsed.find(i.value()->getPeerPhoneNumber()) == alreadyUsed.constEnd()) { + Contact* contact = AkonadiBackend::getInstance()->getContactByPhone(i.value()->getPeerPhoneNumber(),true); + if (contact && toReturn.find(contact) == toReturn.end()) { + toReturn[contact] = QDateTime::fromTime_t(i.value()->getStartTimeStamp().toUInt()); + } + alreadyUsed << i.value()->getPeerPhoneNumber(); + } + } + return toReturn; +} + +CALLMODEL_TEMPLATE void SORTABLE_T::setHistoryCategory(QList<Call*>& calls,HistorySortingMode mode) +{ + QHash<QString,uint> popularityCount; + QMap<QString, QList<Call*> > byDate; + switch (mode) { + case HistorySortingMode::Date: + foreach (QString cat, m_slHistoryConst) { + byDate[cat] = QList<Call*>(); + } + break; + case HistorySortingMode::Popularity: + foreach (Call* call, calls) { + popularityCount[getIdentity(call)]++; + } + break; + default: + break; + } + foreach (Call* call, calls) { + QString category; + switch (mode) { + case HistorySortingMode::Date: + { + category = timeToHistoryCategory(QDateTime::fromTime_t(call->getStartTimeStamp().toUInt()).date()); + byDate[category] <<call; + } + break; + case HistorySortingMode::Name2: + category = getIdentity(call); + break; + case HistorySortingMode::Popularity: + { + QString identity = getIdentity(call); + category = identity+"("+QString::number(popularityCount[identity])+")"; + } + break; + case HistorySortingMode::Length: + category = "TODO"; + break; + default: + break; + } + call->setProperty("section",category); + } + switch (mode) { + case HistorySortingMode::Date: + calls.clear(); + foreach (QString cat, m_slHistoryConst) { + foreach (Call* call, byDate[cat]) { + calls << call; + } + } + break; + default: + break; + } +} + +CALLMODEL_TEMPLATE void SORTABLE_T::setContactCategory(QList<Contact*> contacts,ContactSortingMode mode) +{ + QHash<Contact*, QDateTime> recentlyUsed; + switch (mode) { + case ContactSortingMode::Recently_used: + recentlyUsed = getContactListByTime(); + foreach (QString cat, m_slHistoryConst) { + //m_pContactView->addCategory(cat); + } + break; + default: + break; + } + foreach (Contact* cont, contacts) { + if (cont->getPhoneNumbers().count() && usableNumberCount(cont)) { + QString category; + switch (mode) { + case ContactSortingMode::Name: + category = QString(cont->getFormattedName()[0]); + break; + case ContactSortingMode::Organisation: + category = (cont->getOrganization().isEmpty())?"Unknow":cont->getOrganization(); + break; + case ContactSortingMode::Recently_used: + if (recentlyUsed.find(cont) != recentlyUsed.end()) + category = timeToHistoryCategory(recentlyUsed[cont].date()); + else + category = m_slHistoryConst[Never]; + break; + case ContactSortingMode::Group: + category = "TODO"; + break; + case ContactSortingMode::Department: + category = (cont->getDepartment().isEmpty())?"Unknow":cont->getDepartment();; + break; + default: + break; + } + } + } +} + +///Return the identity of the call caller, try to return something usefull +CALLMODEL_TEMPLATE QString SORTABLE_T::getIdentity(Call* item) +{ + Contact* contact = AkonadiBackend::getInstance()->getContactByPhone(item->getPeerPhoneNumber()); + if (contact) + return contact->getFormattedName(); + else if (!item->getPeerName().isEmpty()) + return item->getPeerName(); + else + return item->getPeerPhoneNumber(); +} + +CALLMODEL_TEMPLATE int SORTABLE_T::usableNumberCount(Contact* cont) +{ + uint result =0; + QStringList list = ConfigurationSkeleton::phoneTypeList(); + foreach (Contact::PhoneNumber* pn,cont->getPhoneNumbers()) { + result += list.indexOf(pn->getType()) != -1; + } + return result; +} diff --git a/kde/src/klib/dataengine.h b/kde/src/klib/dataengine.h new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/kde/plasma/dataengine/CMakeLists.txt b/kde/src/klib/dataengine/CMakeLists.txt similarity index 64% rename from kde/plasma/dataengine/CMakeLists.txt rename to kde/src/klib/dataengine/CMakeLists.txt index 867b10900d910300e50955897785df5fb46c5f9a..94632a980d0533e4e9244ed7cea09d4b262dfb20 100644 --- a/kde/plasma/dataengine/CMakeLists.txt +++ b/kde/src/klib/dataengine/CMakeLists.txt @@ -13,14 +13,19 @@ include_directories( set(sflphone_engine_SRCS sflphonEngine.cpp + sflphoneService.cpp ) kde4_add_plugin(plasma_engine_sflphone ${sflphone_engine_SRCS}) target_link_libraries(plasma_engine_sflphone qtsflphone + ksflphone ${KDE4_KDECORE_LIBS} - ${KDE4_PLASMA_LIBS}) + ${KDE4_PLASMA_LIBS} + ${KDEPIMLIBS_AKONADI_KMIME_LIBS} + ${KDEPIMLIBS_AKONADI_LIBS} + ${KDEPIMLIBS_AKONADI_CONTACT_LIBS} ) install(TARGETS plasma_engine_sflphone DESTINATION ${PLUGIN_INSTALL_DIR}) @@ -28,4 +33,6 @@ install(TARGETS plasma_engine_sflphone install(FILES plasma-engine-sflphone.desktop DESTINATION ${SERVICES_INSTALL_DIR}) -#TARGET_LINK_LIBRARIES(sflphone-client-kde sflphonekde ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDE4_KABC_LIBS}) +install(FILES sflphone.operations + DESTINATION ${DATA_INSTALL_DIR}/plasma/services) + diff --git a/kde/plasma/dataengine/plasma-engine-sflphone.desktop b/kde/src/klib/dataengine/plasma-engine-sflphone.desktop similarity index 100% rename from kde/plasma/dataengine/plasma-engine-sflphone.desktop rename to kde/src/klib/dataengine/plasma-engine-sflphone.desktop diff --git a/kde/plasma/dataengine/plasma-engine-testtime.desktop b/kde/src/klib/dataengine/plasma-engine-testtime.desktop similarity index 100% rename from kde/plasma/dataengine/plasma-engine-testtime.desktop rename to kde/src/klib/dataengine/plasma-engine-testtime.desktop diff --git a/kde/src/klib/dataengine/sflphonEngine.cpp b/kde/src/klib/dataengine/sflphonEngine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..526d64f867103bd92cdbffb23eb809f892fc87fc --- /dev/null +++ b/kde/src/klib/dataengine/sflphonEngine.cpp @@ -0,0 +1,322 @@ +#include "sflphonEngine.h" + +#include <Plasma/DataContainer> + +#include "../../lib/Call.h" +#include "../../lib/Account.h" +#include "../../lib/AccountList.h" +#include "../../lib/Contact.h" +#include "../../lib/dbus/metatypes.h" +#include "../../lib/instance_interface_singleton.h" +#include "../../lib/configurationmanager_interface_singleton.h" +#include "../../lib/callmanager_interface_singleton.h" +#include "../../lib/sflphone_const.h" +#include "../../klib/AkonadiBackend.h" +#include "../../klib/HelperFunctions.h" +#include "../../klib/ConfigurationSkeleton.h" +#include "sflphoneService.h"> + +CallModel<>* SFLPhoneEngine::m_pModel = NULL; + +SFLPhoneEngine::SFLPhoneEngine(QObject* parent, const QVariantList& args) + : Plasma::DataEngine(parent, args) +{ + Q_UNUSED(args) + if (not m_pModel) { + m_pModel = new CallModel<>(CallModel<>::ActiveCall); + m_pModel->initCall(); + m_pModel->initHistory(); + } + + //CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); + + connect(m_pModel , SIGNAL( callStateChanged(Call*)) , this , SLOT(callStateChangedSignal(Call*) )); + connect(m_pModel , SIGNAL( callAdded(Call*)) , this , SLOT(callStateChangedSignal(Call*) )); + connect(m_pModel , SIGNAL( callStateChanged(Call*)) , this , SLOT(callStateChangedSignal(Call*) )); + //connect(&callManager , SIGNAL( incomingCall(Call*)) , this , SLOT(incomingCallSignal(Call*) )); + //connect(&callManager , SIGNAL( conferenceCreated(Call*)) , this , SLOT(conferenceCreatedSignal(Call*) )); + //connect(&callManager , SIGNAL( conferenceChanged(Call*)) , this , SLOT(conferenceChangedSignal(Call*) )); + connect(AkonadiBackend::getInstance(), SIGNAL( collectionChanged()) , this , SLOT(updateCollection() )); + +} + +bool SFLPhoneEngine::sourceRequestEvent(const QString &name) +{ + if ( name == "history" ) { + updateHistory(); + } + else if ( name == "calls" ) { + updateCallList(); + } + else if ( name == "conferences" ) { + updateConferenceList(); + } + else if ( name == "info" ) { + updateInfo(); + } + else if ( name == "accounts" ) { + updateAccounts(); + } + else if ( name == "contacts" ) { + updateContacts(); + } + else if ( name == "bookmark" ) { + updateBookmarkList(); + } + else if ( name.left(7) == "Number:" ) { + generateNumberList(name); + } + return true;//updateSourceEvent(name); +} + +bool SFLPhoneEngine::updateSourceEvent(const QString &name) +{ + Q_UNUSED(name) + return true; +} + +QStringList SFLPhoneEngine::sources() const { + QStringList toReturn; + toReturn << "calls" << "history" << "conferences" << "info" << "accounts" << "contacts" << "bookmark"; + return toReturn; +} + +Plasma::Service* SFLPhoneEngine::serviceForSource(const QString &source) +{ + if (source != "calls") { + return 0; + } + + SFLPhoneService *service = new SFLPhoneService(this); + service->setParent(this); + return service; +} + +QString SFLPhoneEngine::getCallStateName(call_state state) +{ + if (state == CALL_STATE_INCOMING) { + return I18N_NOOP("Ringing (in)"); + } else if (state == CALL_STATE_RINGING) { + return I18N_NOOP("Ringing (out)"); + } else if (state == CALL_STATE_CURRENT) { + return I18N_NOOP("Talking"); + } else if (state == CALL_STATE_DIALING) { + return I18N_NOOP("Dialing"); + } else if (state == CALL_STATE_HOLD) { + return I18N_NOOP("Hold"); + } else if (state == CALL_STATE_FAILURE) { + return I18N_NOOP("Failed"); + } else if (state == CALL_STATE_BUSY) { + return I18N_NOOP("Busy"); + } else if (state == CALL_STATE_TRANSFER) { + return I18N_NOOP("Transfer"); + } else if (state == CALL_STATE_TRANSF_HOLD) { + return I18N_NOOP("Transfer hold"); + } else if (state == CALL_STATE_OVER) { + return I18N_NOOP("Over"); + } else if (state == CALL_STATE_ERROR) { + return I18N_NOOP("Error"); + } + return ""; +} + +void SFLPhoneEngine::updateHistory() +{ + CallList list = m_pModel->getHistory().values(); + setHistoryCategory(list,HistorySortingMode::Date); + + foreach (Call* oldCall, list) { + historyCall[oldCall->getCallId()][ "peerName" ] = oldCall->getPeerName(); + historyCall[oldCall->getCallId()][ "peerNumber" ] = oldCall->getPeerPhoneNumber(); + historyCall[oldCall->getCallId()][ "length" ] = oldCall->getStopTimeStamp().toInt() - oldCall->getStartTimeStamp().toInt(); + historyCall[oldCall->getCallId()][ "date" ] = oldCall->getStopTimeStamp(); + historyCall[oldCall->getCallId()][ "id" ] = oldCall->getCallId(); + if (oldCall->property("section").isValid()) + historyCall[oldCall->getCallId()][ "section" ] = oldCall->property("section"); + setData("history", oldCall->getCallId() , historyCall[oldCall->getCallId()]); + } +} + +void SFLPhoneEngine::updateCallList() +{ + removeAllData("calls"); + foreach (Call* call, m_pModel->getCalls()) { + if ((!m_pModel->isConference(call)) && (call->getState() != CALL_STATE_OVER)) { + currentCall[call->getCallId()][ "peerName" ] = call->getPeerName(); + currentCall[call->getCallId()][ "peerNumber" ] = call->getPeerPhoneNumber(); + currentCall[call->getCallId()][ "stateName" ] = getCallStateName(call->getState()); + currentCall[call->getCallId()][ "state" ] = call->getState(); + currentCall[call->getCallId()][ "id" ] = call->getCallId(); + setData("calls", call->getCallId(), currentCall[call->getCallId()]); + } + } +} + +void SFLPhoneEngine::updateBookmarkList() +{ + removeAllData("bookmark"); + int i=0; + QStringList cl = getModel()->getNumbersByPopularity(); + for (;i < ((cl.size() < 10)?cl.size():10);i++) { + QHash<QString,QVariant> pop; + Contact* cont = AkonadiBackend::getInstance()->getContactByPhone(cl[i],true); + if (cont) { + pop["peerName" ] = cont->getFormattedName(); + } + else { + pop["peerName" ] = cl[i]; + } + pop["peerNumber" ] = cl[i] ; + pop["section" ] = "Popular" ; + pop["listPriority" ] = 1000 ; + pop["id" ] = i ; + setData("bookmark", QString::number(i), pop); + } + + //TODO Wont work for now + foreach (QString nb, ConfigurationSkeleton::bookmarkList()) { + i++; + QHash<QString,QVariant> pop; + pop["peerName" ] = "TODO" ; + pop["peerNumber" ] = nb ; + pop["section" ] = "1" ; + pop["listPriority" ] = 0 ; + pop["id" ] = i ; + setData("bookmark", QString::number(i), pop); + } +} + +void SFLPhoneEngine::updateConferenceList() +{ + foreach (Call* call, m_pModel->getCalls()) { + if (m_pModel->isConference(call)) { + CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); + currentConferences[call->getConfId()] = callManager.getParticipantList(call->getConfId()); + setData("conferences", call->getConfId(), currentConferences[call->getConfId()]); + } + } +} + +void SFLPhoneEngine::updateCollection() +{ + + typedef QHash<QString,QVariant> SerializedContact; + ContactList list = AkonadiBackend::getInstance()->update(); + if (!list.size()) + return; + ContactHash hash = HelperFunctions::toHash(list); + foreach (SerializedContact cont, hash) { + if (!m_hContacts[hash.key(cont)].size()) { + m_hContacts[hash.key(cont)] = cont; + } + // + } + removeAllData("contacts"); + int i=0; + foreach (SerializedContact cont, m_hContacts) { + cont["section"] = "test"; + setData("contacts", QString::number(i), QVariant(cont)); + i++; + } + updateBookmarkList(); +} + +void SFLPhoneEngine::updateContacts() +{ + QHash<QString,QVariant> test; + test[ "nickName" ] = ""; + test[ "firstName" ] = ""; + test[ "secondName" ] = ""; + test[ "formattedName" ] = ""; + test[ "organization" ] = ""; + test[ "Uid" ] = ""; + test[ "preferredEmail" ] = ""; + test[ "type" ] = ""; + test[ "group" ] = ""; + test[ "department" ] = ""; + setData("contacts", "fake",test ); +} + +void SFLPhoneEngine::updateInfo() +{ + setData("info", I18N_NOOP("Current_account"), m_pModel->getCurrentAccountId()); +} + +void SFLPhoneEngine::updateAccounts() +{ + const QVector<Account*>& list = m_pModel->getAccountList()->getAccounts(); + foreach(Account* a,list) { + QHash<QString,QVariant> acc; + acc["id"] = a->getAccountId(); + acc["alias"] = a->getAccountDetail(ACCOUNT_ALIAS); + setData("accounts", QString::number(rand()) , acc); + } +} + +void SFLPhoneEngine::generateNumberList(QString name) +{ + QString contactUid = name.right(name.size()-7); + qDebug() << "LOOKING FOR " << contactUid; + Contact* cont = AkonadiBackend::getInstance()->getContactByUid(contactUid); + if (cont) { + foreach(Contact::PhoneNumber* num,cont->getPhoneNumbers()) { + QHash<QString,QVariant> hash; + hash[ "number" ] = num->getNumber(); + hash[ "type" ] = num->getType(); + setData(name, QString::number(rand()) , hash); + } + } + else { + kDebug() << "Contact not found"; + } +} + +void SFLPhoneEngine::callStateChangedSignal(Call* call) +{ + Q_UNUSED(call) + updateCallList(); +} + +void SFLPhoneEngine::incomingCallSignal(Call* call) +{ + Q_UNUSED(call) + updateCallList(); +} + +void SFLPhoneEngine::conferenceCreatedSignal(Call* conf) +{ + Q_UNUSED(conf) + updateConferenceList(); +} + +void SFLPhoneEngine::conferenceChangedSignal(Call* conf) +{ + Q_UNUSED(conf) + updateConferenceList(); +} + +void SFLPhoneEngine::incomingMessageSignal(const QString& accountId, const QString& message) +{ + Q_UNUSED(accountId) + Q_UNUSED(message) + //TODO +} + +void SFLPhoneEngine::voiceMailNotifySignal(const QString& accountId, int count) +{ + Q_UNUSED(accountId) + Q_UNUSED(count) + //TODO +} + +void SFLPhoneEngine::accountChanged() +{ + +} + +CallModel<>* SFLPhoneEngine::getModel() +{ + return m_pModel; +} + +K_EXPORT_PLASMA_DATAENGINE(sflphone, SFLPhoneEngine) diff --git a/kde/plasma/dataengine/sflphonEngine.h b/kde/src/klib/dataengine/sflphonEngine.h similarity index 75% rename from kde/plasma/dataengine/sflphonEngine.h rename to kde/src/klib/dataengine/sflphonEngine.h index 9a234f254094761e2d0e6db71e2968f05999f0da..b29212540d24f199a07d1b002f0e9cad951a8a18 100644 --- a/kde/plasma/dataengine/sflphonEngine.h +++ b/kde/src/klib/dataengine/sflphonEngine.h @@ -22,37 +22,51 @@ #define SFLPHONEENGINE_H #include <Plasma/DataEngine> +#include <Plasma/Service> #include <QHash> -#include "../../src/lib/CallModel.h" +#include "../../lib/CallModel.h" +#include "../SortableDockCommon.h" typedef QHash<QString,QVariant> HashStringString; +typedef QHash<QString,QHash<QString,QVariant> > ContactHash; class Call; -class SFLPhoneEngine : public Plasma::DataEngine +class SFLPhoneEngine : public Plasma::DataEngine,public SortableDockCommon<> { Q_OBJECT public: SFLPhoneEngine(QObject* parent, const QVariantList& args); + Plasma::Service *serviceForSource(const QString &source); virtual QStringList sources() const; + static CallModel<>* getModel(); + + friend class SFLPhoneService; + protected: bool sourceRequestEvent(const QString& name); bool updateSourceEvent(const QString& source); private: - QHash<QString, HashStringString > historyCall ; - QHash<QString, HashStringString > currentCall ; - QHash<QString, QStringList> currentConferences ; - CallModelConvenience* m_pModel; + QHash<QString, HashStringString > historyCall ; + QHash<QString, HashStringString > currentCall ; + QHash<QString, QStringList> currentConferences ; + static CallModel<>* m_pModel ; + ContactHash m_hContacts ; QString getCallStateName(call_state state); void updateHistory (); void updateCallList (); - void updateContacts (); + void updateAccounts (); void updateConferenceList (); + void updateContacts (); + void updateBookmarkList (); void updateInfo(); + + void generateNumberList(QString name); private slots: + void updateCollection(); void callStateChangedSignal (Call* call); void incomingCallSignal (Call* conf); void conferenceCreatedSignal (Call* conf); diff --git a/kde/src/klib/dataengine/sflphone.operations b/kde/src/klib/dataengine/sflphone.operations new file mode 100644 index 0000000000000000000000000000000000000000..801ae0062249178a0917d027a747d42a7dfbda63 --- /dev/null +++ b/kde/src/klib/dataengine/sflphone.operations @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE kcfg SYSTEM + "http://www.kde.org/standards/kcfg/1.0/kcfg.xsd"> +<kcfg> + <group name="Call"> + <entry name="AccountId" type="String"> + <label>Account id to make this call</label> + </entry> + <entry name="Number" type="String"> + <label>Number to call</label> + </entry> + </group> + <group name="DMTF"> + <entry name="str" type="String"> + <label>Right sound for a key</label> + </entry> + </group> + <group name="Transfer"> + <entry name="callid" type="String"> + <label>A valid call identifier number</label> + </entry> + <entry name="transfernumber" type="String"> + <label>Number to transfer too</label> + </entry> + </group> + <group name="Hangup"> + <entry name="callid" type="String"> + <label>A valid call identifier number</label> + </entry> + </group> + <group name="Hold"> + <entry name="callid" type="String"> + <label>A valid call identifier number</label> + </entry> + </group> +</kcfg> diff --git a/kde/src/klib/dataengine/sflphoneService.cpp b/kde/src/klib/dataengine/sflphoneService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdcf45a7cdcc6dcf1603b765caa6c6d194f63f45 --- /dev/null +++ b/kde/src/klib/dataengine/sflphoneService.cpp @@ -0,0 +1,35 @@ +#include "sflphoneService.h" + +#include "../../lib/Call.h" + +SFLPhoneService::SFLPhoneService(SFLPhoneEngine *engine) + +{ + m_engine = engine; + setName("sflphone"); +} + +ServiceJob *SFLPhoneService::createJob(const QString &operation, QMap<QString, QVariant> ¶meters) +{ + if (!m_engine) { + return 0; + } + + if (operation == "Call") { + return new CallJob(this, operation,parameters); + } + else if (operation == "DMTF") { + return new DTMFJob(this, operation,parameters); + } + else if (operation == "Transfer") { + return new TransferJob(this, operation,parameters); + } + else if (operation == "Hangup") { + return new HangUpJob(this, operation,parameters); + } + else if (operation == "Hold") { + return new HoldJob(this, operation,parameters); + } + m_engine->setData(operation, parameters["query"]); + return 0; +} \ No newline at end of file diff --git a/kde/src/klib/dataengine/sflphoneService.h b/kde/src/klib/dataengine/sflphoneService.h new file mode 100644 index 0000000000000000000000000000000000000000..1425b491dcd537f4a940c07956855b8d874e1626 --- /dev/null +++ b/kde/src/klib/dataengine/sflphoneService.h @@ -0,0 +1,128 @@ +#ifndef SFLPHONE_SERVICE_H +#define SFLPHONE_SERVICE_H + +#include "sflphonEngine.h" + +#include <Plasma/Service> +#include <Plasma/ServiceJob> + +#include "../../lib/Call.h" +#include "../../lib/CallModel.h" + +using namespace Plasma; + +class SFLPhoneService : public Plasma::Service +{ + Q_OBJECT + +public: + SFLPhoneService(SFLPhoneEngine *engine); + ServiceJob *createJob(const QString &operation, QMap<QString, QVariant> ¶meters); + +private: + SFLPhoneEngine *m_engine; + +}; + +class CallJob : public Plasma::ServiceJob +{ + Q_OBJECT +public: + CallJob(QObject* parent, const QString& operation, const QVariantMap& parameters = QVariantMap()) + : Plasma::ServiceJob("", operation, parameters, parent) + , m_AccountId ( parameters[ "AccountId" ].toString() ) + , m_Number ( parameters[ "Number" ].toString() ) + {} + + void start() + { + Call* call = SFLPhoneEngine::getModel()->addDialingCall(m_Number,m_AccountId); + call->setCallNumber(m_Number); + call->actionPerformed(CALL_ACTION_ACCEPT); + } + +private: + QString m_AccountId; + QString m_Number; +}; + +class DTMFJob : public Plasma::ServiceJob +{ + Q_OBJECT +public: + DTMFJob(QObject* parent, const QString& operation, const QVariantMap& parameters = QVariantMap()) + : Plasma::ServiceJob("", operation, parameters, parent) + , m_mStr( parameters[ "str" ].toString() ) + {} + + void start() + { + CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); + callManager.playDTMF(m_mStr); + } +private: + QString m_mStr; +}; + +class HangUpJob : public Plasma::ServiceJob +{ + Q_OBJECT +public: + HangUpJob(QObject* parent, const QString& operation, const QVariantMap& parameters = QVariantMap()) + : Plasma::ServiceJob("", operation, parameters, parent) + , m_CallId( parameters[ "callid" ].toString() ) + {} + + void start() + { + Call* call = SFLPhoneEngine::getModel()->getCall(m_CallId); + call->actionPerformed(CALL_ACTION_REFUSE); + call->changeCurrentState(CALL_STATE_OVER); + } +private: + QString m_CallId; +}; + +class TransferJob : public Plasma::ServiceJob +{ + Q_OBJECT +public: + TransferJob(QObject* parent, const QString& operation, const QVariantMap& parameters = QVariantMap()) + : Plasma::ServiceJob("", operation, parameters, parent) + , m_CallId ( parameters[ "callid" ].toString() ) + , m_transferNumber ( parameters[ "transfernumber" ].toString() ) + {} + + void start() + { + Call* call = SFLPhoneEngine::getModel()->getCall(m_CallId); + call->setTransferNumber(m_transferNumber); + call->changeCurrentState(CALL_STATE_TRANSFER); + call->actionPerformed(CALL_ACTION_ACCEPT); + call->changeCurrentState(CALL_STATE_OVER); + } +private: + QString m_CallId; + QString m_transferNumber; +}; + +class HoldJob : public Plasma::ServiceJob +{ + Q_OBJECT +public: + HoldJob(QObject* parent, const QString& operation, const QVariantMap& parameters = QVariantMap()) + : Plasma::ServiceJob("", operation, parameters, parent) + , m_CallId ( parameters[ "callid" ].toString() ) + {} + + void start() + { + Call* call = SFLPhoneEngine::getModel()->getCall(m_CallId); + call->actionPerformed(CALL_ACTION_HOLD); + } +private: + QString m_CallId; +}; + + +#endif //SFLPHONE_SERVICE_H diff --git a/kde/src/conf/kcfg_settings.kcfgc b/kde/src/klib/kcfg_settings.kcfgc similarity index 61% rename from kde/src/conf/kcfg_settings.kcfgc rename to kde/src/klib/kcfg_settings.kcfgc index b14ca1863f8e830d10729b176f512a36358b339b..d64e6e44c5aca7b83f34998d1795e2ef470e1c44 100755 --- a/kde/src/conf/kcfg_settings.kcfgc +++ b/kde/src/klib/kcfg_settings.kcfgc @@ -3,3 +3,5 @@ File=sflphone-client-kde.kcfg ClassName=ConfigurationSkeletonBase Singleton=true Mutators=true +Visibility=LIB_EXPORT +IncludeFiles=\"../src/lib/typedefs.h\" \ No newline at end of file diff --git a/kde/src/conf/sflphone-client-kde.kcfg b/kde/src/klib/sflphone-client-kde.kcfg similarity index 81% rename from kde/src/conf/sflphone-client-kde.kcfg rename to kde/src/klib/sflphone-client-kde.kcfg index 3bc1f21fb5c8833228e5f10a013060a8e8afc471..4e9685f0d39ea3899c36820ffcc9f9f9a6c0dd37 100755 --- a/kde/src/conf/sflphone-client-kde.kcfg +++ b/kde/src/klib/sflphone-client-kde.kcfg @@ -26,21 +26,31 @@ <entry name="notifOnCalls" type="Bool"> <label>Defines whether user should be notified when receiving a call.</label> + <default>true</default> </entry> <entry name="notifOnMessages" type="Bool"> <label>Defines whether user should be notified when receiving a message.</label> + <default>true</default> </entry> <entry name="displayOnStart" type="Bool"> <label>Defines whether the main window should be displayed on start.</label> + <default>true</default> </entry> <entry name="displayOnCalls" type="Bool"> <label>Defines whether the main window should be displayed when receiving a message.</label> + <default>true</default> </entry> <entry name="displayDialpad" type="Bool"> <label>Defines whether the dialpad is being shown by default</label> + <default>true</default> + </entry> + <entry name="displayMessageBox" type="Bool"> + <label>Defines whether the text message box is visible</label> + <default>false</default> </entry> <entry name="displayVolume" type="Bool"> <label>Defines whether the volume widgets are visible by default</label> + <default>false</default> </entry> <entry name="displayMenu" type="Bool"> <label>Defines whether the main menu is visible by default, it can be restored with "Ctrl+m"</label> @@ -48,9 +58,19 @@ <entry name="displayDataRange" type="Bool"> <label>Defines whether call history is restricted to a specific date range</label> </entry> + <entry name="displayPopularAsBookmark" type="Bool"> + <label>Defines whether or not to display the 10 most popular phone number as bookmark automagically</label> + </entry> + <entry name="historySortMode" type="Int"> + <label>Define sorting order for history list</label> + </entry> + <entry name="contactSortMode" type="Int"> + <label>Define sorting order for contact list</label> + </entry> <entry name="displayContactCallHistory" type="Bool"> <label>Defines if the individual contact history list is visible</label> - </entry> + </entry> + <!-- Audio Settings --> @@ -67,11 +87,6 @@ <entry name="ringtone" type="Path"> <label>Defines which ringtone is used.</label> </entry> - <!-- - <entry name="activeCodecList" type="StringList"> - <label>Defines which ALSA plugin to use.</label> - </entry> - --> <entry name="alsaPlugin" type="String"> <label>Defines which ALSA plugin to use.</label> </entry> @@ -90,20 +105,10 @@ <entry name="enableAddressBook" type="Bool"> <label>Defines whether the search in KDE Address Book is enabled</label> </entry> - <entry name="maxResults" type="Int"> - <label>Defines the max number of contacts to display during a search in address book.</label> - </entry> - <entry name="displayPhoto" type="Bool"> - <label>Defines whether to display contacts photos.</label> - </entry> - <entry name="business" type="Bool"> - <label>Defines whether to display professionnal phone numbers.</label> - </entry> - <entry name="mobile" type="Bool"> - <label>Defines whether to display mobile phone numbers.</label> - </entry> - <entry name="home" type="Bool"> - <label>Defines whether to display personnal phone numbers.</label> + + <entry name="phoneTypeList" type="StringList"> + <label>Defines whether the search in KDE Address Book is enabled</label> + <default>{Work,Home,Messenger,Prefered number,Voice,Mobile,Work,Video,Mailbox,Modem,Car,ISDN,PCS,Pager,Other...,Work}</default> </entry> <!-- Bookmark --> @@ -111,12 +116,6 @@ <label>List of bookmarked clients</label> </entry> - <!-- Record Settings --> - - <entry name="destinationFolder" type="Path"> - <label>Defines the destination directory for call recordings.</label> - </entry> - <!-- Hooks Settings --> <entry name="enableHooksSIP" type="Bool"> diff --git a/kde/src/lib/Account.cpp b/kde/src/lib/Account.cpp index 2bd6e0e9d46f616daaa7217780a2e8c50794a66c..e3b349d930f2cdcdddf0c4bb3097617638990b4c 100644 --- a/kde/src/lib/Account.cpp +++ b/kde/src/lib/Account.cpp @@ -86,6 +86,12 @@ Account* Account::buildExistingAccountFromId(const QString& _accountId) return NULL; } a->m_pAccountDetails = aDetails; + + //Enable for debug + // foreach (QString str, *aDetails) { + // qDebug() << aDetails->key(str) << str; + // } + return a; } @@ -152,6 +158,10 @@ const QString& Account::getAccountDetail(const QString& param) const } if (m_pAccountDetails->find(param) != m_pAccountDetails->end()) return (*m_pAccountDetails)[param]; + else if (m_pAccountDetails->count() > 0) { + qDebug() << "Account paramater \"" << param << "\" not found"; + return EMPTY_STRING; + } else { qDebug() << "Account details not found, there is " << m_pAccountDetails->count() << " details available"; return EMPTY_STRING; @@ -167,13 +177,13 @@ const QString& Account::getAlias() const ///Is this account enabled bool Account::isEnabled() const { - return (getAccountDetail(ACCOUNT_ENABLED) == ACCOUNT_ENABLED_TRUE); + return (getAccountDetail(ACCOUNT_ENABLED) == REGISTRATION_ENABLED_TRUE); } ///Is this account registered bool Account::isRegistered() const { - return (getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED); + return (getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED); } @@ -207,7 +217,7 @@ void Account::setAccountId(const QString& id) ///Set account enabled void Account::setEnabled(bool checked) { - setAccountDetail(ACCOUNT_ENABLED, checked ? ACCOUNT_ENABLED_TRUE : ACCOUNT_ENABLED_FALSE); + setAccountDetail(ACCOUNT_ENABLED, checked ? REGISTRATION_ENABLED_TRUE : REGISTRATION_ENABLED_FALSE); } /***************************************************************************** @@ -222,8 +232,8 @@ void Account::updateState() if(! isNew()) { ConfigurationManagerInterface & configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); MapStringString details = configurationManager.getAccountDetails(getAccountId()).value(); - QString status = details[ACCOUNT_STATUS]; - setAccountDetail(ACCOUNT_STATUS, status); //Update -internal- object state + QString status = details[ACCOUNT_REGISTRATION_STATUS]; + setAccountDetail(ACCOUNT_REGISTRATION_STATUS, status); //Update -internal- object state } } diff --git a/kde/src/lib/AccountList.cpp b/kde/src/lib/AccountList.cpp index 8a99b6b899a9095ffd4fc7a81df429b6cdf3f50f..9b46222014f547b8befa3c7219948395a00aeee3 100644 --- a/kde/src/lib/AccountList.cpp +++ b/kde/src/lib/AccountList.cpp @@ -143,7 +143,7 @@ QVector<Account*> AccountList::getAccountsByState(const QString& state) { QVector<Account *> v; for (int i = 0; i < m_pAccounts->size(); ++i) { - if ((*m_pAccounts)[i]->getAccountDetail(ACCOUNT_STATUS) == state) + if ((*m_pAccounts)[i]->getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == state) v += (*m_pAccounts)[i]; } return v; @@ -157,7 +157,7 @@ QVector<Account*> AccountList::registeredAccounts() const Account* current; for (int i = 0; i < m_pAccounts->count(); ++i) { current = (*m_pAccounts)[i]; - if(current->getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED) { + if(current->getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED) { qDebug() << current->getAlias() << " : " << current; registeredAccounts.append(current); } @@ -171,11 +171,11 @@ Account* AccountList::firstRegisteredAccount() const Account* current; for (int i = 0; i < m_pAccounts->count(); ++i) { current = (*m_pAccounts)[i]; - if(current && current->getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED) { + if(current && current->getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED) { return current; } else { - qDebug() << "Account " << current->getAccountId() << " is not registered (" << current->getAccountDetail(ACCOUNT_STATUS) << ")"; + qDebug() << "Account " << ((current)?current->getAccountId():"") << " is not registered (" << ((current)?current->getAccountDetail(ACCOUNT_REGISTRATION_STATUS):"") << ") State:" << ((current)?current->getAccountDetail(ACCOUNT_REGISTRATION_STATUS):""); } } return NULL; diff --git a/kde/src/lib/AccountList.h b/kde/src/lib/AccountList.h index 68f995b08dfd2bde6c4891fafed49d22a1e6be08..b1fce03a9d02c00c385c84cef0ebb233947e8666 100644 --- a/kde/src/lib/AccountList.h +++ b/kde/src/lib/AccountList.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ + **************************************************************************/ #ifndef ACCOUNT_LIST_H #define ACCOUNT_LIST_H @@ -70,5 +70,4 @@ signals: void accountListUpdated(); }; - #endif diff --git a/kde/src/lib/CMakeLists.txt b/kde/src/lib/CMakeLists.txt index c2fa10571ef547aeec51bee8f033c6322ec560ba..3db06e46222025221271cb49ff41cf8d14a01202 100644 --- a/kde/src/lib/CMakeLists.txt +++ b/kde/src/lib/CMakeLists.txt @@ -1,5 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +ADD_DEFINITIONS("-std=c++0x") +# ADD_DEFINITIONS("-std=c++0x") + ADD_DEFINITIONS( ${QT_DEFINITIONS} -fexceptions @@ -17,7 +20,7 @@ FIND_PACKAGE ( Qt4 REQUIRED ) INCLUDE ( KDE4Defaults ) -set(GENERIC_LIB_VERSION "1.0.2") +set(GENERIC_LIB_VERSION "1.1.0") INCLUDE_DIRECTORIES ( ${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/kde/src/lib/Call.cpp b/kde/src/lib/Call.cpp index 7504e8e0ec41f3a6bfe9a42263bc2961d4902591..b1683e4b4a22008fbb906172fff0a4d936f755f6 100644 --- a/kde/src/lib/Call.cpp +++ b/kde/src/lib/Call.cpp @@ -313,7 +313,7 @@ daemon_call_state Call::toDaemonCallState(const QString & stateName) QString Call::getStopTimeStamp() const { if (m_pStopTime == NULL) - return QString(); + return QString("0"); return QString::number(m_pStopTime->toTime_t()); } @@ -321,7 +321,7 @@ QString Call::getStopTimeStamp() const QString Call::getStartTimeStamp() const { if (m_pStartTime == NULL) - return QString(); + return QString("0"); return QString::number(m_pStartTime->toTime_t()); } @@ -385,6 +385,12 @@ const QString& Call::getConfId() const return m_ConfId; } +///Get the recording path +const QString& Call::getRecordingPath() const +{ + return m_RecordingPath; +} + ///Get the current codec QString Call::getCurrentCodecName() const { @@ -459,6 +465,18 @@ void Call::setConfId(QString value) m_ConfId = value; } +///Set the recording path +void Call::setRecordingPath(const QString& path) +{ + m_RecordingPath = path; +} + +///Set peer name +void Call::setPeerName(const QString& name) +{ + m_PeerName = name; +} + /***************************************************************************** * * * Mutator * @@ -523,6 +541,11 @@ void Call::changeCurrentState(call_state newState) emit isOver(this); } +void Call::sendTextMessage(QString message) +{ + CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); + callManager.sendTextMessage(m_CallId,message); +} /***************************************************************************** * * @@ -608,7 +631,7 @@ void Call::call() qDebug() << "account = " << m_Account; if(m_Account.isEmpty()) { qDebug() << "Account is not set, taking the first registered."; - this->m_Account = CallModelConvenience::getCurrentAccountId(); + this->m_Account = CallModel<>::getCurrentAccountId(); } if(!m_Account.isEmpty()) { qDebug() << "Calling " << m_CallNumber << " with account " << m_Account << ". callId : " << m_CallId; diff --git a/kde/src/lib/Call.h b/kde/src/lib/Call.h index 8e475dbcdfdcd9c665168835413d4b42fabd370f..ad2fbdc004fedf5bd57fa8549ee36db4b2183bde 100644 --- a/kde/src/lib/Call.h +++ b/kde/src/lib/Call.h @@ -151,21 +151,25 @@ public: const QString& getConfId () const; const QString& getTransferNumber () const; const QString& getCallNumber () const; + const QString& getRecordingPath () const; //Automated function call_state stateChanged(const QString & newState); call_state actionPerformed(call_action action); //Setters - void setConference(bool value); - void setConfId(QString value); - void setTransferNumber(const QString& number); - void setCallNumber(const QString& number); + void setConference ( bool value ); + void setConfId ( QString value ); + void setTransferNumber ( const QString& number ); + void setCallNumber ( const QString& number ); + void setRecordingPath ( const QString& path ); + void setPeerName ( const QString& name ); //Mutators void appendText(const QString& str); void backspaceItemText(); void changeCurrentState(call_state newState); + void sendTextMessage(QString message); private: @@ -175,6 +179,7 @@ private: QString m_ConfId ; QString m_PeerPhoneNumber; QString m_PeerName ; + QString m_RecordingPath ; history_state m_HistoryState ; QDateTime* m_pStartTime ; QDateTime* m_pStopTime ; diff --git a/kde/src/lib/CallModel.cpp b/kde/src/lib/CallModel.cpp index 66c37d1f39618cb30c86b023e0a3b91b6e070cd8..f172b83aa2f51f51b7cfefb986f58126060291ee 100644 --- a/kde/src/lib/CallModel.cpp +++ b/kde/src/lib/CallModel.cpp @@ -60,7 +60,12 @@ void CallModelBase::on1_callStateChanged(const QString &callID, const QString &s qDebug() << "Call found" << call; call->stateChanged(state); } - //updateWindowCallState(); //NEED_PORT + + if (call->getCurrentState() == CALL_STATE_OVER) { + addToHistory(call); + emit historyChanged(); + } + emit callStateChanged(call); } @@ -91,7 +96,7 @@ void CallModelBase::on1_changingConference(const QString &confID, const QString { Call* conf = getCall(confID); qDebug() << "Changing conference state" << conf << confID; - if (conf) { + if (conf && dynamic_cast<Call*>(conf)) { //Prevent a race condition between call and conference changeConference(confID, state); emit conferenceChanged(conf); } diff --git a/kde/src/lib/CallModel.h b/kde/src/lib/CallModel.h index 608af376d043a0d15c16ba95e663e4afe460ac99..d5654546c3c3fae720be34358874229956e48e23 100644 --- a/kde/src/lib/CallModel.h +++ b/kde/src/lib/CallModel.h @@ -23,7 +23,9 @@ #include <QObject> #include <QVector> -#include <QHash> +#include <QWidget> +#include <QModelIndex> +#include <QMap> #include "typedefs.h" //Qt @@ -37,12 +39,12 @@ class AccountList; class Account; class ContactBackend; -typedef QHash<QString, Call*> CallHash; +typedef QMap<QString, Call*> CallMap; typedef QList<Call*> CallList; -///@class CallModelBase Base class for the central model/frontend -///This class need to exist because template classes can't have signals ans -///slots because Qt MOC generator can't guess the type at precompilation +///@class CallModelBase Base class for the central model/frontend +///This class need to exist because template classes can't have signals and +///slots because Qt MOC generator can't guess the type at precompilation class LIB_EXPORT CallModelBase : public QObject { Q_OBJECT @@ -54,6 +56,7 @@ public: virtual Call* findCallByCallId ( const QString& callId ) = 0; virtual Call* addRingingCall ( const QString& callId ) = 0; virtual Call* addIncomingCall ( const QString& callId ) = 0; + virtual void addToHistory ( Call* call ) = 0; virtual Call* addCall ( Call* call , Call* parent =0 ); virtual Call* getCall ( const QString& callId ) const = 0; public slots: @@ -67,15 +70,16 @@ public slots: private: static bool dbusInit; signals: - void callStateChanged (Call* call ); - void incomingCall (Call* call ); - void conferenceCreated (Call* conf ); - void conferenceChanged (Call* conf ); - void conferenceRemoved (const QString& confId ); - void aboutToRemoveConference (Call* conf ); - void voiceMailNotify (const QString& accountID , int count ); - void volumeChanged (const QString& device , double value ); - void callAdded (Call* call , Call* parent ); + void callStateChanged ( Call* call ); + void incomingCall ( Call* call ); + void conferenceCreated ( Call* conf ); + void conferenceChanged ( Call* conf ); + void conferenceRemoved ( const QString& confId ); + void aboutToRemoveConference ( Call* conf ); + void voiceMailNotify ( const QString& accountID , int count ); + void volumeChanged ( const QString& device , double value ); + void callAdded ( Call* call , Call* parent ); + void historyChanged ( ); }; /** @@ -84,7 +88,7 @@ signals: * solution may be less "clean" than MVC, but is 3 time smaller and easier to improve (in fact, possible to improve). */ ///@class CallModel Central model/frontend to deal with sflphoned -template <typename CallWidget, typename Index> +template <typename CallWidget = QWidget*, typename Index = QModelIndex*> class LIB_EXPORT CallModel : public CallModelBase { public: enum ModelType { @@ -109,6 +113,7 @@ class LIB_EXPORT CallModel : public CallModelBase { void removeCall ( Call* call ); void attendedTransfer ( Call* toTransfer , Call* target ); void transfer ( Call* toTransfer , QString target ); + void addToHistory ( Call* call ); virtual bool selectItem(Call* item) { Q_UNUSED(item); return false;} @@ -123,10 +128,11 @@ class LIB_EXPORT CallModel : public CallModelBase { void removeConference ( Call* call ); //Getters - int size (); - CallList getCallList (); - static const CallHash& getHistory (); - static const QStringList getHistoryCallId (); + int size (); + CallList getCallList (); + static const CallMap& getHistory (); + static const QStringList getNumbersByPopularity (); + static const QStringList getHistoryCallId (); //Account related static Account* getCurrentAccount ( ); @@ -175,11 +181,11 @@ class LIB_EXPORT CallModel : public CallModelBase { struct InternalStruct; typedef QList<InternalStruct*> InternalCallList; struct InternalStruct { - CallWidget call ; - Call* call_real ; - Index index ; - InternalCallList children ; - bool conference ; + CallWidget call ; + Call* call_real ; + Index index ; + InternalCallList children ; + bool conference ; }; typedef QHash< Call* , InternalStruct* > InternalCall ; typedef QHash< QString , InternalStruct* > InternalCallId; @@ -187,8 +193,8 @@ class LIB_EXPORT CallModel : public CallModelBase { typedef QHash< Index , InternalStruct* > InternalIndex ; //Static attributes - static CallHash m_sActiveCalls ; - static CallHash m_sHistoryCalls; + static CallMap m_sActiveCalls ; + static CallMap m_sHistoryCalls; static InternalCall m_sPrivateCallList_call ; static InternalCallId m_sPrivateCallList_callId; @@ -208,11 +214,11 @@ class LIB_EXPORT CallModel : public CallModelBase { bool updateCommon (Call* call); }; -class CallModelConvenience : public CallModel<QWidget*,QModelIndex*> +/*class CallModelConvenience : public CallModel<QWidget*,QModelIndex*> { public: CallModelConvenience(ModelType type) : CallModel<QWidget*,QModelIndex*>(type) {} -}; +};*/ #include "CallModel.hpp" diff --git a/kde/src/lib/CallModel.hpp b/kde/src/lib/CallModel.hpp index f19081c5a580269fd29f90a9985c553b9ec9ffe8..43b667221cb0dcd8f1337a302d0f05f2346fa080 100644 --- a/kde/src/lib/CallModel.hpp +++ b/kde/src/lib/CallModel.hpp @@ -38,20 +38,45 @@ //System #include "unistd.h" +//Define +#define CALLMODEL_TEMPLATE template<typename CallWidget, typename Index> +#define CALLMODEL_T CallModel<CallWidget,Index> + //Static member -template <typename CallWidget, typename Index> QString CallModel<CallWidget,Index>::m_sPriorAccountId = "" ; -template <typename CallWidget, typename Index> AccountList* CallModel<CallWidget,Index>::m_spAccountList = 0 ; -template <typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::m_sInstanceInit = false ; -template <typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::m_sCallInit = false ; -template <typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::m_sHistoryInit = false ; +CALLMODEL_TEMPLATE QString CALLMODEL_T::m_sPriorAccountId = "" ; +CALLMODEL_TEMPLATE AccountList* CALLMODEL_T::m_spAccountList = 0 ; +CALLMODEL_TEMPLATE bool CALLMODEL_T::m_sInstanceInit = false ; +CALLMODEL_TEMPLATE bool CALLMODEL_T::m_sCallInit = false ; +CALLMODEL_TEMPLATE bool CALLMODEL_T::m_sHistoryInit = false ; -template <typename CallWidget, typename Index> QHash<QString, Call*> CallModel<CallWidget,Index>::m_sActiveCalls ; -template <typename CallWidget, typename Index> QHash<QString, Call*> CallModel<CallWidget,Index>::m_sHistoryCalls ; +CALLMODEL_TEMPLATE CallMap CALLMODEL_T::m_sActiveCalls ; +CALLMODEL_TEMPLATE CallMap CALLMODEL_T::m_sHistoryCalls ; + +CALLMODEL_TEMPLATE typename CALLMODEL_T::InternalCall CALLMODEL_T::m_sPrivateCallList_call ; +CALLMODEL_TEMPLATE typename CALLMODEL_T::InternalCallId CALLMODEL_T::m_sPrivateCallList_callId ; +CALLMODEL_TEMPLATE typename CALLMODEL_T::InternalIndex CALLMODEL_T::m_sPrivateCallList_index ; +CALLMODEL_TEMPLATE typename CALLMODEL_T::InternalWidget CALLMODEL_T::m_sPrivateCallList_widget ; + +/***************************************************************************** + * * + * Private classes * + * * + ****************************************************************************/ +class SortableCallSource { +public: + SortableCallSource(Call* call=0) : count(0),callInfo(call) {} + uint count; + Call* callInfo; + bool operator<(SortableCallSource other) { + return (other.count > count); + } +}; + +inline bool operator< (const SortableCallSource & s1, const SortableCallSource & s2) +{ + return s1.count < s2.count; +} -template <typename CallWidget, typename Index> typename CallModel<CallWidget,Index>::InternalCall CallModel<CallWidget,Index>::m_sPrivateCallList_call ; -template <typename CallWidget, typename Index> typename CallModel<CallWidget,Index>::InternalCallId CallModel<CallWidget,Index>::m_sPrivateCallList_callId ; -template <typename CallWidget, typename Index> typename CallModel<CallWidget,Index>::InternalIndex CallModel<CallWidget,Index>::m_sPrivateCallList_index ; -template <typename CallWidget, typename Index> typename CallModel<CallWidget,Index>::InternalWidget CallModel<CallWidget,Index>::m_sPrivateCallList_widget ; /***************************************************************************** * * @@ -60,7 +85,7 @@ template <typename CallWidget, typename Index> typename CallModel<CallWidget,In ****************************************************************************/ ///Retrieve current and older calls from the daemon, fill history and the calls TreeView and enable drag n' drop -template<typename CallWidget, typename Index> CallModel<CallWidget,Index>::CallModel(ModelType type) : CallModelBase(0) +CALLMODEL_TEMPLATE CALLMODEL_T::CallModel(ModelType type) : CallModelBase(0) { Q_UNUSED(type) init(); @@ -68,7 +93,7 @@ template<typename CallWidget, typename Index> CallModel<CallWidget,Index>::CallM } ///Open the connection to the daemon and register this client -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::init() +CALLMODEL_TEMPLATE bool CALLMODEL_T::init() { if (!m_sInstanceInit) { registerCommTypes(); @@ -77,7 +102,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: //Setup accounts if (m_spAccountList == NULL) - m_spAccountList = new AccountList(true); + m_spAccountList = new AccountList(true); } m_sInstanceInit = true; return true; @@ -85,7 +110,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: ///Fill the call list ///@warning This solution wont scale to multiple call or history model implementation. Some static addCall + foreach for each call would be needed if this case ever become unavoidable -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::initCall() +CALLMODEL_TEMPLATE bool CALLMODEL_T::initCall() { if (!m_sCallInit) { CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); @@ -106,36 +131,36 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Set how the call can find more informations about the call it receive -template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>::initContact ( ContactBackend* be ) +CALLMODEL_TEMPLATE void CALLMODEL_T::initContact ( ContactBackend* be ) { Call::setContactBackend(be); } ///Fill the history list ///@warning This solution wont scale to multiple call or history model implementation. Some static addCall + foreach for each call would be needed if this case ever become unavoidable -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::initHistory() +CALLMODEL_TEMPLATE bool CALLMODEL_T::initHistory() { if (!m_sHistoryInit) { ConfigurationManagerInterface& configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); - QStringList historyMap = configurationManager.getHistory().value(); - foreach (QString historyCallId, historyMap) { - QStringList param = historyCallId.split("|"); - if (param.count() <= 10) { - //If this ever change, look at the gnome client - QString history_state = param[0]; - QString peer_number = param[1]; - QString peer_name = param[2]; - QString time_start = param[3]; - QString time_stop = param[4]; - QString callID = param[5]; - QString accountID = param[6]; - QString recordfile = param[7]; - QString confID = param[8]; - QString time_added = param[9]; - m_sHistoryCalls[time_start] = Call::buildHistoryCall(callID, time_start.toUInt(), time_stop.toUInt(), accountID, peer_name, peer_number, history_state); - addCall(m_sHistoryCalls[time_start]); + QVector< QMap<QString, QString> > history = configurationManager.getHistory(); + foreach (MapStringString hc, history) { + Call* pastCall = Call::buildHistoryCall( + hc[ CALLID_KEY ] , + hc[ TIMESTAMP_START_KEY ].toUInt(), + hc[ TIMESTAMP_STOP_KEY ].toUInt(), + hc[ ACCOUNT_ID_KEY ] , + hc[ DISPLAY_NAME_KEY ] , + hc[ PEER_NUMBER_KEY ] , + hc[ STATE_KEY ] + ); + if (pastCall->getPeerName().isEmpty()) { + pastCall->setPeerName("Unknow"); } + pastCall->setRecordingPath(hc[ RECORDING_PATH_KEY ]); + m_sHistoryCalls[ hc[TIMESTAMP_START_KEY ]] = pastCall; + addCall(pastCall); } + qDebug() << "There is " << m_sHistoryCalls.count() << "in history"; } m_sHistoryInit = true; return true; @@ -149,19 +174,19 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: ****************************************************************************/ ///Return the active call count -template<typename CallWidget, typename Index> int CallModel<CallWidget,Index>::size() +CALLMODEL_TEMPLATE int CALLMODEL_T::size() { return m_sActiveCalls.size(); } ///Return a call corresponding to this ID or NULL -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::findCallByCallId(const QString& callId) +CALLMODEL_TEMPLATE Call* CALLMODEL_T::findCallByCallId(const QString& callId) { return m_sActiveCalls[callId]; } ///Return the action call list -template<typename CallWidget, typename Index> QList<Call*> CallModel<CallWidget,Index>::getCallList() +CALLMODEL_TEMPLATE QList<Call*> CALLMODEL_T::getCallList() { QList<Call*> callList; foreach(Call* call, m_sActiveCalls) { @@ -178,9 +203,12 @@ template<typename CallWidget, typename Index> QList<Call*> CallModel<CallWidget, ****************************************************************************/ ///Add a call in the model structure, the call must exist before being added to the model -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::addCall(Call* call, Call* parent) +CALLMODEL_TEMPLATE Call* CALLMODEL_T::addCall(Call* call, Call* parent) { Q_UNUSED(parent) + if (!call) + return new Call("",""); //Invalid, but better than managing NULL everywhere + InternalStruct* aNewStruct = new InternalStruct; aNewStruct->call_real = call; aNewStruct->conference = false; @@ -194,7 +222,7 @@ template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>: } ///Common set of instruction shared by all call adder -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::addCallCommon(Call* call) +CALLMODEL_TEMPLATE Call* CALLMODEL_T::addCallCommon(Call* call) { m_sActiveCalls[call->getCallId()] = call; addCall(call); @@ -203,7 +231,7 @@ template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>: } ///Create a new dialing call from peer name and the account ID -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::addDialingCall(const QString& peerName, QString account) +CALLMODEL_TEMPLATE Call* CALLMODEL_T::addDialingCall(const QString& peerName, QString account) { QString account2 = account; if (account2.isEmpty()) { @@ -215,21 +243,21 @@ template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>: } ///Create a new incomming call when the daemon is being called -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::addIncomingCall(const QString& callId) +CALLMODEL_TEMPLATE Call* CALLMODEL_T::addIncomingCall(const QString& callId) { Call* call = Call::buildIncomingCall(callId); return addCallCommon(call); } ///Create a ringing call -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::addRingingCall(const QString& callId) +CALLMODEL_TEMPLATE Call* CALLMODEL_T::addRingingCall(const QString& callId) { Call* call = Call::buildRingingCall(callId); return addCallCommon(call); } ///Generate a new random call unique identifier (callId) -template<typename CallWidget, typename Index> QString CallModel<CallWidget,Index>::generateCallId() +CALLMODEL_TEMPLATE QString CALLMODEL_T::generateCallId() { int id = qrand(); QString res = QString::number(id); @@ -237,7 +265,7 @@ template<typename CallWidget, typename Index> QString CallModel<CallWidget,Index } ///Remove a call and update the internal structure -template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>::removeCall(Call* call) +CALLMODEL_TEMPLATE void CALLMODEL_T::removeCall(Call* call) { InternalStruct* internal = m_sPrivateCallList_call[call]; @@ -264,7 +292,7 @@ template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>:: } ///Transfer "toTransfer" to "target" and wait to see it it succeeded -template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>::attendedTransfer(Call* toTransfer, Call* target) +CALLMODEL_TEMPLATE void CALLMODEL_T::attendedTransfer(Call* toTransfer, Call* target) { CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); callManager.attendedTransfer(toTransfer->getCallId(),target->getCallId()); @@ -275,9 +303,9 @@ template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>:: } ///Transfer this call to "target" number -template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>::transfer(Call* toTransfer, QString target) +CALLMODEL_TEMPLATE void CALLMODEL_T::transfer(Call* toTransfer, QString target) { - qDebug() << "\n\n\n\n\nTransferring call " << toTransfer->getCallId() << target << "\n\n\n\n\n"; + qDebug() << "Transferring call " << toTransfer->getCallId() << "to" << target; toTransfer->setTransferNumber(target); toTransfer->changeCurrentState(CALL_STATE_TRANSFER); toTransfer->actionPerformed(CALL_ACTION_ACCEPT); @@ -291,7 +319,7 @@ template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>:: ****************************************************************************/ ///Add a new conference, get the call list and update the interface as needed -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::addConference(const QString & confID) +CALLMODEL_TEMPLATE Call* CALLMODEL_T::addConference(const QString & confID) { qDebug() << "Notified of a new conference " << confID; CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); @@ -320,7 +348,7 @@ template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>: } ///Join two call to create a conference, the conference will be created later (see addConference) -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::createConferenceFromCall(Call* call1, Call* call2) +CALLMODEL_TEMPLATE bool CALLMODEL_T::createConferenceFromCall(Call* call1, Call* call2) { qDebug() << "Joining call: " << call1->getCallId() << " and " << call2->getCallId(); CallManagerInterface &callManager = CallManagerInterfaceSingleton::getInstance(); @@ -329,7 +357,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Add a new participant to a conference -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::addParticipant(Call* call2, Call* conference) +CALLMODEL_TEMPLATE bool CALLMODEL_T::addParticipant(Call* call2, Call* conference) { if (conference->isConference()) { CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); @@ -343,7 +371,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Remove a participant from a conference -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::detachParticipant(Call* call) +CALLMODEL_TEMPLATE bool CALLMODEL_T::detachParticipant(Call* call) { CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); callManager.detachParticipant(call->getCallId()); @@ -351,7 +379,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Merge two conferences -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::mergeConferences(Call* conf1, Call* conf2) +CALLMODEL_TEMPLATE bool CALLMODEL_T::mergeConferences(Call* conf1, Call* conf2) { CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); callManager.joinConference(conf1->getConfId(),conf2->getConfId()); @@ -359,7 +387,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Executed when the daemon signal a modification in an existing conference. Update the call list and update the TreeView -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::changeConference(const QString& confId, const QString& state) +CALLMODEL_TEMPLATE bool CALLMODEL_T::changeConference(const QString& confId, const QString& state) { qDebug() << "Conf changed"; Q_UNUSED(state) @@ -377,14 +405,14 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Remove a conference from the model and the TreeView -template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>::removeConference(const QString &confId) +CALLMODEL_TEMPLATE void CALLMODEL_T::removeConference(const QString &confId) { qDebug() << "Ending conversation containing " << m_sPrivateCallList_callId[confId]->children.size() << " participants"; removeConference(getCall(confId)); } ///Remove a conference using it's call object -template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>::removeConference(Call* call) +CALLMODEL_TEMPLATE void CALLMODEL_T::removeConference(Call* call) { InternalStruct* internal = m_sPrivateCallList_call[call]; @@ -403,7 +431,7 @@ template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>:: ****************************************************************************/ ///Return a list of all previous calls -template<typename CallWidget, typename Index> const QStringList CallModel<CallWidget,Index>::getHistoryCallId() +CALLMODEL_TEMPLATE const QStringList CALLMODEL_T::getHistoryCallId() { QStringList toReturn; foreach(Call* call, m_sHistoryCalls) { @@ -413,11 +441,46 @@ template<typename CallWidget, typename Index> const QStringList CallModel<CallWi } ///Return the history list -template<typename CallWidget, typename Index> const CallHash& CallModel<CallWidget,Index>::getHistory() +CALLMODEL_TEMPLATE const CallMap& CALLMODEL_T::getHistory() { return m_sHistoryCalls; } +///Add to history +CALLMODEL_TEMPLATE void CALLMODEL_T::addToHistory(Call* call) +{ + if (call) { + m_sHistoryCalls[call->getStartTimeStamp()] = call; + } +} + +///Sort all history call by popularity and return the result (most popular first) +CALLMODEL_TEMPLATE const QStringList CALLMODEL_T::getNumbersByPopularity() +{ + QHash<QString,SortableCallSource*> hc; + foreach (Call* call, getHistory()) { + if (!hc[call->getPeerPhoneNumber()]) { + hc[call->getPeerPhoneNumber()] = new SortableCallSource(call); + } + hc[call->getPeerPhoneNumber()]->count++; + } + QList<SortableCallSource> userList; + foreach (SortableCallSource* i,hc) { + userList << *i; + } + qSort(userList); + QStringList cl; + for (int i=userList.size()-1;i >=0 ;i--) { + cl << userList[i].callInfo->getPeerPhoneNumber(); + } + foreach (SortableCallSource* i,hc) { + delete i; + } + + return cl; +} + + /***************************************************************************** * * * Account related code * @@ -425,7 +488,7 @@ template<typename CallWidget, typename Index> const CallHash& CallModel<CallWidg ****************************************************************************/ ///Return the current account id (do not put in the cpp file) -template<typename CallWidget, typename Index> QString CallModel<CallWidget,Index>::getCurrentAccountId() +CALLMODEL_TEMPLATE QString CALLMODEL_T::getCurrentAccountId() { Account* firstRegistered = getCurrentAccount(); if(firstRegistered == NULL) { @@ -438,10 +501,10 @@ template<typename CallWidget, typename Index> QString CallModel<CallWidget,Index ///Return the current account -template<typename CallWidget, typename Index> Account* CallModel<CallWidget,Index>::getCurrentAccount() +CALLMODEL_TEMPLATE Account* CALLMODEL_T::getCurrentAccount() { Account* priorAccount = getAccountList()->getAccountById(m_sPriorAccountId); - if(priorAccount && priorAccount->getAccountDetail(ACCOUNT_STATUS) == ACCOUNT_STATE_REGISTERED ) { + if(priorAccount && priorAccount->getAccountDetail(ACCOUNT_REGISTRATION_STATUS) == ACCOUNT_STATE_REGISTERED ) { return priorAccount; } else { @@ -451,7 +514,7 @@ template<typename CallWidget, typename Index> Account* CallModel<CallWidget,Inde } ///Return a list of registered accounts -template<typename CallWidget, typename Index> AccountList* CallModel<CallWidget,Index>::getAccountList() +CALLMODEL_TEMPLATE AccountList* CALLMODEL_T::getAccountList() { if (m_spAccountList == NULL) { m_spAccountList = new AccountList(true); @@ -460,13 +523,13 @@ template<typename CallWidget, typename Index> AccountList* CallModel<CallWidget, } ///Return the previously used account ID -template<typename CallWidget, typename Index> QString CallModel<CallWidget,Index>::getPriorAccoundId() +CALLMODEL_TEMPLATE QString CALLMODEL_T::getPriorAccoundId() { return m_sPriorAccountId; } ///Set the previous account used -template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>::setPriorAccountId(const QString& value) { +CALLMODEL_TEMPLATE void CALLMODEL_T::setPriorAccountId(const QString& value) { m_sPriorAccountId = value; } @@ -477,7 +540,7 @@ template<typename CallWidget, typename Index> void CallModel<CallWidget,Index>:: ****************************************************************************/ ///Get a call from it's widget -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::getCall ( const CallWidget widget ) const +CALLMODEL_TEMPLATE Call* CALLMODEL_T::getCall ( const CallWidget widget ) const { if (m_sPrivateCallList_widget[widget]) { return m_sPrivateCallList_widget[widget]->call_real; @@ -486,19 +549,19 @@ template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>: } ///Get a call list from a conference -template<typename CallWidget, typename Index> QList<Call*> CallModel<CallWidget,Index>::getCalls ( const CallWidget widget ) const +CALLMODEL_TEMPLATE QList<Call*> CALLMODEL_T::getCalls ( const CallWidget widget ) const { QList<Call*> toReturn; if (m_sPrivateCallList_widget[widget] && m_sPrivateCallList_widget[widget]->conference) { foreach (InternalStruct* child, m_sPrivateCallList_widget[widget]->children) { - toReturn << child.call_real; + toReturn << child.call_real; } } return toReturn; } ///Get a list of every call -template<typename CallWidget, typename Index> QList<Call*> CallModel<CallWidget,Index>::getCalls ( ) +CALLMODEL_TEMPLATE QList<Call*> CALLMODEL_T::getCalls ( ) { QList<Call*> toReturn; foreach (InternalStruct* child, m_sPrivateCallList_call) { @@ -508,7 +571,7 @@ template<typename CallWidget, typename Index> QList<Call*> CallModel<CallWidget, } ///Is the call associated with that widget a conference -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::isConference ( const CallWidget widget ) const +CALLMODEL_TEMPLATE bool CALLMODEL_T::isConference ( const CallWidget widget ) const { if (m_sPrivateCallList_widget[widget]) { return m_sPrivateCallList_widget[widget]->conference; @@ -517,7 +580,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Is that call a conference -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::isConference ( const Call* call ) const +CALLMODEL_TEMPLATE bool CALLMODEL_T::isConference ( const Call* call ) const { if (m_sPrivateCallList_call[(Call*)call]) { return m_sPrivateCallList_call[(Call*)call]->conference; @@ -526,25 +589,25 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Do nothing, provided for API consistency -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::getCall ( const Call* call ) const +CALLMODEL_TEMPLATE Call* CALLMODEL_T::getCall ( const Call* call ) const { return call; } ///Return the calls from the "call" conference -template<typename CallWidget, typename Index> QList<Call*> CallModel<CallWidget,Index>::getCalls ( const Call* call ) const +CALLMODEL_TEMPLATE QList<Call*> CALLMODEL_T::getCalls ( const Call* call ) const { QList<Call*> toReturn; if (m_sPrivateCallList_call[call] && m_sPrivateCallList_call[call]->conference) { foreach (InternalStruct* child, m_sPrivateCallList_call[call]->children) { - toReturn << child.call_real; + toReturn << child.call_real; } } return toReturn; } ///Is the call associated with that Index a conference -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::isConference ( const Index idx ) const +CALLMODEL_TEMPLATE bool CALLMODEL_T::isConference ( const Index idx ) const { if (m_sPrivateCallList_index[idx]) { return m_sPrivateCallList_index[idx]->conference; @@ -553,7 +616,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Get the call associated with this index -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::getCall ( const Index idx ) const +CALLMODEL_TEMPLATE Call* CALLMODEL_T::getCall ( const Index idx ) const { if (m_sPrivateCallList_index[idx]) { return m_sPrivateCallList_index[idx]->call_real; @@ -563,19 +626,19 @@ template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>: } ///Get the call associated with that conference index -template<typename CallWidget, typename Index> QList<Call*> CallModel<CallWidget,Index>::getCalls ( const Index idx ) const +CALLMODEL_TEMPLATE QList<Call*> CALLMODEL_T::getCalls ( const Index idx ) const { QList<Call*> toReturn; if (m_sPrivateCallList_index[idx] && m_sPrivateCallList_index[idx]->conference) { foreach (InternalStruct* child, m_sPrivateCallList_index[idx]->children) { - toReturn << child.call_real; + toReturn << child.call_real; } } return toReturn; } ///Is the call associated with that ID a conference -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::isConference ( const QString& callId ) const +CALLMODEL_TEMPLATE bool CALLMODEL_T::isConference ( const QString& callId ) const { if (m_sPrivateCallList_callId[callId]) { return m_sPrivateCallList_callId[callId]->conference; @@ -584,7 +647,7 @@ template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>:: } ///Get the call associated with this ID -template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>::getCall ( const QString& callId ) const +CALLMODEL_TEMPLATE Call* CALLMODEL_T::getCall ( const QString& callId ) const { if (m_sPrivateCallList_callId[callId]) { return m_sPrivateCallList_callId[callId]->call_real; @@ -593,19 +656,19 @@ template<typename CallWidget, typename Index> Call* CallModel<CallWidget,Index>: } ///Get the calls associated with this ID -template<typename CallWidget, typename Index> QList<Call*> CallModel<CallWidget,Index>::getCalls ( const QString& callId ) const +CALLMODEL_TEMPLATE QList<Call*> CALLMODEL_T::getCalls ( const QString& callId ) const { QList<Call*> toReturn; if (m_sPrivateCallList_callId[callId] && m_sPrivateCallList_callId[callId]->conference) { foreach (InternalStruct* child, m_sPrivateCallList_callId[callId]->children) { - toReturn << child.callId_real; + toReturn << child.callId_real; } } return toReturn; } ///Get the index associated with this call -template<typename CallWidget, typename Index> Index CallModel<CallWidget,Index>::getIndex ( const Call* call ) const +CALLMODEL_TEMPLATE Index CALLMODEL_T::getIndex ( const Call* call ) const { if (m_sPrivateCallList_call[(Call*)call]) { return m_sPrivateCallList_call[(Call*)call]->index; @@ -614,7 +677,7 @@ template<typename CallWidget, typename Index> Index CallModel<CallWidget,Index>: } ///Get the index associated with this index (dummy implementation) -template<typename CallWidget, typename Index> Index CallModel<CallWidget,Index>::getIndex ( const Index idx ) const +CALLMODEL_TEMPLATE Index CALLMODEL_T::getIndex ( const Index idx ) const { if (m_sPrivateCallList_index[idx]) { return m_sPrivateCallList_index[idx]->index; @@ -623,7 +686,7 @@ template<typename CallWidget, typename Index> Index CallModel<CallWidget,Index>: } ///Get the index associated with this call -template<typename CallWidget, typename Index> Index CallModel<CallWidget,Index>::getIndex ( const CallWidget widget ) const +CALLMODEL_TEMPLATE Index CALLMODEL_T::getIndex ( const CallWidget widget ) const { if (m_sPrivateCallList_widget[widget]) { return m_sPrivateCallList_widget[widget]->index; @@ -632,7 +695,7 @@ template<typename CallWidget, typename Index> Index CallModel<CallWidget,Index>: } ///Get the index associated with this ID -template<typename CallWidget, typename Index> Index CallModel<CallWidget,Index>::getIndex ( const QString& callId ) const +CALLMODEL_TEMPLATE Index CALLMODEL_T::getIndex ( const QString& callId ) const { if (m_sPrivateCallList_callId[callId]) { return m_sPrivateCallList_callId[callId]->index; @@ -641,7 +704,7 @@ template<typename CallWidget, typename Index> Index CallModel<CallWidget,Index>: } ///Get the widget associated with this call -template<typename CallWidget, typename Index> CallWidget CallModel<CallWidget,Index>::getWidget ( const Call* call ) const +CALLMODEL_TEMPLATE CallWidget CALLMODEL_T::getWidget ( const Call* call ) const { if (m_sPrivateCallList_call[call]) { return m_sPrivateCallList_call[call]->call; @@ -650,7 +713,7 @@ template<typename CallWidget, typename Index> CallWidget CallModel<CallWidget,In } ///Get the widget associated with this ID -template<typename CallWidget, typename Index> CallWidget CallModel<CallWidget,Index>::getWidget ( const Index idx ) const +CALLMODEL_TEMPLATE CallWidget CALLMODEL_T::getWidget ( const Index idx ) const { if (m_sPrivateCallList_index[idx]) { return m_sPrivateCallList_index[idx]->call; @@ -659,7 +722,7 @@ template<typename CallWidget, typename Index> CallWidget CallModel<CallWidget,In } ///Get the widget associated with this widget (dummy) -template<typename CallWidget, typename Index> CallWidget CallModel<CallWidget,Index>::getWidget ( const CallWidget widget ) const +CALLMODEL_TEMPLATE CallWidget CALLMODEL_T::getWidget ( const CallWidget widget ) const { if (m_sPrivateCallList_widget[widget]) { return m_sPrivateCallList_widget[widget]->call; @@ -668,7 +731,7 @@ template<typename CallWidget, typename Index> CallWidget CallModel<CallWidget,In } ///Get the widget associated with this ID -template<typename CallWidget, typename Index> CallWidget CallModel<CallWidget,Index>::getWidget ( const QString& widget ) const +CALLMODEL_TEMPLATE CallWidget CALLMODEL_T::getWidget ( const QString& widget ) const { if (m_sPrivateCallList_widget[widget]) { return m_sPrivateCallList_widget[widget]->call; @@ -677,32 +740,33 @@ template<typename CallWidget, typename Index> CallWidget CallModel<CallWidget,In } ///Common set of instruction shared by all gui updater -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::updateCommon(Call* call) +CALLMODEL_TEMPLATE bool CALLMODEL_T::updateCommon(Call* call) { - if (!m_sPrivateCallList_call[call]) { + if (!m_sPrivateCallList_call[call] && dynamic_cast<Call*>(call)) { m_sPrivateCallList_call [ call ] = new InternalStruct ; m_sPrivateCallList_call [ call ]->call_real = call ; m_sPrivateCallList_call [ call ]->conference = false ; m_sPrivateCallList_callId [ call->getCallId() ] = m_sPrivateCallList_call[call] ; } + else + return false; return true; } ///Update the widget associated with this call -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::updateWidget (Call* call, CallWidget value ) +CALLMODEL_TEMPLATE bool CALLMODEL_T::updateWidget (Call* call, CallWidget value ) { - updateCommon(call); + if (!updateCommon(call)) return false; m_sPrivateCallList_call[call]->call = value ; m_sPrivateCallList_widget[value] = m_sPrivateCallList_call[call] ; return true; } - ///Update the index associated with this call -template<typename CallWidget, typename Index> bool CallModel<CallWidget,Index>::updateIndex (Call* call, Index value ) +CALLMODEL_TEMPLATE bool CALLMODEL_T::updateIndex (Call* call, Index value ) { updateCommon(call); m_sPrivateCallList_call[call]->index = value ; m_sPrivateCallList_index[value] = m_sPrivateCallList_call[call] ; return true; -} \ No newline at end of file +} diff --git a/kde/src/lib/Contact.cpp b/kde/src/lib/Contact.cpp index 3f4069c8c2d9924a48a2e1b550f2dbe6e3593d47..2be1e9abf78c4e3b80732aaa68c1a113f8009b01 100644 --- a/kde/src/lib/Contact.cpp +++ b/kde/src/lib/Contact.cpp @@ -106,6 +106,17 @@ const QString& Contact::getUid() const return m_Uid; } +///Get the group +const QString& Contact::getGroup() const +{ + return m_Group; +} + +const QString& Contact::getDepartment() const +{ + return m_Department; +} + ///Get the contact type const QString& Contact::getType() const { @@ -139,7 +150,7 @@ void Contact::setFamilyName(const QString& name) ///Set the Photo/Avatar void Contact::setPhoto(QPixmap* photo) { - m_pPhoto = photo; + m_pPhoto = photo; } ///Set the formatted name (display name) @@ -164,4 +175,35 @@ void Contact::setPreferredEmail(const QString& name) void Contact::setUid(const QString& id) { m_Uid = id; +} + +///Set Group +void Contact::setGroup(const QString& name) +{ + m_Group = name; +} + +///Set department +void Contact::setDepartment(const QString& name) +{ + m_Department = name; +} + +///Turn the contact into QString-QString hash +QHash<QString,QVariant> Contact::toHash() +{ + QHash<QString,QVariant> aContact; + //aContact[""] = PhoneNumbers getPhoneNumbers() const; + aContact[ "nickName" ] = getNickName(); + aContact[ "firstName" ] = getFirstName(); + aContact[ "secondName" ] = getSecondName(); + aContact[ "formattedName" ] = getFormattedName(); + aContact[ "organization" ] = getOrganization(); + aContact[ "uid" ] = getUid(); + aContact[ "preferredEmail" ] = getPreferredEmail(); + //aContact[ "Photo" ] = QVariant(*getPhoto()); + aContact[ "type" ] = getType(); + aContact[ "group" ] = getGroup(); + aContact[ "department" ] = getDepartment(); + return aContact; } \ No newline at end of file diff --git a/kde/src/lib/Contact.h b/kde/src/lib/Contact.h index 169ddf0b60e057aa70bd1337cea9daf7dae3c051..c13a6e0d01b25b5191564fccfda7c8a497960d79 100644 --- a/kde/src/lib/Contact.h +++ b/kde/src/lib/Contact.h @@ -21,7 +21,8 @@ #ifndef CONTACT_H #define CONTACT_H -#include <QObject> +#include <QtCore/QObject> +#include <QtCore/QVariant> //Qt class QListWidgetItem; @@ -69,6 +70,8 @@ private: QString m_PreferredEmail ; QString m_Organization ; QString m_Uid ; + QString m_Group ; + QString m_Department ; bool m_DisplayPhoto ; PhoneNumbers m_Numbers ; @@ -89,17 +92,24 @@ public: virtual const QString& getPreferredEmail() const; virtual const QPixmap* getPhoto() const; virtual const QString& getType() const; + virtual const QString& getGroup() const; + virtual const QString& getDepartment() const; //Setters - virtual void setPhoneNumbers (PhoneNumbers ); - virtual void setFormattedName (const QString& name ); - virtual void setNickName (const QString& name ); - virtual void setFirstName (const QString& name ); - virtual void setFamilyName (const QString& name ); - virtual void setOrganization (const QString& name ); - virtual void setPreferredEmail (const QString& name ); - virtual void setUid (const QString& id ); - virtual void setPhoto (QPixmap* photo ); + virtual void setPhoneNumbers ( PhoneNumbers ); + virtual void setFormattedName ( const QString& name ); + virtual void setNickName ( const QString& name ); + virtual void setFirstName ( const QString& name ); + virtual void setFamilyName ( const QString& name ); + virtual void setOrganization ( const QString& name ); + virtual void setPreferredEmail ( const QString& name ); + virtual void setGroup ( const QString& name ); + virtual void setDepartment ( const QString& name ); + virtual void setUid ( const QString& id ); + virtual void setPhoto ( QPixmap* photo ); + + //Mutator + QHash<QString,QVariant> toHash(); protected: virtual void initItemWidget(); diff --git a/kde/src/lib/ContactBackend.h b/kde/src/lib/ContactBackend.h index 81a0c051d2e8c3b4d291530e8d1fe4afdc579ae1..64ad72cca992066de42adf718fc3d821d7bbdfc7 100644 --- a/kde/src/lib/ContactBackend.h +++ b/kde/src/lib/ContactBackend.h @@ -24,12 +24,16 @@ #include <QObject> #include <QHash> +#include <QStringList> +#include <QVariant> #include "typedefs.h" +#include "Contact.h" //SFLPhone class Contact; +//Typedef typedef QList<Contact*> ContactList; ///@class ContactBackend Allow different way to handle contact without poluting the library @@ -37,7 +41,7 @@ class LIB_EXPORT ContactBackend : public QObject { Q_OBJECT public: ContactBackend(QObject* parent); - virtual Contact* getContactByPhone ( const QString& phoneNumber ) = 0; + virtual Contact* getContactByPhone ( const QString& phoneNumber , bool resolveDNS = false) = 0; virtual Contact* getContactByUid ( const QString& uid ) = 0; virtual void editContact ( Contact* contact ) = 0; virtual void addNewContact ( Contact* contact ) = 0; diff --git a/kde/src/lib/Item.h b/kde/src/lib/Item.h index 24238fa5c4e34f318efd4916f6226e3e107979dd..101d362edd0623eb4551c82418dfafb6d423cad7 100644 --- a/kde/src/lib/Item.h +++ b/kde/src/lib/Item.h @@ -26,67 +26,67 @@ class QListWidgetItem; /** - @author Jérémy Quentin <jeremy.quentin@gmail.com> - Represents an item of a list, that is displayed - by an QListWidgetItem with a QWidget inside. - The two objects are contained in this class, but their - initializations are pure virtual. - The template class WIDGET_TYPE should be derived from - QWidget. - The implementation of initItem should call initItemWidget + * @author Jérémy Quentin <jeremy.quentin@gmail.com> + * Represents an item of a list, that is displayed + * by an QListWidgetItem with a QWidget inside. + * The two objects are contained in this class, but their + * initializations are pure virtual. + * The template class WIDGET_TYPE should be derived from + * QWidget. + * The implementation of initItem should call initItemWidget */ template<class WIDGET_TYPE>class LIB_EXPORT Item { protected: - QListWidgetItem * item; - WIDGET_TYPE * itemWidget; - + QListWidgetItem * item; + WIDGET_TYPE * itemWidget; + public: - /** - * Would be great to take the QListWidget as attribute - * to be able to add the itemWidget to the item in the list. - * For the moment, we have to do it from outside. - */ - Item(/*QListWidget *list=0*/) { - item = NULL; - itemWidget = NULL; - } - - /** - * Be careful that it is not already deleted by QObject - * Commented for safety reasons... - */ - virtual ~Item() { -// delete item; -// delete itemWidget; - } - - QListWidgetItem* getItem() { - return item; - } - - WIDGET_TYPE* getItemWidget() { - return itemWidget; - } - - const QListWidgetItem* getItem() const { - return item; - } - const WIDGET_TYPE* getItemWidget() const { - return itemWidget; - } - - /** - * Initializes the item and widget - * Implementation should call initItemWidget! - */ - virtual void initItem() = 0; - + /** + * Would be great to take the QListWidget as attribute + * to be able to add the itemWidget to the item in the list. + * For the moment, we have to do it from outside. + */ + Item(/*QListWidget *list=0*/) { + item = NULL; + itemWidget = NULL; + } + + /** + * Be careful that it is not already deleted by QObject + * Commented for safety reasons... + */ + virtual ~Item() { + // delete item; + // delete itemWidget; + } + + QListWidgetItem* getItem() { + return item; + } + + WIDGET_TYPE* getItemWidget() { + return itemWidget; + } + + const QListWidgetItem* getItem() const { + return item; + } + const WIDGET_TYPE* getItemWidget() const { + return itemWidget; + } + + /** + * Initializes the item and widget + * Implementation should call initItemWidget! + */ + virtual void initItem() = 0; + protected: - virtual void initItemWidget() = 0; - - + virtual void initItemWidget() = 0; + + }; #endif diff --git a/kde/src/lib/configurationmanager_interface_singleton.cpp b/kde/src/lib/configurationmanager_interface_singleton.cpp index bcd19e8ff1f37f55b7e6853682e95b0e14eb73ce..0c78866ed5dc8fdea5063e53fd8e4757ba8366b6 100644 --- a/kde/src/lib/configurationmanager_interface_singleton.cpp +++ b/kde/src/lib/configurationmanager_interface_singleton.cpp @@ -32,4 +32,4 @@ ConfigurationManagerInterface & ConfigurationManagerInterfaceSingleton::getInsta } return *interface; } - + diff --git a/kde/src/lib/dbus/callmanager-introspec.xml b/kde/src/lib/dbus/callmanager-introspec.xml index 46cec40068df52b9d16a50324c3947821ed7f443..a742426b77507d01a447521eca94b2237ad136f1 100644 --- a/kde/src/lib/dbus/callmanager-introspec.xml +++ b/kde/src/lib/dbus/callmanager-introspec.xml @@ -1,825 +1,781 @@ <?xml version="1.0" encoding="UTF-8" ?> <node name="/callmanager-introspec" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> - <interface name="org.sflphone.SFLphone.CallManager"> - - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - <p>The CallManager interface is used to manage - any call and conference related actions.</p> - <p>Since SFLphone-daemon support multiple incoming/outgoing calls, any actions involving a specific call must address the method by the means of a unique callID. SFLphone-clients is responsible to generate the callID on outgoing call. On the other hand, SFLphone-daemon will generate a unique callID on incoming calls.</p> - </tp:docstring> - <method name="placeCall" tp:name-for-bindings="placeCall"> - <tp:docstring> - <p>This is the main method in order to place a new call. The call is registered to the daemon using this method.</p> - </tp:docstring> - <arg type="s" name="accountID" direction="in"> - <tp:docstring> - The ID of the account you want to make a call with. If the call is to be placed whithout any account by the means of a SIP URI (i.e. sip:num@server), the "IP2IP_PROFILE" is passed as the accountID. For more details about accounts see the configuration manager interface. - </tp:docstring> - </arg> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The callID is a unique identifier that must be randomly generated on the client's side. Any subsequent actions refering to this call must use this callID. - </tp:docstring> - </arg> - <arg type="s" name="to" direction="in"> - <tp:docstring> - If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified. - </tp:docstring> - </arg> - </method> - - <method name="placeCallFirstAccount" tp:name-for-bindings="placeCallFirstAccount"> - <tp:added version="0.9.8"/> - <tp:docstring> - Place a call with the fist registered account, regarding to the account list order. - <tp:rationale> - Use this function when you don't have any information about the accounts used (Ex: Firefly mozilla extension) - </tp:rationale> - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The callID is a unique identifier that must be randomly generated on the client's side. Any subsequent actions refering to this call must use this callID. - </tp:docstring> - </arg> - <arg type="s" name="to" direction="in"> - <tp:docstring> - If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified. - </tp:docstring> - </arg> - </method> - - <method name="refuse" tp:name-for-bindings="refuse"> - <tp:docstring> - Refuse an incoming call. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The callID. - </tp:docstring> - </arg> - - </method> - - <method name="accept" tp:name-for-bindings="accept"> - <tp:docstring> - Answer an incoming call. Automatically put the current call on state HOLD. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The callID. - </tp:docstring> - </arg> - </method> - - <method name="hangUp" tp:name-for-bindings="hangUp"> - <tp:docstring> - Hangup a call in state "CURRENT" or "HOLD". - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The callID. - </tp:docstring> - </arg> - </method> - - <method name="hangUpConference" tp:name-for-bindings="hangUpConference"> - <tp:added version="0.9.7"/> - <tp:docstring> - Hangup a conference, and every call participating to the conference. - </tp:docstring> - <arg type="s" name="confID" direction="in"> - <tp:docstring> - The unique conference ID. - </tp:docstring> - </arg> - </method> - - <method name="hold" tp:name-for-bindings="hold"> - <tp:docstring> - Place a call on hold. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The callID. - </tp:docstring> - </arg> - </method> - - <method name="unhold" tp:name-for-bindings="unhold"> - <tp:docstring> - Hold off a call, and place this call on state CURRENT. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The callID. - </tp:docstring> - </arg> - </method> - - <method name="transfer" tp:name-for-bindings="transfer"> - <tp:docstring> - Transfer a call to given phone number. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The callID. - </tp:docstring> - </arg> - <arg type="s" name="to" direction="in"> - <tp:docstring> - The phone number to transfer the call to. - </tp:docstring> - </arg> - </method> - - <method name="attendedTransfer" tp:name-for-bindings="attendedTransfer"> - <tp:docstring> - Perform an attended transfer on two calls - </tp:docstring> - <arg type="s" name="transferID" direction="in"> - <tp:docstring> - The callID of the call to be transfered. - </tp:docstring> - </arg> - <arg type="s" name="targetID" direction="in"> - <tp:docstring> - The callID of the target call. - </tp:docstring> - </arg> - </method> - - <method name="playDTMF" tp:name-for-bindings="playDTMF"> - <tp:docstring> - Dual-Tone multi-frequency. Tell the core to play dial tones. A SIP INFO message is sent to notify the server. - </tp:docstring> - <arg type="s" name="key" direction="in"> - <tp:docstring> - Unicode charter for pressed key - </tp:docstring> - </arg> - </method> - - <method name="startTone" tp:name-for-bindings="startTone"> - <tp:docstring> - Start audio stream and play tone.. - </tp:docstring> - <arg type="i" name="start" direction="in"/> - <arg type="i" name="type" direction="in"/> - </method> - - <method name="setVolume" tp:name-for-bindings="setVolume"> - <tp:docstring> - <p>Sets the volume using a linear scale [0,100].</p> - <tp:rationale>Pulseaudio has its own mechanism to modify application volume. This method is enabled only if the ALSA API is used.</tp:rationale> - </tp:docstring> - <arg type="s" name="device" direction="in"> - <tp:docstring> - The device: mic or speaker - </tp:docstring> - </arg> - <arg type="d" name="value" direction="in"> - <tp:docstring> - The volume value (between 0 and 100) - </tp:docstring> - </arg> - </method> - - <method name="getVolume" tp:name-for-bindings="getVolume"> - <tp:docstring> - <p>Return the volume value of the given device on a linear scale [0,100].</p> - <tp:rationale>Only enabled if the ALSA API is used, Pulseaudio has its own mechanism to modify application volume.</tp:rationale> - </tp:docstring> - <arg type="s" name="device" direction="in"> - <tp:docstring> - The device: mic or speaker - </tp:docstring> - </arg> - <arg type="d" name="value" direction="out"> - <tp:docstring> - The volume value (between 0 and 100) - </tp:docstring> - </arg> - </method> - - <method name="joinParticipant" tp:name-for-bindings="joinParticipant"> - <tp:added version="0.9.7"/> - <tp:docstring> - <p>Join two participants together to create a 3-way conference including the current client.</p> - <tp:rationale>The signal <tp:member-ref>conferenceCreated</tp:member-ref> is emitted on success.</tp:rationale> - </tp:docstring> - <arg type="s" name="sel_callID" direction="in"/> - <arg type="s" name="drag_callID" direction="in"/> - </method> - - <method name="createConfFromParticipantList" tp:name-for-bindings="createConfFromParticipantList"> - <tp:added version="0.9.14"/> - <tp:docstring> - <p>Create a conference from a list of participant</p> - <tp:rationale>The signal <tp:member-ref>conferenceCreated</tp:member-ref> is emitted on success.</tp:rationale> - </tp:docstring> - <arg type="as" name="participants" direction="in"/> - </method> - - <method name="addParticipant" tp:name-for-bindings="addParticipant"> - <tp:added version="0.9.7"/> - <tp:docstring> - <p>Join a new particiant to an existing conference.</p> - <tp:rationale>The signal <tp:member-ref>conferenceChanged</tp:member-ref> is emitted on success.</tp:rationale> - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The ID of the call to add to the conference - </tp:docstring> - </arg> - <arg type="s" name="confID" direction="in"> - <tp:docstring> - An existing conference ID - </tp:docstring> - </arg> - </method> - - <method name="addMainParticipant" tp:name-for-bindings="addMainParticipant"> - <tp:added version="0.9.7"/> - <tp:docstring> - <p>As the core can handle multiple calls an conferences, it may happens that the client's user leave a conference to answer an incoming call or send new ones. This method is used to reintroduce SFLphone-client's user into the conference.</p> - <p>It put the current call on state HOLD or detach SFLphone-client's user from the another conference.</p> - </tp:docstring> - <arg type="s" name="confID" direction="in"> - <tp:docstring> - An existing conference ID - </tp:docstring> - </arg> - </method> - - <method name="detachParticipant" tp:name-for-bindings="detachParticipant"> - <tp:added version="0.9.7"/> - <tp:docstring> - Detach the given call from the conference. If only one participant is left, the conference is deleted and the signal <tp:member-ref>conferenceRemoved</tp:member-ref> is emited. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The call ID - </tp:docstring> - </arg> - </method> - - <method name="joinConference" tp:name-for-bindings="joinConference"> - <tp:added version="0.9.7"/> - <tp:docstring> - Join two conferences together. - </tp:docstring> - <arg type="s" name="sel_confID" direction="in"/> - <arg type="s" name="drag_confID" direction="in"/> - </method> - - <method name="getConferenceDetails" tp:name-for-bindings="getConferenceDetails"> - <tp:added version="0.9.7"/> - <tp:docstring> - Returns a hashtable containing conference details. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The conference ID - </tp:docstring> - </arg> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="infos" direction="out"> - <tp:docstring> - A map containing the ID of the conferences - and their states: - <ul> - <li>ACTIVE_ATTACHED</li> - <li>ACTIVE_DETACHED</li> - <li>HOLD</li> - </ul> - </tp:docstring> - </arg> - </method> - - <method name="getConferenceList" tp:name-for-bindings="getConferenceList"> - <tp:added version="0.9.7"/> - <tp:docstring> - Returns a list containing all active - conferences. - <tp:rationale>To update client status, one should - use <tp:member-ref>getParticipantList</tp:member-ref> - with provided conference IDs.</tp:rationale> - </tp:docstring> - <arg type="as" name="list" direction="out"> - <tp:docstring> - The list of conferences. - </tp:docstring> - </arg> - </method> - - <method name="setRecording" tp:name-for-bindings="setRecording"> - <tp:docstring> - Start recording a call. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The ID of the call to record. - </tp:docstring> - </arg> - </method> - - <method name="getIsRecording" tp:name-for-bindings="getIsRecording"> - <tp:docstring> - Tells whether or not a call is being recorded. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The call ID. - </tp:docstring> - </arg> - <arg type="b" name="isRecording" direction="out"> - <tp:docstring> - Returns true is the call is being recorded. False otherwise. - </tp:docstring> - </arg> - </method> - - <signal name="recordPlaybackFilepath" tp:name-for-bindings="recordPlaybackFilepath"> - <tp:docstring> - Once after starting recording for the first time, this signal is emited to - provide the recorded file path to client application. - </tp:docstring> - <arg type="s" name="callID" /> - <arg type="s" name="filepath"/> - </signal> - - <signal name="recordPlaybackStopped" tp:name-for-bindings="recordPlaybackStopped"> - <tp:docstring/> - <arg type="s" name="filepath" /> - </signal> - - - <method name="getCallDetails" tp:name-for-bindings="getCallDetails"> - <tp:docstring> - Get all the details about a specific call. - </tp:docstring> - <arg type="s" name="callID" direction="in"> - <tp:docstring> - The call ID. - </tp:docstring> - </arg> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="infos" direction="out" tp:type="String_String_Map"> - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - <p>A map containing the call details: </p> - <ul> - <li>ACCOUNTID</li> - <li>PEER_NUMBER</li> - <li>PEER_NAME</li> - <li>DISPLAY_NAME</li> - <li>CALL_STATE</li> - <li>CALL_TYPE</li> - </ul> - </tp:docstring> - </arg> - </method> - - <method name="getCallList" tp:name-for-bindings="getCallList"> - <tp:docstring> - Get the list of active calls. - <tp:rationale>To get the call details, iterate on the return value and call <tp:member-ref>getCallDetails</tp:member-ref> method.</tp:rationale> - </tp:docstring> - <arg type="as" name="list" direction="out"> - <tp:docstring> - A list of call IDs. - </tp:docstring> - </arg> - </method> - - <method name="getCurrentCallID" tp:name-for-bindings="getCurrentCallID"> - <tp:docstring> - Unused - </tp:docstring> - <arg type="s" name="callID" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getCurrentAudioCodecName" tp:name-for-bindings="getCurrentAudioCodecName"> - <tp:docstring> - Unused - </tp:docstring> - <arg type="s" name="callID" direction="in"/> - <arg type="s" name="codecName" direction="out"/> - </method> - - <method name="sendTextMessage" tp:name-for-bindings="sendTextMessage"> - <tp:docstring> - Send a text message to the specified call - </tp:docstring> - <arg type="s" name="callID" direction="in"/> - <arg type="s" name="message" direction="in"/> - </method> - - <signal name="newCallCreated" tp:name-for-bindings="newCallCreated"> - <tp:docstring> - <p>Notify that a cell have been created.</p> - <p>The callID generated by the daemon must be stored by the clients in order to address other action for - this call. This signal is emitted when call have been created by the daemon itself.</p> - <tp:rationale> The client must subscribe to this signal to handle calls created by other clients </tp:rationale> - </tp:docstring> - <arg type="s" name="accountID"> - <tp:docstring> - The account ID of the calle. Clients must notify teh right account when receiving this signal. - </tp:docstring> - </arg> - <arg type="s" name="callID"> - <tp:docstring> - A new call ID. - </tp:docstring> - </arg> - <arg type="s" name="to"> - <tp:docstring> - The sip uri this call is trying to reach - </tp:docstring> - </arg> - </signal> - - <signal name="incomingCall" tp:name-for-bindings="incomingCall"> - <tp:docstring> - <p>Notify an incoming call.</p> - <p>The callID generated by the daemon must be stored by the clients in order to address other action for - this call. This signal is emitted when we receive a call from a remote peer</p> - <tp:rationale>The client must subscribe to this signal to handle incoming calls.</tp:rationale> - </tp:docstring> - <arg type="s" name="accountID"> - <tp:docstring> - The account ID of the callee. Clients must notify the right account when receiving this signal. - </tp:docstring> - </arg> - <arg type="s" name="callID"> - <tp:docstring> - A new call ID. - </tp:docstring> - </arg> - <arg type="s" name="from"> - <tp:docstring> - The caller phone number. - </tp:docstring> - </arg> - </signal> - - <signal name="incomingMessage" tp:name-for-bindings="incomingMessage"> - <tp:docstring> - Notify clients that a new text message has been received. - </tp:docstring> - <arg type="s" name="callID" /> - <arg type="s" name="from" /> - <arg type="s" name="message" /> - </signal> - - <signal name="callStateChanged" tp:name-for-bindings="callStateChanged"> - <tp:docstring> - <p>Notify of a change in a call state.</p> - <p>The client must subscribe to this signal.</p> - </tp:docstring> - <arg type="s" name="callID"> - <tp:docstring> - The call ID. - </tp:docstring> - </arg> - <arg type="s" name="state" > - <tp:docstring> - The acceptable states are: - <ul> - <li>INCOMING: Initial state of incoming calls</li> - <li>RINGING: Initial state of received outgoing call</li> - <li>CURRENT: The normal active state of an answered call</li> - <li>HUNGUP: Notify that the call has been hungup by peer</li> - <li>BUSY</li> - <li>FAILURE: Error when processing a call</li> - <li>HOLD</li> - <li>UNHOLD_CURRENT</li> - <li>UNHOLD_RECORD</li> - </ul> - </tp:docstring> - </arg> - </signal> - - <signal name="conferenceChanged" tp:name-for-bindings="conferenceChanged"> - <tp:added version="0.9.7"/> - <tp:docstring> - Notify of a change in the conferences state - </tp:docstring> - <arg type="s" name="confID"> - <tp:docstring> - The conference ID. - </tp:docstring> - </arg> - <arg type="s" name="state"> - <tp:docstring> - The acceptable states are: - <ul> - <li>ACTIVE_ATTACHED: SFLphone user is - participating to this conference</li> - <li>ACTIVE_DETACHED: This situation can - occur if a call is received while - SFLphone user is participating to a - conference. In this case, one can leave - the conference by answering the - call. Other participants may continue - conferencing normally.</li> - <li>HOLD: Each call in this conference - is on state HOLD</li> - </ul> - </tp:docstring> - </arg> - </signal> - - <method name="getParticipantList" tp:name-for-bindings="getParticipantList"> - <tp:added version="0.9.7"/> - <tp:docstring> - Get the call IDs of every participant to a given conference. The client should keep and update the list of participant. - </tp:docstring> - <arg type="s" name="confID" direction="in"> - <tp:docstring> - The conference ID. - </tp:docstring> - </arg> - <arg type="as" name="list" direction="out"> - <tp:docstring> - The list of the call IDs. - </tp:docstring> - </arg> - </method> - - <signal name="conferenceCreated" tp:name-for-bindings="conferenceCreated"> - <tp:added version="0.9.7"/> - <tp:docstring> - Emited when a new conference is created. SFLphone-client is reponsible to store the confID and call <tp:member-ref>getParticipantList</tp:member-ref> to update the display. - </tp:docstring> - <arg type="s" name="confID"> - <tp:docstring> - A new conference ID. - </tp:docstring> - </arg> - </signal> - - <signal name="conferenceRemoved" tp:name-for-bindings="conferenceRemoved"> - <tp:added version="0.9.7"/> - <tp:docstring> - Emited when a new conference is remove. SFLphone-client should have kept a list of current participant in order to display modification. - </tp:docstring> - <arg type="s" name="confID"> - <tp:docstring> - The conference ID. - </tp:docstring> - </arg> - </signal> - - <method name="holdConference" tp:name-for-bindings="holdConference"> - <tp:added version="0.9.7"/> - <tp:docstring> - Hold on every calls participating to this conference. - </tp:docstring> - <arg type="s" name="confID" direction="in"> - <tp:docstring> - The conference ID. - </tp:docstring> - </arg> - </method> - - <method name="unholdConference" tp:name-for-bindings="unholdConference"> - <tp:added version="0.9.7"/> - <tp:docstring> - Hold off every calls participating to this conference. - </tp:docstring> - <arg type="s" name="confID" direction="in"> - <tp:docstring> - The conference ID. - </tp:docstring> - </arg> - </method> - - <method name="startRecordedFilePlayback" tp:name-for-bindings="startRecordedFilePlayback"> - <tp:added version="0.9.14"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="filepath" direction="in"/> - <arg type="b" name="result" direction="out"/> - </method> - - <method name="stopRecordedFilePlayback" tp:name-for-bindings="stopRecordedFilePlayback"> - <tp:added version="0.9.14"/> - <tp:docstring/> - <arg type="s" name="filepath" direction="in"/> - </method> - - <signal name="sipCallStateChanged" tp:name-for-bindings="sipCallStateChanged"> - <tp:docstring> - <p>Call state changed, SFLphone received a notification - from registrar concerning this call.</p> - </tp:docstring> - <arg type="s" name="callID" /> - <tp:docstring> - The call ID - </tp:docstring> - <arg type="s" name="state" /> - <tp:docstring> - Description string - </tp:docstring> - <arg type="i" name="code" /> - <tp:docstring> - The SIP or IAX2 message code - </tp:docstring> - </signal> - - <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged"> - <tp:docstring> - <p>Account state changed, SFLphone received a notification - from registrar.</p> - </tp:docstring> - <arg type="s" name="accountID" > - <tp:docstring> - The account ID - </tp:docstring> - </arg> - <arg type="s" name="state"> - <tp:docstring> - Description string - </tp:docstring> - </arg> - <arg type="i" name="code"> - <tp:docstring> - The SIP or IAX2 message code - </tp:docstring> - </arg> - </signal> - - <signal name="voiceMailNotify" tp:name-for-bindings="voiceMailNotify"> - <tp:docstring> - Notify the clients of the voicemail number for a specific account, if applicable. - </tp:docstring> - <arg type="s" name="accountID"> - <tp:docstring> - The account ID. - </tp:docstring> - </arg> - <arg type="i" name="count"> - <tp:docstring> - The number of waiting messages. - </tp:docstring> - </arg> - </signal> - - <signal name="volumeChanged" tp:name-for-bindings="volumeChanged"> - <tp:docstring> - <p>Notify clients of a volume level - change.</p> - <p>This signal occurs only if ALSA is - enabled since Pulseaudio streams are - managed externally. </p> - </tp:docstring> - <arg type="s" name="device"> - <tp:docstring> - The device: mic or speaker - </tp:docstring> - </arg> - <arg type="d" name="value"> - <tp:docstring> - The new volume value - </tp:docstring> - </arg> - </signal> - - <signal name="transferSucceded" tp:name-for-bindings="transferSucceded"> - <tp:docstring> - <p>Transfer has been successfully - processed. Client should remove transfered - call from call list as it is no longer - accessible in SFLphone-daemon.</p> - </tp:docstring> - </signal> - - <signal name="transferFailed" tp:name-for-bindings="transferFailed"> - <tp:docstring> - <p>Transfer operation failed. Corespondin - call is no longer accessible in - SFLphone-daemon.</p> - </tp:docstring> - </signal> - - <signal name="secureSdesOn" tp:name-for-bindings="secureSdesOn"> - <tp:added version="0.9.7"/> - <tp:docstring> - <p>Signal sent on SDES session success. Media transmission is encripted - for this call only. It does not apply for a - conference.</p> - <p>A conference can be considered to be secured if and only if each - participant is secured.</p> - </tp:docstring> - <arg type="s" name="callID"/> - </signal> - - <signal name="secureSdesOff" tp:name-for-bindings="secureSdesOff"> - <tp:added version="0.9.7"/> - <tp:docstring> - <p>Sinal sent to notify that SDES session - failed.</p> - <p>Media transmission is not encrypted.</p> - </tp:docstring> - <arg type="s" name="callID" /> - </signal> - - <!-- ZRTP Methods and Signals --> - <signal name="secureZrtpOn" tp:name-for-bindings="secureZrtpOn"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" /> - <arg type="s" name="cipher" /> - </signal> - - <signal name="secureZrtpOff" tp:name-for-bindings="secureZrtpOff"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" /> - </signal> - - <signal name="confirmGoClear" tp:name-for-bindings="confirmGoClear"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" /> - </signal> - - <signal name="zrtpNegotiationFailed" tp:name-for-bindings="zrtpNegotiationFailed"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" /> - <arg type="s" name="reason" /> - <arg type="s" name="severity" /> - </signal> - - <signal name="zrtpNotSuppOther" tp:name-for-bindings="zrtpNotSuppOther"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" /> - </signal> - - <signal name="showSAS" tp:name-for-bindings="showSAS"> - <tp:added version="0.9.7"/> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" /> - <arg type="s" name="sas" /> - <arg type="b" name="verified"/> - </signal> - - <method name="setSASVerified" tp:name-for-bindings="setSASVerified"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="resetSASVerified" tp:name-for-bindings="resetSASVerified"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="setConfirmGoClear" tp:name-for-bindings="setConfirmGoClear"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="requestGoClear" tp:name-for-bindings="requestGoClear"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="acceptEnrollment" tp:name-for-bindings="acceptEnrollment"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" direction="in"/> - <arg type="b" name="accepted" direction="in"/> - </method> - - <method name="setPBXEnrollment" tp:name-for-bindings="setPBXEnrollment"> - <tp:added version="0.9.7"/> - <tp:docstring> - </tp:docstring> - <arg type="s" name="callID" direction="in"/> - <arg type="b" name="yesNo" direction="in"/> - </method> - - </interface> + <interface name="org.sflphone.SFLphone.CallManager"> + + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The CallManager interface is used to manage call and conference related actions.</p> + <p>Since SFLphone-daemon supports multiple incoming/outgoing calls, any actions involving a specific call must address the method by the means of a unique callID. + SFLphone-clients is responsible for generating the callID on outgoing calls. Conversely, SFLphone-daemon will generate a unique callID for incoming calls.</p> + </tp:docstring> + <method name="placeCall" tp:name-for-bindings="placeCall"> + <tp:docstring> + <p>This is the main method in order to place a new call. The call is registered with the daemon using this method.</p> + </tp:docstring> + <arg type="s" name="accountID" direction="in"> + <tp:docstring> + The ID of the account with which you want to make a call. If the call is to be placed without any account by means of a SIP URI (i.e. sip:num@server), the "IP2IP_PROFILE" is passed as the accountID. For more details on accounts see the configuration manager interface. + </tp:docstring> + </arg> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID is a unique identifier that must be randomly generated on the client's side. Any subsequent actions refering to this call must use this callID. + </tp:docstring> + </arg> + <arg type="s" name="to" direction="in"> + <tp:docstring> + If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified. + </tp:docstring> + </arg> + </method> + + <method name="placeCallFirstAccount" tp:name-for-bindings="placeCallFirstAccount"> + <tp:added version="0.9.8"/> + <tp:docstring> + Place a call with the first registered account in the account list. + <tp:rationale> + Use this function when you don't have any information about the accounts used (Ex: Firefly mozilla extension) + </tp:rationale> + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID is a unique identifier that must be randomly generated on the client's side. Any subsequent actions refering to this call must use this callID. + </tp:docstring> + </arg> + <arg type="s" name="to" direction="in"> + <tp:docstring> + If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified. + </tp:docstring> + </arg> + </method> + + <method name="refuse" tp:name-for-bindings="refuse"> + <tp:docstring> + Refuse an incoming call. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + + </method> + + <method name="accept" tp:name-for-bindings="accept"> + <tp:docstring> + Answer an incoming call. Automatically puts the current call on HOLD. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + </method> + + <method name="hangUp" tp:name-for-bindings="hangUp"> + <tp:docstring> + Hangup a call in state "CURRENT" or "HOLD". + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + </method> + + <method name="hangUpConference" tp:name-for-bindings="hangUpConference"> + <tp:added version="0.9.7"/> + <tp:docstring> + Hangup a conference, and every call participating to the conference. + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + The unique conference ID. + </tp:docstring> + </arg> + </method> + + <method name="hold" tp:name-for-bindings="hold"> + <tp:docstring> + Place a call on hold. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + </method> + + <method name="unhold" tp:name-for-bindings="unhold"> + <tp:docstring> + Take a call off hold, and place this call in state CURRENT. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + </method> + + <method name="transfer" tp:name-for-bindings="transfer"> + <tp:docstring> + Transfer a call to the given phone number. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + <arg type="s" name="to" direction="in"> + <tp:docstring> + The phone number to which the call will be transferred. + </tp:docstring> + </arg> + </method> + + <method name="attendedTransfer" tp:name-for-bindings="attendedTransfer"> + <tp:docstring> + Perform an attended transfer on two calls. + </tp:docstring> + <arg type="s" name="transferID" direction="in"> + <tp:docstring> + The callID of the call to be transfered. + </tp:docstring> + </arg> + <arg type="s" name="targetID" direction="in"> + <tp:docstring> + The callID of the target call. + </tp:docstring> + </arg> + </method> + + <method name="playDTMF" tp:name-for-bindings="playDTMF"> + <tp:docstring> + Dual-Tone multi-frequency. Tell the core to play dialtones. A SIP INFO message is sent to notify the server. + </tp:docstring> + <arg type="s" name="key" direction="in"> + <tp:docstring> + Unicode character for pressed key. + </tp:docstring> + </arg> + </method> + + <method name="startTone" tp:name-for-bindings="startTone"> + <tp:docstring> + Start audio stream and play tone. + </tp:docstring> + <arg type="i" name="start" direction="in"/> + <arg type="i" name="type" direction="in"/> + </method> + + <method name="setVolume" tp:name-for-bindings="setVolume"> + <tp:docstring> + <p>Sets the volume using a linear scale [0,100].</p> + <tp:rationale>Pulseaudio has its own mechanism to modify application volume. This method is enabled only if the ALSA API is used.</tp:rationale> + </tp:docstring> + <arg type="s" name="device" direction="in"> + <tp:docstring> + The device: mic or speaker + </tp:docstring> + </arg> + <arg type="d" name="value" direction="in"> + <tp:docstring> + The volume value (between 0 and 100) + </tp:docstring> + </arg> + </method> + + <method name="getVolume" tp:name-for-bindings="getVolume"> + <tp:docstring> + <p>Return the volume value of the given device on a linear scale [0,100].</p> + <tp:rationale>Only enabled if the ALSA API is used, Pulseaudio has its own mechanism to modify application volume.</tp:rationale> + </tp:docstring> + <arg type="s" name="device" direction="in"> + <tp:docstring> + The device: mic or speaker + </tp:docstring> + </arg> + <arg type="d" name="value" direction="out"> + <tp:docstring> + The volume value (between 0 and 100) + </tp:docstring> + </arg> + </method> + + <method name="joinParticipant" tp:name-for-bindings="joinParticipant"> + <tp:added version="0.9.7"/> + <tp:docstring> + <p>Join two participants together to create a 3-way conference including the current client.</p> + <tp:rationale>The signal <tp:member-ref>conferenceCreated</tp:member-ref> is emitted on success.</tp:rationale> + </tp:docstring> + <arg type="s" name="sel_callID" direction="in"/> + <arg type="s" name="drag_callID" direction="in"/> + </method> + + <method name="createConfFromParticipantList" tp:name-for-bindings="createConfFromParticipantList"> + <tp:added version="0.9.14"/> + <tp:docstring> + <p>Create a conference from a list of participants</p> + <tp:rationale>The signal <tp:member-ref>conferenceCreated</tp:member-ref> is emitted on success.</tp:rationale> + </tp:docstring> + <arg type="as" name="participants" direction="in"/> + </method> + + <method name="addParticipant" tp:name-for-bindings="addParticipant"> + <tp:added version="0.9.7"/> + <tp:docstring> + <p>Join a new particiant to an existing conference.</p> + <tp:rationale>The signal <tp:member-ref>conferenceChanged</tp:member-ref> is emitted on success.</tp:rationale> + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The ID of the call to add to the conference + </tp:docstring> + </arg> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + An existing conference ID + </tp:docstring> + </arg> + </method> + + <method name="addMainParticipant" tp:name-for-bindings="addMainParticipant"> + <tp:added version="0.9.7"/> + <tp:docstring> + <p>As the core can handle multiple calls and conferences, it may happen that the client's user leaves a conference to answer an incoming call or to start new calls. This method is used to reintroduce SFLphone-client's user into the conference.</p> + <p>Its put the current call on HOLD or detaches SFLphone-client's user from the another conference.</p> + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + An existing conference ID + </tp:docstring> + </arg> + </method> + + <method name="detachParticipant" tp:name-for-bindings="detachParticipant"> + <tp:added version="0.9.7"/> + <tp:docstring> + Detach the given call from the conference. If only one participant is left, the conference is deleted and the signal <tp:member-ref>conferenceRemoved</tp:member-ref> is emited. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call ID + </tp:docstring> + </arg> + </method> + + <method name="joinConference" tp:name-for-bindings="joinConference"> + <tp:added version="0.9.7"/> + <tp:docstring> + Join two conferences together. + </tp:docstring> + <arg type="s" name="sel_confID" direction="in"/> + <arg type="s" name="drag_confID" direction="in"/> + </method> + + <method name="getConferenceDetails" tp:name-for-bindings="getConferenceDetails"> + <tp:added version="0.9.7"/> + <tp:docstring> + Returns a hashtable containing conference details. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The conference ID + </tp:docstring> + </arg> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="infos" direction="out"> + <tp:docstring> + A map containing the ID of the conferences + and their states: + <ul> + <li>ACTIVE_ATTACHED</li> + <li>ACTIVE_DETACHED</li> + <li>HOLD</li> + </ul> + </tp:docstring> + </arg> + </method> + + <method name="getConferenceList" tp:name-for-bindings="getConferenceList"> + <tp:added version="0.9.7"/> + <tp:docstring> + Returns a list containing all active + conferences. + <tp:rationale>To update client status, one should + use <tp:member-ref>getParticipantList</tp:member-ref> + with provided conference IDs.</tp:rationale> + </tp:docstring> + <arg type="as" name="list" direction="out"> + <tp:docstring> + The list of conferences. + </tp:docstring> + </arg> + </method> + + <method name="setRecording" tp:name-for-bindings="setRecording"> + <tp:docstring> + Start recording a call. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The ID of the call to record. + </tp:docstring> + </arg> + </method> + + <method name="getIsRecording" tp:name-for-bindings="getIsRecording"> + <tp:docstring> + Tells whether or not a call is being recorded. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call ID. + </tp:docstring> + </arg> + <arg type="b" name="isRecording" direction="out"> + <tp:docstring> + Returns true is the call is being recorded. False otherwise. + </tp:docstring> + </arg> + </method> + + <signal name="recordPlaybackFilepath" tp:name-for-bindings="recordPlaybackFilepath"> + <tp:docstring> + Once after starting recording for the first time, this signal is emited to + provide the recorded file path to client application. + </tp:docstring> + <arg type="s" name="callID" /> + <arg type="s" name="filepath"/> + </signal> + + <signal name="recordPlaybackStopped" tp:name-for-bindings="recordPlaybackStopped"> + <tp:docstring/> + <arg type="s" name="filepath" /> + </signal> + + + <method name="getCallDetails" tp:name-for-bindings="getCallDetails"> + <tp:docstring> + Get all the details about a specific call. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call ID. + </tp:docstring> + </arg> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="infos" direction="out" tp:type="String_String_Map"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>A map containing the call details: </p> + <ul> + <li>ACCOUNTID</li> + <li>PEER_NUMBER</li> + <li>PEER_NAME</li> + <li>DISPLAY_NAME</li> + <li>CALL_STATE</li> + <li>CALL_TYPE</li> + </ul> + </tp:docstring> + </arg> + </method> + + <method name="getCallList" tp:name-for-bindings="getCallList"> + <tp:docstring> + Get the list of active calls. + <tp:rationale>To get the call details, iterate on the return value and call <tp:member-ref>getCallDetails</tp:member-ref> method.</tp:rationale> + </tp:docstring> + <arg type="as" name="list" direction="out"> + <tp:docstring> + A list of call IDs. + </tp:docstring> + </arg> + </method> + + <method name="getCurrentAudioCodecName" tp:name-for-bindings="getCurrentAudioCodecName"> + <arg type="s" name="callID" direction="in"/> + <arg type="s" name="codecName" direction="out"/> + </method> + + <method name="sendTextMessage" tp:name-for-bindings="sendTextMessage"> + <tp:docstring> + Send a text message to the specified call + </tp:docstring> + <arg type="s" name="callID" direction="in"/> + <arg type="s" name="message" direction="in"/> + </method> + + <signal name="newCallCreated" tp:name-for-bindings="newCallCreated"> + <tp:docstring> + <p>Notify that a call has been created.</p> + <p>The callID generated by the daemon must be stored by the clients in order to address other actions for + this call. This signal is emitted when call haves been created by the daemon itself.</p> + <tp:rationale>The client must subscribe to this signal to handle calls created by other clients</tp:rationale> + </tp:docstring> + <arg type="s" name="accountID"> + <tp:docstring> + The account ID of the call. Clients must notify the right account when receiving this signal. + </tp:docstring> + </arg> + <arg type="s" name="callID"> + <tp:docstring> + A new call ID. + </tp:docstring> + </arg> + <arg type="s" name="to"> + <tp:docstring> + The SIP URI this call is trying to reach. + </tp:docstring> + </arg> + </signal> + + <signal name="incomingCall" tp:name-for-bindings="incomingCall"> + <tp:docstring> + <p>Notify an incoming call.</p> + <p>The callID generated by the daemon must be stored by the clients in order to address other action for + this call. This signal is emitted when we receive a call from a remote peer</p> + <tp:rationale>The client must subscribe to this signal to handle incoming calls.</tp:rationale> + </tp:docstring> + <arg type="s" name="accountID"> + <tp:docstring> + The account ID of the callee. Clients must notify the right account when receiving this signal. + </tp:docstring> + </arg> + <arg type="s" name="callID"> + <tp:docstring> + A new call ID. + </tp:docstring> + </arg> + <arg type="s" name="from"> + <tp:docstring> + The caller phone number. + </tp:docstring> + </arg> + </signal> + + <signal name="incomingMessage" tp:name-for-bindings="incomingMessage"> + <tp:docstring> + Notify clients that a new text message has been received. + </tp:docstring> + <arg type="s" name="callID" /> + <arg type="s" name="from" /> + <arg type="s" name="message" /> + </signal> + + <signal name="callStateChanged" tp:name-for-bindings="callStateChanged"> + <tp:docstring> + <p>Notify of a change in a call state.</p> + <p>The client must subscribe to this signal.</p> + </tp:docstring> + <arg type="s" name="callID"> + <tp:docstring> + The call ID. + </tp:docstring> + </arg> + <arg type="s" name="state" > + <tp:docstring> + The acceptable states are: + <ul> + <li>INCOMING: Initial state of incoming calls</li> + <li>RINGING: Initial state of received outgoing call</li> + <li>CURRENT: The normal active state of an answered call</li> + <li>HUNGUP: Notify that the call has been hungup by peer</li> + <li>BUSY</li> + <li>FAILURE: Error when processing a call</li> + <li>HOLD</li> + <li>UNHOLD_CURRENT</li> + <li>UNHOLD_RECORD</li> + </ul> + </tp:docstring> + </arg> + </signal> + + <signal name="conferenceChanged" tp:name-for-bindings="conferenceChanged"> + <tp:added version="0.9.7"/> + <tp:docstring> + Notify of a change in the conferences state + </tp:docstring> + <arg type="s" name="confID"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + <arg type="s" name="state"> + <tp:docstring> + The acceptable states are: + <ul> + <li>ACTIVE_ATTACHED: SFLphone user is + participating to this conference</li> + <li>ACTIVE_DETACHED: This situation can + occur if a call is received while + SFLphone user is participating to a + conference. In this case, one can leave + the conference by answering the + call. Other participants may continue + conferencing normally.</li> + <li>HOLD: Each call in this conference + is on state HOLD</li> + </ul> + </tp:docstring> + </arg> + </signal> + + <method name="getParticipantList" tp:name-for-bindings="getParticipantList"> + <tp:added version="0.9.7"/> + <tp:docstring> + Get the call IDs of every participant to a given conference. The client should keep and update the list of participants. + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + <arg type="as" name="list" direction="out"> + <tp:docstring> + The list of the call IDs. + </tp:docstring> + </arg> + </method> + + <signal name="conferenceCreated" tp:name-for-bindings="conferenceCreated"> + <tp:added version="0.9.7"/> + <tp:docstring> + Emited when a new conference is created. SFLphone-client is reponsible for storing the confID and call <tp:member-ref>getParticipantList</tp:member-ref> to update the display. + </tp:docstring> + <arg type="s" name="confID"> + <tp:docstring> + A new conference ID. + </tp:docstring> + </arg> + </signal> + + <signal name="conferenceRemoved" tp:name-for-bindings="conferenceRemoved"> + <tp:added version="0.9.7"/> + <tp:docstring> + Emited when a new conference is remove. SFLphone-client should have kept a list of current participant in order to display modification. + </tp:docstring> + <arg type="s" name="confID"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + </signal> + + <method name="holdConference" tp:name-for-bindings="holdConference"> + <tp:added version="0.9.7"/> + <tp:docstring> + Hold every call which is participating in this conference. + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + </method> + + <method name="unholdConference" tp:name-for-bindings="unholdConference"> + <tp:added version="0.9.7"/> + <tp:docstring> + Hold off every call participating in this conference. + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + </method> + + <method name="startRecordedFilePlayback" tp:name-for-bindings="startRecordedFilePlayback"> + <tp:added version="0.9.14"/> + <arg type="s" name="filepath" direction="in"/> + <arg type="b" name="result" direction="out"/> + </method> + + <method name="stopRecordedFilePlayback" tp:name-for-bindings="stopRecordedFilePlayback"> + <tp:added version="0.9.14"/> + <tp:docstring/> + <arg type="s" name="filepath" direction="in"/> + </method> + + <signal name="sipCallStateChanged" tp:name-for-bindings="sipCallStateChanged"> + <tp:docstring> + <p>Call state changed, SFLphone received a notification + from registrar concerning this call.</p> + </tp:docstring> + <arg type="s" name="callID" /> + <tp:docstring> + The call ID + </tp:docstring> + <arg type="s" name="state" /> + <tp:docstring> + Description string + </tp:docstring> + <arg type="i" name="code" /> + <tp:docstring> + The SIP or IAX2 message code + </tp:docstring> + </signal> + + <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged"> + <tp:docstring> + <p>Account state changed, SFLphone received a notification + from registrar.</p> + </tp:docstring> + <arg type="s" name="accountID" > + <tp:docstring> + The account ID + </tp:docstring> + </arg> + <arg type="s" name="state"> + <tp:docstring> + Description string + </tp:docstring> + </arg> + <arg type="i" name="code"> + <tp:docstring> + The SIP or IAX2 message code + </tp:docstring> + </arg> + </signal> + + <signal name="voiceMailNotify" tp:name-for-bindings="voiceMailNotify"> + <tp:docstring> + Notify the clients of the voicemail number for a specific account, if applicable. + </tp:docstring> + <arg type="s" name="accountID"> + <tp:docstring> + The account ID. + </tp:docstring> + </arg> + <arg type="i" name="count"> + <tp:docstring> + The number of waiting messages. + </tp:docstring> + </arg> + </signal> + + <signal name="volumeChanged" tp:name-for-bindings="volumeChanged"> + <tp:docstring> + <p>Notify clients of a volume level change.</p> + <p>This signal occurs only if ALSA is enabled since Pulseaudio streams are managed externally. </p> + </tp:docstring> + <arg type="s" name="device"> + <tp:docstring> + The device: mic or speaker + </tp:docstring> + </arg> + <arg type="d" name="value"> + <tp:docstring> + The new volume value + </tp:docstring> + </arg> + </signal> + + <signal name="transferSucceeded" tp:name-for-bindings="transferSucceeded"> + <tp:docstring> + <p>Transfer has been successfully + processed. Client should remove transfered + call from call list as it is no longer + accessible in SFLphone-daemon.</p> + </tp:docstring> + </signal> + + <signal name="transferFailed" tp:name-for-bindings="transferFailed"> + <tp:docstring> + <p>Transfer operation failed. Corresponding + call is no longer accessible in + SFLphone-daemon.</p> + </tp:docstring> + </signal> + + <signal name="secureSdesOn" tp:name-for-bindings="secureSdesOn"> + <tp:added version="0.9.7"/> + <tp:docstring> + <p>Signal sent on SDES session success. Media transmission is encripted + for this call only. It does not apply for a conference.</p> + <p>A conference can be considered to be secured if and only if each + participant is secured.</p> + </tp:docstring> + <arg type="s" name="callID"/> + </signal> + + <signal name="secureSdesOff" tp:name-for-bindings="secureSdesOff"> + <tp:added version="0.9.7"/> + <tp:docstring> + <p>Sinal sent to notify that SDES session failed.</p> + <p>Media transmission is not encrypted.</p> + </tp:docstring> + <arg type="s" name="callID" /> + </signal> + + <!-- ZRTP Methods and Signals --> + <signal name="secureZrtpOn" tp:name-for-bindings="secureZrtpOn"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" /> + <arg type="s" name="cipher" /> + </signal> + + <signal name="secureZrtpOff" tp:name-for-bindings="secureZrtpOff"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" /> + </signal> + + <signal name="confirmGoClear" tp:name-for-bindings="confirmGoClear"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" /> + </signal> + + <signal name="zrtpNegotiationFailed" tp:name-for-bindings="zrtpNegotiationFailed"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" /> + <arg type="s" name="reason" /> + <arg type="s" name="severity" /> + </signal> + + <signal name="zrtpNotSuppOther" tp:name-for-bindings="zrtpNotSuppOther"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" /> + </signal> + + <signal name="showSAS" tp:name-for-bindings="showSAS"> + <tp:added version="0.9.7"/> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" /> + <arg type="s" name="sas" /> + <arg type="b" name="verified"/> + </signal> + + <method name="setSASVerified" tp:name-for-bindings="setSASVerified"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" direction="in"/> + </method> + + <method name="resetSASVerified" tp:name-for-bindings="resetSASVerified"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" direction="in"/> + </method> + + <method name="setConfirmGoClear" tp:name-for-bindings="setConfirmGoClear"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" direction="in"/> + </method> + + <method name="requestGoClear" tp:name-for-bindings="requestGoClear"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" direction="in"/> + </method> + + <method name="acceptEnrollment" tp:name-for-bindings="acceptEnrollment"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" direction="in"/> + <arg type="b" name="accepted" direction="in"/> + </method> + + <method name="setPBXEnrollment" tp:name-for-bindings="setPBXEnrollment"> + <tp:added version="0.9.7"/> + <arg type="s" name="callID" direction="in"/> + <arg type="b" name="yesNo" direction="in"/> + </method> + + </interface> </node> diff --git a/kde/src/lib/dbus/configurationmanager-introspec.xml b/kde/src/lib/dbus/configurationmanager-introspec.xml index 13f666940b39300c39b405ac4abe3ff7ce1e0aa0..926ff774de75a99636920b3dc711ab6914695cb9 100644 --- a/kde/src/lib/dbus/configurationmanager-introspec.xml +++ b/kde/src/lib/dbus/configurationmanager-introspec.xml @@ -1,107 +1,97 @@ <?xml version="1.0" ?> <node name="/configurationmanager-introspec" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> - <interface name="org.sflphone.SFLphone.ConfigurationManager"> - - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - Used to handle the configuration stuff: accounts settings, account registration, user preferences, ... - </tp:docstring> - - <method name="getAccountDetails" tp:name-for-bindings="getAccountDetails"> - <tp:docstring> - Get all parameters of the specified account. - </tp:docstring> - <arg type="s" name="accountID" direction="in"> - <tp:docstring> - The account ID - </tp:docstring> - </arg> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="details" direction="out" tp:type="String_String_Map"> - <tp:docstring> - The available keys / parameters are: - <ul> - <li>CONFIG_ACCOUNT_ENABLE: True or False (Default: True)</li> - <li>CONFIG_ACCOUNT_RESOLVE_ONCE</li> - <li>CONFIG_ACCOUNT_TYPE: SIP or IAX2 (Default: SIP)</li> - <li>HOSTNAME: The IP adress or hostname of the registrar</li> - <li>USERNAME: The username (or extension) of the account</li> - <li>PASSWORD: The password associated to the account</li> - <li>REALM</li> - <li>CONFIG_ACCOUNT_MAILBOX: Number to dial to access the voicemail box</li> - <li>CONFIG_ACCOUNT_REGISTRATION_EXPIRE: SIP header expiration value (Default: 1600)</li> - <li>LOCAL_INTERFACE: The network interface (Default: eth0)</li> - <li>PUBLISHED_SAMEAS_LOCAL: If False, the published address equals the local address. This is the default.</li> - <li>PUBLISHED_ADDRESS: The SIP published address</li> - <li>LOCAL_PORT: The SIP listening port (Default: 5060)</li> - <li>PUBLISHED_PORT: The SIP published port</li> - <li>DISPLAY_NAMEL: The display name</li> - <li>STUN_ENABLE: True or False (Default: False)</li> - <li>STUN_SERVER: The STUN server address</li> - <li>REGISTRATION_STATUS: The account registration status. Should be Registered to make calls.</li> - <li>REGISTRATION_STATE_CODE</li> - <li>REGISTRATION_STATE_DESCRIPTION</li> - <li>SRTP_KEY_EXCHANGE</li> - <li>SRTP_ENABLE: Whether or not voice communication are encrypted - True or False (Default: False)</li> - <li>SRTP_RTP_FALLBACK</li> - <li>ZRTP_DISPLAY_SAS</li> - <li>ZRTP_DISPLAY_SAS_ONCE</li> - <li>ZRTP_HELLO_HASH</li> - <li>ZRTP_NOT_SUPP_WARNING</li> - <li>TLS_LISTENER_PORT: TLS listening port (Default: 5061)</li> - <li>TLS_ENABLE: Whether or not signalling is encrypted - True or False (Default: False)</li> - <li>TLS_CA_LIST_FILE</li> - <li>TLS_CERTIFICATE_FILE</li> - <li>TLS_PRIVATE_KEY_FILE</li> - <li>TLS_METHOD</li> - <li>TLS_CIPHERS</li> - <li>TLS_SERVER_NAME</li> - <li>TLS_VERIFY_SERVER</li> - <li>TLS_VERIFY_CLIENT</li> - <li>TLS_REQUIRE_CLIENT_CERTIFICATE</li> - <li>TLS_NEGOTIATION_TIMEOUT_SEC</li> - <li>TLS_NEGOTIATION_TIMEOUT_MSEC</li> - </ul> - </tp:docstring> - </arg> - </method> - - <method name="setAccountDetails" tp:name-for-bindings="setAccountDetails"> - <tp:docstring> - Send new account parameters, or account parameters changes, to the core. The hash table is not required to be complete, only the updated parameters may be specified. - <tp:rationale>Account settings are written to the configuration file when sflphone properly quits.</tp:rationale> - <tp:rationale>After calling this method, the core will emit the signal <tp:member-ref>accountsChanged</tp:member-ref> with the updated data. The client must subscribe to this signal and use it to update its internal data structure.</tp:rationale> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="MapStringString"/> - <arg type="s" name="accountID" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - <arg type="a{ss}" name="details" direction="in" tp:type="String_String_Map"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setCredentials" tp:name-for-bindings="setCredentials"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="accountID" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="VectorMapStringString"/> - <arg type="aa{ss}" name="credentialInformation" direction="in" tp:type="String_String_Map"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getIp2IpDetails" tp:name-for-bindings="getIp2IpDetails"> + <interface name="org.sflphone.SFLphone.ConfigurationManager"> + + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + Used to handle the configuration stuff: accounts settings, account registration, user preferences, ... + </tp:docstring> + + <method name="getAccountDetails" tp:name-for-bindings="getAccountDetails"> + <tp:docstring> + Get all parameters of the specified account. + </tp:docstring> + <arg type="s" name="accountID" direction="in"> + <tp:docstring> + The account ID + </tp:docstring> + </arg> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="out" tp:type="String_String_Map"> + <tp:docstring> + The available keys / parameters are: + <ul> + <li>CONFIG_ACCOUNT_ENABLE: True or False (Default: True)</li> + <li>CONFIG_ACCOUNT_RESOLVE_ONCE</li> + <li>CONFIG_ACCOUNT_TYPE: SIP or IAX2 (Default: SIP)</li> + <li>HOSTNAME: The IP adress or hostname of the registrar</li> + <li>USERNAME: The username (or extension) of the account</li> + <li>PASSWORD: The password associated to the account</li> + <li>REALM</li> + <li>CONFIG_ACCOUNT_MAILBOX: Number to dial to access the voicemail box</li> + <li>CONFIG_ACCOUNT_REGISTRATION_EXPIRE: SIP header expiration value (Default: 1600)</li> + <li>LOCAL_INTERFACE: The network interface (Default: eth0)</li> + <li>PUBLISHED_SAMEAS_LOCAL: If False, the published address equals the local address. This is the default.</li> + <li>PUBLISHED_ADDRESS: The SIP published address</li> + <li>LOCAL_PORT: The SIP listening port (Default: 5060)</li> + <li>PUBLISHED_PORT: The SIP published port</li> + <li>DISPLAY_NAMEL: The display name</li> + <li>STUN_ENABLE: True or False (Default: False)</li> + <li>STUN_SERVER: The STUN server address</li> + <li>REGISTRATION_STATUS: The account registration status. Should be Registered to make calls.</li> + <li>REGISTRATION_STATE_CODE</li> + <li>REGISTRATION_STATE_DESCRIPTION</li> + <li>SRTP_KEY_EXCHANGE</li> + <li>SRTP_ENABLE: Whether or not voice communication are encrypted - True or False (Default: False)</li> + <li>SRTP_RTP_FALLBACK</li> + <li>ZRTP_DISPLAY_SAS</li> + <li>ZRTP_DISPLAY_SAS_ONCE</li> + <li>ZRTP_HELLO_HASH</li> + <li>ZRTP_NOT_SUPP_WARNING</li> + <li>TLS_LISTENER_PORT: TLS listening port (Default: 5061)</li> + <li>TLS_ENABLE: Whether or not signalling is encrypted - True or False (Default: False)</li> + <li>TLS_CA_LIST_FILE</li> + <li>TLS_CERTIFICATE_FILE</li> + <li>TLS_PRIVATE_KEY_FILE</li> + <li>TLS_METHOD</li> + <li>TLS_CIPHERS</li> + <li>TLS_SERVER_NAME</li> + <li>TLS_VERIFY_SERVER</li> + <li>TLS_VERIFY_CLIENT</li> + <li>TLS_REQUIRE_CLIENT_CERTIFICATE</li> + <li>TLS_NEGOTIATION_TIMEOUT_SEC</li> + <li>TLS_NEGOTIATION_TIMEOUT_MSEC</li> + </ul> + </tp:docstring> + </arg> + </method> + + <method name="setAccountDetails" tp:name-for-bindings="setAccountDetails"> + <tp:docstring> + Send new account parameters, or account parameters changes, to the core. The hash table is not required to be complete, only the updated parameters may be specified. + <tp:rationale>Account settings are written to the configuration file when sflphone properly quits.</tp:rationale> + <tp:rationale>After calling this method, the core will emit the signal <tp:member-ref>accountsChanged</tp:member-ref> with the updated data. The client must subscribe to this signal and use it to update its internal data structure.</tp:rationale> + </tp:docstring> + <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="MapStringString"/> + <arg type="s" name="accountID" direction="in"> + </arg> + <arg type="a{ss}" name="details" direction="in" tp:type="String_String_Map"> + </arg> + </method> + + <method name="setCredentials" tp:name-for-bindings="setCredentials"> + <arg type="s" name="accountID" direction="in"> + </arg> + <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="VectorMapStringString"/> + <arg type="aa{ss}" name="credentialInformation" direction="in" tp:type="String_String_Map"> + </arg> + </method> + + <method name="getIp2IpDetails" tp:name-for-bindings="getIp2IpDetails"> <tp:docstring> Get configuration settings of the IP2IP_PROFILE. They are sligthly different from account settings since no VoIP accounts are involved. </tp:docstring> <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <!--<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/>--> + <!--<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/>--> <arg type="a{ss}" name="details" direction="out" tp:type="String_String_Map"> <tp:docstring> Available parameters are: @@ -134,597 +124,388 @@ </arg> </method> - <method name="getCredentials" tp:name-for-bindings="getCredentials"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="accountID" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> - <arg type="aa{ss}" name="credentialInformation" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="addAccount" tp:name-for-bindings="addAccount"> - <tp:docstring> - Add a new account. When created, the signal <tp:member-ref>accountsChanged</tp:member-ref> is emitted. The clients must then call <tp:member-ref>getAccountList</tp:member-ref> to update their internal data structure. - <tp:rationale>If no details are specified, the default parameters are used.</tp:rationale> - <tp:rationale>The core tries to register the account as soon it is created.</tp:rationale> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <arg type="a{ss}" name="details" direction="in" tp:type="String_String_Map"> - <tp:docstring> - The new account settings - </tp:docstring> - </arg> - <arg type="s" name="createdAccountId" direction="out"> - <tp:docstring> - A new account ID - </tp:docstring> - </arg> - </method> - - <method name="setAccountsOrder" tp:name-for-bindings="setAccountsOrder"> - <tp:docstring> - Update the accounts order. - <tp:rationale>When placing a call, the first registered account in the list is used.</tp:rationale> - </tp:docstring> - <arg type="s" name="order" direction="in"> - <tp:docstring> - An ordered list of account IDs, delimited by '/' - </tp:docstring> - </arg> - </method> - - <method name="removeAccount" tp:name-for-bindings="removeAccount"> - <tp:docstring> - Remove an existing account. When removed, the signal <tp:member-ref>accountsChanged</tp:member-ref> is emitted. The clients must then call <tp:member-ref>getAccountList</tp:member-ref> to update their internal data structure. - </tp:docstring> - <arg type="s" name="accoundID" direction="in"> - <tp:docstring> - The account to remove, identified by its ID - </tp:docstring> - </arg> - </method> - - <method name="getAccountList" tp:name-for-bindings="getAccountList"> - <tp:docstring> - Get a list of all created accounts, as stored by the core. - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"> - <tp:docstring> - A list of account IDs - </tp:docstring> - </arg> - </method> - - <method name="sendRegister" tp:name-for-bindings="sendRegister"> - <tp:docstring> - Send account registration (REGISTER) to the registrar. - </tp:docstring> - the account if expire=1, unregister if expire=0. - - @param[in] input accountID - --> - <arg type="s" name="accountID" direction="in"> - <tp:docstring> - The account ID - </tp:docstring> - </arg> - <arg type="i" name="expire" direction="in"> - <tp:docstring> - <p>To register, expire must be 1.</p> - <p>To un-register, expire must be 0.</p> - </tp:docstring> - </arg> - </method> - - <method name="getAudioManager" tp:name-for-bindings="getAudioManager"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="api" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setAudioManager" tp:name-for-bindings="setAudioManager"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="api" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getRecordPath" tp:name-for-bindings="getRecordPath"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="rec" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setRecordPath" tp:name-for-bindings="setRecordPath"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="rec" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getIsAlwaysRecording" tp:name-for-bindings="getIsAlwaysRecording"> - <tp:docstring> - </tp:docstring> - <arg type="b" name="res" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setIsAlwaysRecording" tp:name-for-bindings="setIsAlwaysRecording"> - <tp:docstring> - </tp:docstring> - <arg type="b" name="enabled" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <!-- /////////////////////// --> - - <!-- Codecs-related methods --> - - <method name="getAudioCodecList" tp:name-for-bindings="getAudioCodecList"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorInt"/> - <arg type="ai" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getAudioCodecDetails" tp:name-for-bindings="getAudioCodecDetails"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="payload" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="details" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getActiveAudioCodecList" tp:name-for-bindings="getActiveAudioCodecList"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorInt"/> - <arg type="s" name="accountID" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - <arg type="ai" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setActiveAudioCodecList" tp:name-for-bindings="setActiveAudioCodecList"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="VectorString"/> - <arg type="as" name="list" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - <arg type="s" name="accountID" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - - <!-- Audio devices methods --> - - <method name="getAudioPluginList" tp:name-for-bindings="getAudioPluginList"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setAudioPlugin" tp:name-for-bindings="setAudioPlugin"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="audioPlugin" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getAudioOutputDeviceList" tp:name-for-bindings="getAudioOutputDeviceList"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setAudioOutputDevice" tp:name-for-bindings="setAudioOutputDevice"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="index" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setAudioInputDevice" tp:name-for-bindings="setAudioInputDevice"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="index" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setAudioRingtoneDevice" tp:name-for-bindings="setAudioRingtoneDevice"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="index" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getAudioInputDeviceList" tp:name-for-bindings="getAudioInputDeviceList"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - - <method name="getCurrentAudioDevicesIndex" tp:name-for-bindings="getCurrentAudioDevicesIndex"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getAudioDeviceIndex" tp:name-for-bindings="getAudioDeviceIndex"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="name" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - <arg type="i" name="index" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getCurrentAudioOutputPlugin" tp:name-for-bindings="getCurrentAudioOutputPlugin"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="plugin" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> + <method name="getCredentials" tp:name-for-bindings="getCredentials"> + <arg type="s" name="accountID" direction="in"> + </arg> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> + <arg type="aa{ss}" name="credentialInformation" direction="out"> + </arg> + </method> + + <method name="addAccount" tp:name-for-bindings="addAccount"> + <tp:docstring> + Add a new account. When created, the signal <tp:member-ref>accountsChanged</tp:member-ref> is emitted. The clients must then call <tp:member-ref>getAccountList</tp:member-ref> to update their internal data structure. + <tp:rationale>If no details are specified, the default parameters are used.</tp:rationale> + <tp:rationale>The core tries to register the account as soon it is created.</tp:rationale> + </tp:docstring> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="in" tp:type="String_String_Map"> + <tp:docstring> + The new account settings + </tp:docstring> + </arg> + <arg type="s" name="createdAccountId" direction="out"> + <tp:docstring> + A new account ID + </tp:docstring> + </arg> + </method> + + <method name="setAccountsOrder" tp:name-for-bindings="setAccountsOrder"> + <tp:docstring> + Update the accounts order. + <tp:rationale>When placing a call, the first registered account in the list is used.</tp:rationale> + </tp:docstring> + <arg type="s" name="order" direction="in"> + <tp:docstring> + An ordered list of account IDs, delimited by '/' + </tp:docstring> + </arg> + </method> + + <method name="removeAccount" tp:name-for-bindings="removeAccount"> + <tp:docstring> + Remove an existing account. When removed, the signal <tp:member-ref>accountsChanged</tp:member-ref> is emitted. The clients must then call <tp:member-ref>getAccountList</tp:member-ref> to update their internal data structure. + </tp:docstring> + <arg type="s" name="accoundID" direction="in"> + <tp:docstring> + The account to remove, identified by its ID + </tp:docstring> + </arg> + </method> + + <method name="getAccountList" tp:name-for-bindings="getAccountList"> + <tp:docstring> + Get a list of all created accounts, as stored by the core. + </tp:docstring> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + <tp:docstring> + A list of account IDs + </tp:docstring> + </arg> + </method> + + <method name="sendRegister" tp:name-for-bindings="sendRegister"> + <tp:docstring> + Send account registration (REGISTER) to the registrar. + </tp:docstring> + Register the account if enable=true, unregister if enable=false. + + @param[in] input accountID + --> + <arg type="s" name="accountID" direction="in"> + <tp:docstring> + The account ID + </tp:docstring> + </arg> + <arg type="b" name="enable" direction="in"> + <tp:docstring> + <p>To register, enable must be true.</p> + <p>To un-register, enable must be false.</p> + </tp:docstring> + </arg> + </method> + + <method name="getAudioManager" tp:name-for-bindings="getAudioManager"> + <arg type="s" name="api" direction="out"> + </arg> + </method> + + <method name="setAudioManager" tp:name-for-bindings="setAudioManager"> + <arg type="s" name="api" direction="in"> + </arg> + </method> + + <method name="getRecordPath" tp:name-for-bindings="getRecordPath"> + <arg type="s" name="rec" direction="out"> + </arg> + </method> + + <method name="setRecordPath" tp:name-for-bindings="setRecordPath"> + <arg type="s" name="rec" direction="in"> + </arg> + </method> + + <method name="getIsAlwaysRecording" tp:name-for-bindings="getIsAlwaysRecording"> + <arg type="b" name="res" direction="out"> + </arg> + </method> + + <method name="setIsAlwaysRecording" tp:name-for-bindings="setIsAlwaysRecording"> + <arg type="b" name="enabled" direction="in"> + </arg> + </method> + + <!-- /////////////////////// --> + + <!-- Codecs-related methods --> + + <method name="getAudioCodecList" tp:name-for-bindings="getAudioCodecList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorInt"/> + <arg type="ai" name="list" direction="out"> + </arg> + </method> + + <method name="getAudioCodecDetails" tp:name-for-bindings="getAudioCodecDetails"> + <arg type="i" name="payload" direction="in"> + </arg> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="details" direction="out"> + </arg> + </method> + + <method name="getActiveAudioCodecList" tp:name-for-bindings="getActiveAudioCodecList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorInt"/> + <arg type="s" name="accountID" direction="in"> + </arg> + <arg type="ai" name="list" direction="out"> + </arg> + </method> + + <method name="setActiveAudioCodecList" tp:name-for-bindings="setActiveAudioCodecList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="VectorString"/> + <arg type="as" name="list" direction="in"> + </arg> + <arg type="s" name="accountID" direction="in"> + </arg> + </method> + + <!-- Audio devices methods --> + + <method name="getAudioPluginList" tp:name-for-bindings="getAudioPluginList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + </arg> + </method> + + <method name="setAudioPlugin" tp:name-for-bindings="setAudioPlugin"> + <arg type="s" name="audioPlugin" direction="in"> + </arg> + </method> + + <method name="getAudioOutputDeviceList" tp:name-for-bindings="getAudioOutputDeviceList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + </arg> + </method> + + <method name="setAudioOutputDevice" tp:name-for-bindings="setAudioOutputDevice"> + <arg type="i" name="index" direction="in"> + </arg> + </method> + + <method name="setAudioInputDevice" tp:name-for-bindings="setAudioInputDevice"> + <arg type="i" name="index" direction="in"> + </arg> + </method> + + <method name="setAudioRingtoneDevice" tp:name-for-bindings="setAudioRingtoneDevice"> + <arg type="i" name="index" direction="in"> + </arg> + </method> + + <method name="getAudioInputDeviceList" tp:name-for-bindings="getAudioInputDeviceList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + </arg> + </method> + + + <method name="getCurrentAudioDevicesIndex" tp:name-for-bindings="getCurrentAudioDevicesIndex"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + </arg> + </method> + + <method name="getAudioDeviceIndex" tp:name-for-bindings="getAudioDeviceIndex"> + <arg type="s" name="name" direction="in"> + </arg> + <arg type="i" name="index" direction="out"> + </arg> + </method> + + <method name="getCurrentAudioOutputPlugin" tp:name-for-bindings="getCurrentAudioOutputPlugin"> + <arg type="s" name="plugin" direction="out"> + </arg> + </method> <method name="getEchoCancelState" tp:name-for-bindings="getNoiseSuppressState"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="state" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setEchoCancelState" tp:name-for-bindings="setEchoCancelState"> - <arg type="s" name="state" direction="in"> - </arg> - </method> - - <method name="setEchoCancelTailLength" tp:name-for-bindings="setEchoCancelTailLength"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="index" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getEchoCancelTailLength" tp:name-for-bindings="getEchoCancelTailLength"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="index" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setEchoCancelDelay" tp:name-for-bindings="setEchoCancelDelay"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="index" direction="in"> - </arg> - </method> - - <method name="getEchoCancelDelay" tp:name-for-bindings="getEchoCancelDelay"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="index" direction="out"> - </arg> - </method> - - - <method name="getNoiseSuppressState" tp:name-for-bindings="getEchoCancelState"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="state" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setNoiseSuppressState" tp:name-for-bindings="setNoiseSuppressState"> - <arg type="s" name="state" direction="in"> - </arg> - </method> - - <!-- General Settings Panel --> - - <method name="isIax2Enabled" tp:name-for-bindings="isIax2Enabled"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="res" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setMailNotify" tp:name-for-bindings="setMailNotify"> - <tp:docstring> - </tp:docstring> - </method> - - <method name="getMailNotify" tp:name-for-bindings="getMailNotify"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="level" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - - <method name="getHistoryLimit" tp:name-for-bindings="getHistoryLimit"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="days" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setHistoryLimit" tp:name-for-bindings="setHistoryLimit"> - <tp:docstring> - </tp:docstring> - <arg type="i" name="days" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <!-- Addressbook configuration --> - <method name="getAddressbookSettings" tp:name-for-bindings="getAddressbookSettings"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringInt"/> - <arg type="a{si}" name="settings" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setAddressbookSettings" tp:name-for-bindings="setAddressbookSettings"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringInt"/> - <arg type="a{si}" name="settings" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <!-- Addressbook list --> - <method name="getAddressbookList" tp:name-for-bindings="getAddressbookList"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="settings" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setAddressbookList" tp:name-for-bindings="setAddressbookList"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="VectorString"/> - <arg type="as" name="settings" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <!-- Hook configuration --> - <method name="getHookSettings" tp:name-for-bindings="getHookSettings"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="settings" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setHookSettings" tp:name-for-bindings="setHookSettings"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <arg type="a{ss}" name="settings" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getHistory" tp:name-for-bindings="getHistory"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="as" name="entries" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setHistory" tp:name-for-bindings="setHistory"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <arg type="as" name="entries" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <signal name="accountsChanged" tp:name-for-bindings="accountsChanged"> - </signal> - - <signal name="errorAlert" tp:name-for-bindings="errorAlert"> - <arg type="i" name="code"> - <tp:docstring> - </tp:docstring> - </arg> - </signal> - - <!-- TLS Methods --> - <method name="getSupportedTlsMethod" tp:name-for-bindings="getSupportedTlsMethod"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getTlsSettingsDefault" tp:name-for-bindings="getTlsSettingsDefault"> + <arg type="s" name="state" direction="out"> + </arg> + </method> + + <method name="setEchoCancelState" tp:name-for-bindings="setEchoCancelState"> + <arg type="s" name="state" direction="in"> + </arg> + </method> + + <method name="setEchoCancelTailLength" tp:name-for-bindings="setEchoCancelTailLength"> + <arg type="i" name="index" direction="in"> + </arg> + </method> + + <method name="getEchoCancelTailLength" tp:name-for-bindings="getEchoCancelTailLength"> + <arg type="i" name="index" direction="out"> + </arg> + </method> + + <method name="setEchoCancelDelay" tp:name-for-bindings="setEchoCancelDelay"> + <arg type="i" name="index" direction="in"> + </arg> + </method> + + <method name="getEchoCancelDelay" tp:name-for-bindings="getEchoCancelDelay"> + <arg type="i" name="index" direction="out"> + </arg> + </method> + + + <method name="getNoiseSuppressState" tp:name-for-bindings="getEchoCancelState"> + <arg type="s" name="state" direction="out"> + </arg> + </method> + + <method name="setNoiseSuppressState" tp:name-for-bindings="setNoiseSuppressState"> + <arg type="s" name="state" direction="in"> + </arg> + </method> + + <!-- General Settings Panel --> + + <method name="isIax2Enabled" tp:name-for-bindings="isIax2Enabled"> + <arg type="i" name="res" direction="out"> + </arg> + </method> + + <method name="setMailNotify" tp:name-for-bindings="setMailNotify"> + </method> + + <method name="getMailNotify" tp:name-for-bindings="getMailNotify"> + <arg type="i" name="level" direction="out"> + </arg> + </method> + + <method name="getHistoryLimit" tp:name-for-bindings="getHistoryLimit"> + <arg type="i" name="days" direction="out"> + </arg> + </method> + + <method name="setHistoryLimit" tp:name-for-bindings="setHistoryLimit"> + <arg type="i" name="days" direction="in"> + </arg> + </method> + + <!-- Addressbook configuration --> + <method name="getAddressbookSettings" tp:name-for-bindings="getAddressbookSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringInt"/> + <arg type="a{si}" name="settings" direction="out"> + </arg> + </method> + + <method name="setAddressbookSettings" tp:name-for-bindings="setAddressbookSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringInt"/> + <arg type="a{si}" name="settings" direction="in"> + </arg> + </method> + + <!-- Addressbook list --> + <method name="getAddressbookList" tp:name-for-bindings="getAddressbookList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="settings" direction="out"> + </arg> + </method> + + <method name="setAddressbookList" tp:name-for-bindings="setAddressbookList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="VectorString"/> + <arg type="as" name="settings" direction="in"> + </arg> + </method> + + <!-- Hook configuration --> + <method name="getHookSettings" tp:name-for-bindings="getHookSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="settings" direction="out"> + </arg> + </method> + + <method name="setHookSettings" tp:name-for-bindings="setHookSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> + <arg type="a{ss}" name="settings" direction="in"> + </arg> + </method> + + <method name="getHistory" tp:name-for-bindings="getHistory"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> + <!-- Return a List of type Dict<string, string> >...a List of Dicts --> + <arg type="aa{ss}" name="entries" direction="out"/> + </method> + + <method name="clearHistory" tp:name-for-bindings="clearHistory"> + </method> + + <signal name="accountsChanged" tp:name-for-bindings="accountsChanged"> + </signal> + + <signal name="errorAlert" tp:name-for-bindings="errorAlert"> + <arg type="i" name="code"> + </arg> + </signal> + + <!-- TLS Methods --> + <method name="getSupportedTlsMethod" tp:name-for-bindings="getSupportedTlsMethod"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + </arg> + </method> + + <method name="getTlsSettingsDefault" tp:name-for-bindings="getTlsSettingsDefault"> <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <tp:docstring> - </tp:docstring> - <arg type="a{ss}" name="details" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getTlsSettings" tp:name-for-bindings="getTlsSettings"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="details" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setTlsSettings" tp:name-for-bindings="setTlsSettings"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <arg type="a{ss}" name="details" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getAddrFromInterfaceName" tp:name-for-bindings="getAddrFromInterfaceName"> - <tp:docstring> - </tp:docstring> - <arg type="s" name="interface" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - <arg type="s" name="address" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getAllIpInterface" tp:name-for-bindings="getAllIpInterface"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getAllIpInterfaceByName" tp:name-for-bindings="getAllIpInterfaceByName"> - <tp:docstring> - </tp:docstring> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="getShortcuts" tp:name-for-bindings="getShortcuts"> + <arg type="a{ss}" name="details" direction="out"> + </arg> + </method> + + <method name="getTlsSettings" tp:name-for-bindings="getTlsSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="out"> + </arg> + </method> + + <method name="setTlsSettings" tp:name-for-bindings="setTlsSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="in"> + </arg> + </method> + + <method name="getAddrFromInterfaceName" tp:name-for-bindings="getAddrFromInterfaceName"> + <arg type="s" name="interface" direction="in"> + </arg> + <arg type="s" name="address" direction="out"> + </arg> + </method> + + <method name="getAllIpInterface" tp:name-for-bindings="getAllIpInterface"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + </arg> + </method> + + <method name="getAllIpInterfaceByName" tp:name-for-bindings="getAllIpInterfaceByName"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + </arg> + </method> + + <method name="getShortcuts" tp:name-for-bindings="getShortcuts"> <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <tp:docstring> - </tp:docstring> - <arg type="a{ss}" name="shortcutsMap" direction="out"> - <tp:docstring> - </tp:docstring> - </arg> - </method> - - <method name="setShortcuts" tp:name-for-bindings="setShortcuts"> + <arg type="a{ss}" name="shortcutsMap" direction="out"> + </arg> + </method> + + <method name="setShortcuts" tp:name-for-bindings="setShortcuts"> <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <tp:docstring> - </tp:docstring> - <arg type="a{ss}" name="shortcutsMap" direction="in"> - <tp:docstring> - </tp:docstring> - </arg> - </method> + <arg type="a{ss}" name="shortcutsMap" direction="in"> + </arg> + </method> </interface> - </node> +</node> diff --git a/kde/src/lib/instance_interface_singleton.cpp b/kde/src/lib/instance_interface_singleton.cpp index cbf2d744a628e06c8d9832c8fd2653ec749fc5cb..68e700c71b3399cb8110b5f962d36a500ca76704 100644 --- a/kde/src/lib/instance_interface_singleton.cpp +++ b/kde/src/lib/instance_interface_singleton.cpp @@ -27,7 +27,7 @@ InstanceInterface* InstanceInterfaceSingleton::interface InstanceInterface& InstanceInterfaceSingleton::getInstance() { if(!interface->connection().isConnected()) { - throw "Error : sflphoned not connected. Service " + interface->service() + " not connected. From instance interface."; + throw "Error : sflphoned not connected. Service " + interface->service() + " not connected. From instance interface."; } return *interface; } diff --git a/kde/src/lib/instance_interface_singleton.h b/kde/src/lib/instance_interface_singleton.h index 1b29e058d21005f9b589456a6aac04ccb64761d6..00251ce7e4941273283e598c82c95ad6299954f1 100644 --- a/kde/src/lib/instance_interface_singleton.h +++ b/kde/src/lib/instance_interface_singleton.h @@ -18,7 +18,7 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ - + #ifndef INSTANCE_INTERFACE_SINGLETON_H #define INSTANCE_INTERFACE_SINGLETON_H @@ -26,8 +26,8 @@ #include "typedefs.h" /** - @author Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> -*/ + * @author Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> + */ class LIB_EXPORT InstanceInterfaceSingleton { diff --git a/kde/src/lib/sflphone_const.h b/kde/src/lib/sflphone_const.h index 10009f279c6c30b36a3d129b89c5b54940eacd01..a37f8ada776bf728b6e5b0398ddf1b6889f01d60 100644 --- a/kde/src/lib/sflphone_const.h +++ b/kde/src/lib/sflphone_const.h @@ -1,17 +1,17 @@ /* * Copyright (C) 2008 Savoir-Faire Linux inc. - * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> - * + * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -25,7 +25,7 @@ /* @file sflphone_const.h * @brief Contains the global variables for the client code */ - + #define APP_NAME "SFLphone KDE Client" #define SIP 0 @@ -110,63 +110,139 @@ /** Account details */ -#define ACCOUNT_TYPE "Account.type" -#define ACCOUNT_ALIAS "Account.alias" -#define ACCOUNT_ENABLED "Account.enable" -#define ACCOUNT_MAILBOX "Account.mailbox" -#define ACCOUNT_RESOLVE_ONCE "Account.resolveOnce" -#define ACCOUNT_REGISTRATION_EXPIRE "Account.expire" -#define ACCOUNT_SIP_STUN_SERVER "STUN.server" -#define ACCOUNT_SIP_STUN_ENABLED "STUN.enable" -#define ACCOUNT_HOSTNAME "hostname" -#define ACCOUNT_USERNAME "username" -#define ACCOUNT_PASSWORD "password" -#define ACCOUNT_AUTHENTICATION_USERNAME "authenticationUsername" -#define ACCOUNT_REALM "realm" -#define ACCOUNT_KEY_EXCHANGE "SRTP.keyExchange" -#define ACCOUNT_SRTP_ENABLED "SRTP.enable" -#define ACCOUNT_ZRTP_DISPLAY_SAS "ZRTP.displaySAS" -#define ACCOUNT_ZRTP_NOT_SUPP_WARNING "ZRTP.notSuppWarning" -#define ACCOUNT_ZRTP_HELLO_HASH "ZRTP.helloHashEnable" -#define ACCOUNT_DISPLAY_SAS_ONCE "ZRTP.displaySasOnce" -#define KEY_EXCHANGE_NONE "0" -#define ZRTP "1" -#define SDES "2" +// #define ACCOUNT_ID "Account.id" +// #define ACCOUNT_TYPE "Account.type" +// #define ACCOUNT_ALIAS "Account.alias" +// #define ACCOUNT_ENABLED "Account.enable" +// #define ACCOUNT_MAILBOX "Account.mailbox" +// #define ACCOUNT_USERAGENT "Account.useragent" +// #define ACCOUNT_REGISTRATION_EXPIRE "Account.registrationExpire" +// #define ACCOUNT_SIP_STUN_SERVER "STUN.server" +// #define ACCOUNT_SIP_STUN_ENABLED "STUN.enable" +// #define ACCOUNT_DTMF_TYPE "Account.dtmfType" +// #define ACCOUNT_HOSTNAME "Account.hostname" +// #define ACCOUNT_USERNAME "Account.username" +// #define ACCOUNT_ROUTE "Account.routeset" +// #define ACCOUNT_PASSWORD "Account.password" +// #define ACCOUNT_REALM "Account.realm" +// #define ACCOUNT_KEY_EXCHANGE "SRTP.keyExchange" +// #define ACCOUNT_SRTP_ENABLED "SRTP.enable" +// #define ACCOUNT_SRTP_RTP_FALLBACK "SRTP.rtpFallback" +// #define ACCOUNT_ZRTP_DISPLAY_SAS "ZRTP.displaySAS" +// #define ACCOUNT_ZRTP_NOT_SUPP_WARNING "ZRTP.notSuppWarning" +// #define ACCOUNT_ZRTP_HELLO_HASH "ZRTP.helloHashEnable" +// #define ACCOUNT_DISPLAY_SAS_ONCE "ZRTP.displaySasOnce" +// #define KEY_EXCHANGE_NONE "0" +// #define ZRTP "1" +// #define SDES "2" /** TLS */ -#define TLS_LISTENER_PORT "TLS.listenerPort" -#define TLS_ENABLE "TLS.enable" -#define TLS_PORT "TLS.port" -#define TLS_CA_LIST_FILE "TLS.certificateListFile" -#define TLS_CERTIFICATE_FILE "TLS.certificateFile" -#define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" -#define TLS_PASSWORD "TLS.password" -#define TLS_METHOD "TLS.method" -#define TLS_CIPHERS "TLS.ciphers" -#define TLS_SERVER_NAME "TLS.serverName" -#define TLS_VERIFY_SERVER "TLS.verifyServer" -#define TLS_VERIFY_CLIENT "TLS.verifyClient" -#define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" -#define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" -#define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" - -#define LOCAL_INTERFACE "Account.localInterface" -#define PUBLISHED_SAMEAS_LOCAL "Account.publishedSameAsLocal" -#define LOCAL_PORT "Account.localPort" -#define PUBLISHED_PORT "Account.publishedPort" -#define PUBLISHED_ADDRESS "Account.publishedAddress" - -#define REGISTRATION_STATUS "Status" -#define REGISTRATION_STATE_CODE "Registration.code" -#define REGISTRATION_STATE_DESCRIPTION "Registration.description" +// #define TLS_LISTENER_PORT "TLS.listenerPort" +// #define TLS_ENABLE "TLS.enable" +// #define TLS_PORT "TLS.port" +// #define TLS_CA_LIST_FILE "TLS.certificateListFile" +// #define TLS_CERTIFICATE_FILE "TLS.certificateFile" +// #define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" +// #define TLS_PASSWORD "TLS.password" +// #define TLS_METHOD "TLS.method" +// #define TLS_CIPHERS "TLS.ciphers" +// #define TLS_SERVER_NAME "TLS.serverName" +// #define TLS_VERIFY_SERVER "TLS.verifyServer" +// #define TLS_VERIFY_CLIENT "TLS.verifyClient" +// #define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" +// #define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" +// #define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" +// +// #define LOCAL_INTERFACE "Account.localInterface" +// #define PUBLISHED_SAMEAS_LOCAL "Account.publishedSameAsLocal" +// #define LOCAL_PORT "Account.localPort" +// #define PUBLISHED_PORT "Account.publishedPort" +// #define PUBLISHED_ADDRESS "Account.publishedAddress" +// +// #define REGISTRATION_STATUS "Registration.Status" +// #define REGISTRATION_STATE_CODE "Registration.code" +// #define REGISTRATION_STATE_DESCRIPTION "Registration.description" + + +#define IP2IP_PROFILE "IP2IP" + +#define ACCOUNT_ID "Account.id" +#define ACCOUNT_TYPE "Account.type" +#define ACCOUNT_ALIAS "Account.alias" +#define ACCOUNT_ENABLED "Account.enable" +#define ACCOUNT_MAILBOX "Account.mailbox" +#define ACCOUNT_USERAGENT "Account.useragent" +#define ACCOUNT_REGISTRATION_EXPIRE "Account.registrationExpire" +#define ACCOUNT_REGISTRATION_STATUS "Account.registrationStatus" +#define ACCOUNT_REGISTRATION_STATE_CODE "Account.registrationCode" +#define ACCOUNT_REGISTRATION_STATE_DESC "Account.registrationDescription" + +#define ACCOUNT_SIP_STUN_SERVER "STUN.server" +#define ACCOUNT_SIP_STUN_ENABLED "STUN.enable" +#define ACCOUNT_DTMF_TYPE "Account.dtmfType" +#define ACCOUNT_HOSTNAME "Account.hostname" +#define ACCOUNT_USERNAME "Account.username" +#define ACCOUNT_ROUTE "Account.routeset" +#define ACCOUNT_PASSWORD "Account.password" +#define ACCOUNT_REALM "Account.realm" +#define ACCOUNT_KEY_EXCHANGE "SRTP.keyExchange" +#define ACCOUNT_SRTP_ENABLED "SRTP.enable" +#define ACCOUNT_SRTP_RTP_FALLBACK "SRTP.rtpFallback" +#define ACCOUNT_ZRTP_DISPLAY_SAS "ZRTP.displaySAS" +#define ACCOUNT_ZRTP_NOT_SUPP_WARNING "ZRTP.notSuppWarning" +#define ACCOUNT_ZRTP_HELLO_HASH "ZRTP.helloHashEnable" +#define ACCOUNT_DISPLAY_SAS_ONCE "ZRTP.displaySasOnce" +#define KEY_EXCHANGE_NONE "none" +#define ZRTP "zrtp" +#define SDES "sdes" + +#define CONFIG_RINGTONE_PATH "Account.ringtonePath" +#define CONFIG_RINGTONE_ENABLED "Account.ringtoneEnabled" + +#define TLS_LISTENER_PORT "TLS.listenerPort" +#define TLS_ENABLE "TLS.enable" +#define TLS_PORT "TLS.port" +#define TLS_CA_LIST_FILE "TLS.certificateListFile" +#define TLS_CERTIFICATE_FILE "TLS.certificateFile" +#define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" +#define TLS_PASSWORD "TLS.password" +#define TLS_METHOD "TLS.method" +#define TLS_CIPHERS "TLS.ciphers" +#define TLS_SERVER_NAME "TLS.serverName" +#define TLS_VERIFY_SERVER "TLS.verifyServer" +#define TLS_VERIFY_CLIENT "TLS.verifyClient" +#define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" +#define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" +#define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" + +#define SHORTCUT_PICKUP "pickUp" +#define SHORTCUT_HANGUP "hangUp" +#define SHORTCUT_POPUP "popupWindow" +#define SHORTCUT_TOGGLEPICKUPHANGUP "togglePickupHangup" +#define SHORTCUT_TOGGLEHOLD "toggleHold" + + +#define CONFIG_ACCOUNT_HOSTNAME "Account.hostname" +#define CONFIG_ACCOUNT_USERNAME "Account.username" +#define CONFIG_ACCOUNT_ROUTESET "Account.routeset" +#define CONFIG_ACCOUNT_PASSWORD "Account.password" +#define CONFIG_ACCOUNT_REALM "Account.realm" +#define CONFIG_ACCOUNT_DEFAULT_REALM "*" +#define CONFIG_ACCOUNT_USERAGENT "Account.useragent" + +#define LOCAL_INTERFACE "Account.localInterface" +#define PUBLISHED_SAMEAS_LOCAL "Account.publishedSameAsLocal" +#define LOCAL_PORT "Account.localPort" +#define PUBLISHED_PORT "Account.publishedPort" +#define PUBLISHED_ADDRESS "Account.publishedAddress" /** Maybe to remove **/ -#define ACCOUNT_EXPIRE "Account.expire" -#define ACCOUNT_STATUS "Status" -#define ACCOUNT_EXPIRE_DEFAULT 600 -#define ACCOUNT_ENABLED_TRUE "true" -#define ACCOUNT_ENABLED_FALSE "false" +// #define ACCOUNT_EXPIRE "Account.expire" +// #define ACCOUNT_STATUS "Status" +#define REGISTRATION_EXPIRE_DEFAULT 600 +#define REGISTRATION_ENABLED_TRUE "true" +#define REGISTRATION_ENABLED_FALSE "false" #define ACCOUNT_TYPE_SIP "SIP" #define ACCOUNT_TYPE_IAX "IAX" #define ACCOUNT_TYPES_TAB {QString(ACCOUNT_TYPE_SIP), QString(ACCOUNT_TYPE_IAX)} @@ -250,37 +326,37 @@ #define CONST_PULSEAUDIO 1 /** TLS */ -#define TLS_LISTENER_PORT "TLS.listenerPort" -#define TLS_ENABLE "TLS.enable" -#define TLS_PORT "TLS.port" -#define TLS_CA_LIST_FILE "TLS.certificateListFile" -#define TLS_CERTIFICATE_FILE "TLS.certificateFile" -#define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" -#define TLS_PASSWORD "TLS.password" -#define TLS_METHOD "TLS.method" -#define TLS_CIPHERS "TLS.ciphers" -#define TLS_SERVER_NAME "TLS.serverName" -#define TLS_VERIFY_SERVER "TLS.verifyServer" -#define TLS_VERIFY_CLIENT "TLS.verifyClient" -#define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" -#define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" -#define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" - -#define ACCOUNT_ID "Account.id" -#define ACCOUNT_AUTHENTICATION_USERNAME "authenticationUsername" -#define ACCOUNT_KEY_EXCHANGE "SRTP.keyExchange" -#define ACCOUNT_SRTP_ENABLED "SRTP.enable" -#define ACCOUNT_SRTP_RTP_FALLBACK "SRTP.rtpFallback" -#define ACCOUNT_ZRTP_DISPLAY_SAS "ZRTP.displaySAS" -#define ACCOUNT_ZRTP_NOT_SUPP_WARNING "ZRTP.notSuppWarning" -#define ACCOUNT_ZRTP_HELLO_HASH "ZRTP.helloHashEnable" -#define ACCOUNT_DISPLAY_SAS_ONCE "ZRTP.displaySasOnce" -#define KEY_EXCHANGE_NONE "0" -#define ZRTP "1" -#define SDES "2" +// #define TLS_LISTENER_PORT "TLS.listenerPort" +// #define TLS_ENABLE "TLS.enable" +// #define TLS_PORT "TLS.port" +// #define TLS_CA_LIST_FILE "TLS.certificateListFile" +// #define TLS_CERTIFICATE_FILE "TLS.certificateFile" +// #define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" +// #define TLS_PASSWORD "TLS.password" +// #define TLS_METHOD "TLS.method" +// #define TLS_CIPHERS "TLS.ciphers" +// #define TLS_SERVER_NAME "TLS.serverName" +// #define TLS_VERIFY_SERVER "TLS.verifyServer" +// #define TLS_VERIFY_CLIENT "TLS.verifyClient" +// #define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" +// #define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" +// #define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" + +// #define ACCOUNT_ID "Account.id" +// #define ACCOUNT_AUTHENTICATION_USERNAME "authenticationUsername" +// #define ACCOUNT_KEY_EXCHANGE "SRTP.keyExchange" +// #define ACCOUNT_SRTP_ENABLED "SRTP.enable" +// #define ACCOUNT_SRTP_RTP_FALLBACK "SRTP.rtpFallback" +// #define ACCOUNT_ZRTP_DISPLAY_SAS "ZRTP.displaySAS" +// #define ACCOUNT_ZRTP_NOT_SUPP_WARNING "ZRTP.notSuppWarning" +// #define ACCOUNT_ZRTP_HELLO_HASH "ZRTP.helloHashEnable" +// #define ACCOUNT_DISPLAY_SAS_ONCE "ZRTP.displaySasOnce" +// #define KEY_EXCHANGE_NONE "0" +// #define ZRTP "1" +// #define SDES "2" typedef enum -{ +{ /** Ringing incoming call */ CALL_STATE_INCOMING = 0, /** Ringing outgoing call */ @@ -317,3 +393,17 @@ static const QString empty(""); #define MIME_PLAIN_TEXT "text/plain" #endif +/** HISTORY SERIALIZATION */ +#define ACCOUNT_ID_KEY "accountid" +#define CALLID_KEY "callid" +#define CONFID_KEY "confid" +#define DISPLAY_NAME_KEY "display_name" +#define PEER_NUMBER_KEY "peer_number" +#define RECORDING_PATH_KEY "recordfile" +#define STATE_KEY "state" +#define TIMESTAMP_START_KEY "timestamp_start" +#define TIMESTAMP_STOP_KEY "timestamp_stop" +#define MISSED_STRING "missed" +#define INCOMING_STRING "incoming" +#define OUTGOING_STRING "outgoing" + diff --git a/kde/src/main.cpp b/kde/src/main.cpp index f91419b4ffb3540ee6335b4d9b6c4160bbab439c..340be2b2ce68b12f20827b7fdd5c83e1743c422a 100755 --- a/kde/src/main.cpp +++ b/kde/src/main.cpp @@ -41,7 +41,7 @@ #include "AccountWizard.h" #include "SFLPhoneapplication.h" #include "conf/ConfigurationDialog.h" -#include "conf/ConfigurationSkeleton.h" +#include "klib/ConfigurationSkeleton.h" #include "CallView.h" #include "SFLPhone.h" #include "AccountListModel.h" @@ -52,7 +52,7 @@ static const char description[] = "A KDE 4 Client for SFLphone"; -static const char version[] = "1.0.2"; +static const char version[] = "1.1.0"; int main(int argc, char **argv) { @@ -75,7 +75,6 @@ int main(int argc, char **argv) ); about.addAuthor( ki18n( "Jérémy Quentin" ), KLocalizedString(), "jeremy.quentin@savoirfairelinux.com" ); about.addAuthor( ki18n( "Emmanuel Lepage Vallee" ), KLocalizedString(), "emmanuel.lepage@savoirfairelinux.com" ); - //about.setTranslator( ki18nc("NAME OF TRANSLATORS","Your names"), ki18nc("EMAIL OF TRANSLATORS","Your emails") ); KCmdLineArgs::init(argc, argv, &about); KCmdLineOptions options; KCmdLineArgs::addCmdLineOptions(options); diff --git a/kde/src/ui/SFLPhoneView_base.ui b/kde/src/ui/SFLPhoneView_base.ui index c56489472622fb9aa1d0e28be67e38a9afd14c00..9ad0c749aa5d497d20bc778661d2ba6dea781fe5 100755 --- a/kde/src/ui/SFLPhoneView_base.ui +++ b/kde/src/ui/SFLPhoneView_base.ui @@ -24,6 +24,33 @@ </property> </widget> </item> + <item> + <widget class="QWidget" name="m_pMessageBoxW" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="KLineEdit" name="m_pSendMessageLE"> + <property name="placeholderText"> + <string>Send text message</string> + </property> + <property name="showClearButton" stdset="0"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="m_pSendMessagePB"> + <property name="text"> + <string>Send</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> <item> <widget class="QWidget" name="widget_controls" native="true"> <property name="enabled"> @@ -163,6 +190,11 @@ </layout> </widget> <customwidgets> + <customwidget> + <class>KLineEdit</class> + <extends>QLineEdit</extends> + <header>klineedit.h</header> + </customwidget> <customwidget> <class>Dialpad</class> <extends>QWidget</extends> diff --git a/kde/src/widgets/BookmarkDock.cpp b/kde/src/widgets/BookmarkDock.cpp index 37638d7aae7c8933d2de67e9933359912fc89d43..cd4a08861379376ba81439494d3297058ffe7e84 100644 --- a/kde/src/widgets/BookmarkDock.cpp +++ b/kde/src/widgets/BookmarkDock.cpp @@ -26,6 +26,8 @@ #include <QtGui/QTreeWidgetItem> #include <QtGui/QTreeWidget> #include <QtGui/QSplitter> +#include <QtGui/QCheckBox> +#include <QStandardItemModel> //KDE #include <KLocalizedString> @@ -33,8 +35,12 @@ #include <KLineEdit> //SFLPhone -#include "conf/ConfigurationSkeleton.h" +#include "klib/ConfigurationSkeleton.h" #include "widgets/HistoryTreeItem.h" +#include "SFLPhone.h" +#include "widgets/CategoryDrawer.h" +#include "widgets/CategorizedTreeWidget.h" +#include "klib/AkonadiBackend.h" ///@class QNumericTreeWidgetItem : Tree widget with different sorting criterias class QNumericTreeWidgetItem : public QTreeWidgetItem { @@ -65,13 +71,21 @@ BookmarkDock::BookmarkDock(QWidget* parent) : QDockWidget(parent) m_pFilterLE = new KLineEdit(this); m_pSplitter = new QSplitter(Qt::Vertical,this); - m_pItemView = new QTreeWidget(this); + m_pItemView = new CategorizedTreeWidget(this); + m_pMostUsedCK = new QCheckBox(this); + m_pFilterLE->setPlaceholderText(i18n("Filter")); + + m_pMostUsedCK->setChecked(ConfigurationSkeleton::displayContactCallHistory()); + QWidget* mainWidget = new QWidget(this); setWidget(mainWidget); + m_pMostUsedCK->setText("Show most called contacts"); + QVBoxLayout* mainLayout = new QVBoxLayout(mainWidget); + mainLayout->addWidget(m_pMostUsedCK); mainLayout->addWidget(m_pSplitter); m_pSplitter->addWidget(m_pItemView); mainLayout->addWidget(m_pFilterLE); @@ -82,11 +96,10 @@ BookmarkDock::BookmarkDock(QWidget* parent) : QDockWidget(parent) setWindowTitle(i18n("Bookmark")); m_pItemView->headerItem()->setText(0,i18n("Bookmark") ); - foreach (QString nb, ConfigurationSkeleton::bookmarkList()) { - addBookmark_internal(nb); - } - - connect(m_pFilterLE, SIGNAL(textChanged(QString)), this, SLOT(filter(QString) )); + connect(m_pFilterLE , SIGNAL(textChanged(QString)), this , SLOT(filter(QString) )); + connect(m_pMostUsedCK , SIGNAL(toggled(bool)), this , SLOT(reload() )); + connect(AkonadiBackend::getInstance() , SIGNAL(collectionChanged()) , this , SLOT(reload() )); + reload(); } ///Destructor @@ -106,7 +119,15 @@ BookmarkDock::~BookmarkDock() void BookmarkDock::addBookmark_internal(const QString& phone) { HistoryTreeItem* widget = new HistoryTreeItem(m_pItemView,phone); - QTreeWidgetItem* item = new QTreeWidgetItem(m_pItemView ); + QTreeWidgetItem* item = NULL; + + if (widget->getName() == "Unknow" || widget->getName().isEmpty()) { + item = m_pItemView->addItem<QNumericTreeWidgetItem>("Unknow"); + } + else { + item = m_pItemView->addItem<QNumericTreeWidgetItem>(QString(widget->getName()[0])); + } + widget->setItem(item); m_pItemView->addTopLevelItem(item); m_pItemView->setItemWidget(item,0,widget); @@ -124,8 +145,33 @@ void BookmarkDock::addBookmark(const QString& phone) void BookmarkDock::filter(QString text) { foreach(HistoryTreeItem* item, m_pBookmark) { - bool visible = (item->getName().toLower().indexOf(text) != -1) || (item->getPhoneNumber().toLower().indexOf(text) != -1); - item->getItem()-> setHidden(!visible); + bool visible = (item->getName().toLower().indexOf(text.toLower()) != -1) || (item->getPhoneNumber().toLower().indexOf(text.toLower()) != -1); + item->getItem()->setHidden(!visible); } m_pItemView->expandAll(); +} + +///Show the most popular items +void BookmarkDock::reload() +{ + m_pItemView->clear(); + m_pBookmark.clear(); + m_pItemView->addCategory("Popular"); + for (int i=65;i<=90;i++) { + m_pItemView->addCategory(QString(i)); + } + if (m_pMostUsedCK->isChecked()) { + QStringList cl = SFLPhone::model()->getNumbersByPopularity(); + for (int i=0;i < ((cl.size() < 10)?cl.size():10);i++) { + QNumericTreeWidgetItem* item = m_pItemView->addItem<QNumericTreeWidgetItem>("Popular"); + HistoryTreeItem* widget = new HistoryTreeItem(m_pItemView,cl[i]); + widget->setItem(item); + m_pItemView->setItemWidget(item,0,widget); + m_pBookmark << widget; + } + } + foreach (QString nb, ConfigurationSkeleton::bookmarkList()) { + addBookmark_internal(nb); + } + ConfigurationSkeleton::setDisplayContactCallHistory(m_pMostUsedCK->isChecked()); } \ No newline at end of file diff --git a/kde/src/widgets/BookmarkDock.h b/kde/src/widgets/BookmarkDock.h index f55fc30347bdf81c7db485e5ce9187f3b9ab0aaa..e47dd018a47c3b6f48a1abd1b0d7da655fd6bafd 100644 --- a/kde/src/widgets/BookmarkDock.h +++ b/kde/src/widgets/BookmarkDock.h @@ -25,12 +25,16 @@ //Qt class QTreeWidget; class QSplitter; +class QCheckBox; +class QTreeView; //KDE class KLineEdit; //SFLPhone class HistoryTreeItem; +class CategoryDrawer; +class CategorizedTreeWidget; //Typedef typedef QList<HistoryTreeItem*> BookmarkList; @@ -47,15 +51,18 @@ public: void addBookmark(const QString& phone); private: //Attributes - QTreeWidget* m_pItemView; - KLineEdit* m_pFilterLE; - QSplitter* m_pSplitter; - BookmarkList m_pBookmark; + CategorizedTreeWidget* m_pItemView ; + KLineEdit* m_pFilterLE ; + QSplitter* m_pSplitter ; + BookmarkList m_pBookmark ; + QCheckBox* m_pMostUsedCK; + QTreeView* m_pTest; //Mutators void addBookmark_internal(const QString& phone); private slots: void filter(QString text); + void reload(); }; #endif \ No newline at end of file diff --git a/kde/src/widgets/CallTreeItem.cpp b/kde/src/widgets/CallTreeItem.cpp index 223cacfbdb146861b2da482525243bbc05330d1b..041ddaae881455186e99daea9fbf569b9b095448 100644 --- a/kde/src/widgets/CallTreeItem.cpp +++ b/kde/src/widgets/CallTreeItem.cpp @@ -48,7 +48,7 @@ #include "lib/Call.h" //SFLPhone -#include "AkonadiBackend.h" +#include "klib/AkonadiBackend.h" #include "widgets/TranslucentButtons.h" #include "SFLPhone.h" @@ -173,11 +173,11 @@ void CallTreeItem::setCall(Call *call) ///Update data void CallTreeItem::updated() { - kDebug() << "\n\n\n\nI am here\n\n\n\n\n" << m_pItemCall->getState() << "\n\n\n"; kDebug() << "Updating tree item"; Contact* contact = AkonadiBackend::getInstance()->getContactByPhone(m_pItemCall->getPeerPhoneNumber()); if (contact) { - m_pIconL->setPixmap(*contact->getPhoto()); + if (contact->getPhoto()) + m_pIconL->setPixmap(*contact->getPhoto()); m_pPeerL->setText("<b>"+contact->getFormattedName()+"</b>"); } else { @@ -244,7 +244,7 @@ void CallTreeItem::updated() void CallTreeItem::dragEnterEvent ( QDragEnterEvent *e ) { kDebug() << "Drag enter"; - if (SFLPhone::model()->getIndex(this)->parent() && + if (SFLPhone::model()->getIndex(this) && SFLPhone::model()->getIndex(this)->parent() && SFLPhone::model()->getIndex(e->mimeData()->data( MIME_CALLID))->parent() && SFLPhone::model()->getIndex(this)->parent() == SFLPhone::model()->getIndex(e->mimeData()->data( MIME_CALLID))->parent() && e->mimeData()->data( MIME_CALLID) != SFLPhone::model()->getCall(this)->getCallId()) { @@ -286,7 +286,7 @@ void CallTreeItem::dragLeaveEvent ( QDragLeaveEvent *e ) ///Something is being dropped void CallTreeItem::dropEvent(QDropEvent *e) { - kDebug() << "Drop accepted" << e->pos(); + kDebug() << "Drop accepted"; QTimer::singleShot(500, this, SLOT(hide())); m_isHover = false; if (e->pos().x() < rect().width()/2) { @@ -330,4 +330,4 @@ void CallTreeItem::hide() m_pBtnConf->setVisible(false); m_pBtnTrans->setVisible(false); } -} \ No newline at end of file +} diff --git a/kde/src/widgets/CategorizedTreeWidget.cpp b/kde/src/widgets/CategorizedTreeWidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89377fd57d4b7b9279fbaddcfb03f382c4dedaa8 --- /dev/null +++ b/kde/src/widgets/CategorizedTreeWidget.cpp @@ -0,0 +1,155 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann <dhaumann kde org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "CategorizedTreeWidget.h" + +#include "CategoryDrawer.h" + +#include <QtGui/QStyledItemDelegate> +#include <QtGui/QPainter> +#include <QtGui/QHeaderView> + +#include <klocale.h> +#include <kdebug.h> + +#include <QDebug> +#include <QEvent> +#include <QKeyEvent> + +//BEGIN KateColorTreeDelegate +class KateColorTreeDelegate : public QStyledItemDelegate +{ + public: + KateColorTreeDelegate(CategorizedTreeWidget* widget) + : QStyledItemDelegate(widget) + , m_tree(widget) + { + } + + QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { + QSize sh = QStyledItemDelegate::sizeHint(option, index); + if (!index.parent().isValid()) { + sh.rheight() += 2 * m_categoryDrawer.leftMargin(); + } else { + sh.rheight() += m_categoryDrawer.leftMargin(); + } + if (index.column() == 0) { + sh.rwidth() += m_categoryDrawer.leftMargin(); + } else if (index.column() == 1) { + sh.rwidth() = 150; + } else { + sh.rwidth() += m_categoryDrawer.leftMargin(); + } + + return sh; + } + + QRect fullCategoryRect(const QStyleOptionViewItem& option, const QModelIndex& index) const { + QModelIndex i = index; + if (i.parent().isValid()) { + i = i.parent(); + } + + QTreeWidgetItem* item = m_tree->itemFromIndex(i); + QRect r = m_tree->visualItemRect(item); + + // adapt width + r.setLeft(m_categoryDrawer.leftMargin()); + r.setWidth(m_tree->viewport()->width() - m_categoryDrawer.leftMargin() - m_categoryDrawer.rightMargin()); + + // adapt height + if (item->isExpanded() && item->childCount() > 0) { + const int childCount = item->childCount(); + const int h = sizeHint(option, index.child(0, 0)).height(); + r.setHeight(r.height() + childCount * h); + } + + r.setTop(r.top() + m_categoryDrawer.leftMargin()); + + return r; + } + + virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const + { + Q_ASSERT(index.isValid()); + + //BEGIN: draw toplevel items + if (!index.parent().isValid()) { + QStyleOptionViewItem opt(option); + const QRegion cl = painter->clipRegion(); + painter->setClipRect(opt.rect); + opt.rect = fullCategoryRect(option, index); + m_categoryDrawer.drawCategory(index, 0, opt, painter); + painter->setClipRegion(cl); + return; + } + //END: draw toplevel items + + //BEGIN: draw background of category for all other items + { + QStyleOptionViewItem opt(option); + opt.rect = fullCategoryRect(option, index); + const QRegion cl = painter->clipRegion(); + QRect cr = option.rect; + if (index.column() == 0) { + if (m_tree->layoutDirection() == Qt::LeftToRight) { + cr.setLeft(5); + } else { + cr.setRight(opt.rect.right()); + } + } + painter->setClipRect(cr); + m_categoryDrawer.drawCategory(index, 0, opt, painter); + painter->setClipRegion(cl); + painter->setRenderHint(QPainter::Antialiasing, false); + } + //END: draw background of category for all other items + + painter->setClipRect(option.rect); + } + + private: + CategorizedTreeWidget* m_tree; + CategoryDrawer m_categoryDrawer; +}; +//END KateColorTreeDelegate + +CategorizedTreeWidget::CategorizedTreeWidget(QWidget *parent) + : QTreeWidget(parent) +{ + setItemDelegate(new KateColorTreeDelegate(this)); + setHeaderHidden(true); + setRootIsDecorated(false); + setIndentation(25); + setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + setHorizontalScrollMode(QAbstractItemView::ScrollPerItem); +} + +void CategorizedTreeWidget::drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const +{ + Q_UNUSED(painter) + Q_UNUSED(rect) + Q_UNUSED(index) +// if (index.parent() != QModelIndex() && index.parent().parent() != QModelIndex()) +// QTreeWidget::drawBranches(painter,rect,index); +} + +QVector<QTreeWidgetItem*> CategorizedTreeWidget::realItems() const +{ + return m_lItems; +} \ No newline at end of file diff --git a/kde/src/widgets/CategorizedTreeWidget.h b/kde/src/widgets/CategorizedTreeWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..fad744306d637d98b2a8d4c22996488cf00421d7 --- /dev/null +++ b/kde/src/widgets/CategorizedTreeWidget.h @@ -0,0 +1,84 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann <dhaumann kde org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_COLOR_TREE_WIDGET_H +#define KATE_COLOR_TREE_WIDGET_H + +#include <QtGui/QTreeWidget> + +class KConfigGroup; +class KateColorTreeItem; +class QTreeWidgetItem; + +class CategorizedTreeWidget : public QTreeWidget +{ + Q_OBJECT + friend class KateColorTreeItem; + friend class KateColorTreeDelegate; + + public: + explicit CategorizedTreeWidget(QWidget *parent = 0); + + public: + template <class T = QTreeWidgetItem> T* addItem(QString category); + template <class T = QTreeWidgetItem> T* addCategory(QString name); + + QVector<QTreeWidgetItem*> realItems() const; + + Q_SIGNALS: + void changed(); + + protected: + void drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const; + private: + QVector<QTreeWidgetItem*> m_lItems; +}; + +template <class T> T* CategorizedTreeWidget::addItem(QString category) +{ + QTreeWidgetItem* categoryItem = 0; + for (int i = 0; i < topLevelItemCount(); ++i) { + if (topLevelItem(i)->text(0) == category) { + categoryItem = topLevelItem(i); + break; + } + } + + if (!categoryItem) { + categoryItem =addCategory(category); + } + setItemHidden(categoryItem,false); + + T* iwdg = new T(categoryItem); + resizeColumnToContents(0); + m_lItems << iwdg; + return iwdg; +} + + +template <class T> T* CategorizedTreeWidget::addCategory(QString name) +{ + T* categoryItem = new T(this); + categoryItem->setText(0, name); + addTopLevelItem(categoryItem); + expandItem(categoryItem); + setItemHidden(categoryItem,true); + return categoryItem; +} + +#endif \ No newline at end of file diff --git a/kde/src/widgets/CategoryDrawer.cpp b/kde/src/widgets/CategoryDrawer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5446e06fdc365b404e57a0797a3f8482d761cd72 --- /dev/null +++ b/kde/src/widgets/CategoryDrawer.cpp @@ -0,0 +1,273 @@ +/*************************************************************************** + * Copyright (C) 2009 by Rafael Fernández López <ereslibre@kde.org> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to * + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +// this code is taken from SystemSettings/icons/CategoryDrawer.{h,cpp} +// Rafael agreet to relicense it under LGPLv2 or LGPLv3, just as we need it, +// see: http://lists.kde.org/?l=kwrite-devel&m=133061943317199&w=2 + +#include "CategoryDrawer.h" + +#include <QPainter> +#include <QApplication> +#include <QStyleOption> + +CategoryDrawer::CategoryDrawer() +{ + setLeftMargin( 7 ); + setRightMargin( 7 ); +} + +void CategoryDrawer::drawCategory(const QModelIndex &index, + int sortRole, + const QStyleOption &option, + QPainter *painter) const +{ + Q_UNUSED( sortRole ) + + painter->setRenderHint(QPainter::Antialiasing); + + const QRect optRect = option.rect; + QFont font(QApplication::font()); + font.setBold(true); + const QFontMetrics fontMetrics = QFontMetrics(font); + const int height = categoryHeight(index, option); + const bool leftToRight = painter->layoutDirection() == Qt::LeftToRight; + + //BEGIN: decoration gradient + { + QPainterPath path(optRect.bottomLeft()); + + path.lineTo(QPoint(optRect.topLeft().x(), optRect.topLeft().y() - 3)); + const QPointF topLeft(optRect.topLeft()); + QRectF arc(topLeft, QSizeF(4, 4)); + path.arcTo(arc, 180, -90); + path.lineTo(optRect.topRight()); + path.lineTo(optRect.bottomRight()); + path.lineTo(optRect.bottomLeft()); + + QColor window(option.palette.window().color()); + const QColor base(option.palette.base().color()); + + window.setAlphaF(0.4); + + QLinearGradient decoGradient1; + if (leftToRight) { + decoGradient1.setStart(optRect.topLeft()); + decoGradient1.setFinalStop(optRect.bottomLeft()); + } else { + decoGradient1.setStart(optRect.topRight()); + decoGradient1.setFinalStop(optRect.bottomRight()); + } + decoGradient1.setColorAt(0, window); + decoGradient1.setColorAt(1, Qt::transparent); + + QLinearGradient decoGradient2; + if (leftToRight) { + decoGradient2.setStart(optRect.topLeft()); + decoGradient2.setFinalStop(optRect.topRight()); + } else { + decoGradient2.setStart(optRect.topRight()); + decoGradient2.setFinalStop(optRect.topLeft()); + } + decoGradient2.setColorAt(0, Qt::transparent); + decoGradient2.setColorAt(1, base); + + painter->fillPath(path, decoGradient1); + painter->fillPath(path, decoGradient2); + } + //END: decoration gradient + + { + QRect newOptRect(optRect); + + if (leftToRight) { + newOptRect.translate(1, 1); + } else { + newOptRect.translate(-1, 1); + } + + //BEGIN: inner top left corner + { + painter->save(); + painter->setPen(option.palette.base().color()); + QRectF arc; + if (leftToRight) { + const QPointF topLeft(newOptRect.topLeft()); + arc = QRectF(topLeft, QSizeF(4, 4)); + arc.translate(0.5, 0.5); + painter->drawArc(arc, 1440, 1440); + } else { + QPointF topRight(newOptRect.topRight()); + topRight.rx() -= 4; + arc = QRectF(topRight, QSizeF(4, 4)); + arc.translate(-0.5, 0.5); + painter->drawArc(arc, 0, 1440); + } + painter->restore(); + } + //END: inner top left corner + + //BEGIN: inner left vertical line + { + QPoint start; + QPoint verticalGradBottom; + if (leftToRight) { + start = newOptRect.topLeft(); + verticalGradBottom = newOptRect.topLeft(); + } else { + start = newOptRect.topRight(); + verticalGradBottom = newOptRect.topRight(); + } + start.ry() += 3; + verticalGradBottom.ry() += newOptRect.height() - 3; + QLinearGradient gradient(start, verticalGradBottom); + gradient.setColorAt(0, option.palette.base().color()); + gradient.setColorAt(1, Qt::transparent); + painter->fillRect(QRect(start, QSize(1, newOptRect.height() - 3)), gradient); + } + //END: inner left vertical line + + //BEGIN: inner horizontal line + { + QPoint start; + QPoint horizontalGradTop; + if (leftToRight) { + start = newOptRect.topLeft(); + horizontalGradTop = newOptRect.topLeft(); + start.rx() += 3; + horizontalGradTop.rx() += newOptRect.width() - 3; + } else { + start = newOptRect.topRight(); + horizontalGradTop = newOptRect.topRight(); + start.rx() -= 3; + horizontalGradTop.rx() -= newOptRect.width() - 3; + } + QLinearGradient gradient(start, horizontalGradTop); + gradient.setColorAt(0, option.palette.base().color()); + gradient.setColorAt(1, Qt::transparent); + QSize rectSize; + if (leftToRight) { + rectSize = QSize(newOptRect.width() - 3, 1); + } else { + rectSize = QSize(-newOptRect.width() + 3, 1); + } + painter->fillRect(QRect(start, rectSize), gradient); + } + //END: inner horizontal line + } + + QColor outlineColor = option.palette.text().color(); + outlineColor.setAlphaF(0.35); + + //BEGIN: top left corner + { + painter->save(); + painter->setPen(outlineColor); + QRectF arc; + if (leftToRight) { + const QPointF topLeft(optRect.topLeft()); + arc = QRectF(topLeft, QSizeF(4, 4)); + arc.translate(0.5, 0.5); + painter->drawArc(arc, 1440, 1440); + } else { + QPointF topRight(optRect.topRight()); + topRight.rx() -= 4; + arc = QRectF(topRight, QSizeF(4, 4)); + arc.translate(-0.5, 0.5); + painter->drawArc(arc, 0, 1440); + } + painter->restore(); + } + //END: top left corner + + //BEGIN: left vertical line + { + QPoint start; + QPoint verticalGradBottom; + if (leftToRight) { + start = optRect.topLeft(); + verticalGradBottom = optRect.topLeft(); + } else { + start = optRect.topRight(); + verticalGradBottom = optRect.topRight(); + } + start.ry() += 3; + verticalGradBottom.ry() += optRect.height() - 3; + QLinearGradient gradient(start, verticalGradBottom); + gradient.setColorAt(0, outlineColor); + gradient.setColorAt(1, option.palette.base().color()); + painter->fillRect(QRect(start, QSize(1, optRect.height() - 3)), gradient); + } + //END: left vertical line + + //BEGIN: horizontal line + { + QPoint start; + QPoint horizontalGradTop; + if (leftToRight) { + start = optRect.topLeft(); + horizontalGradTop = optRect.topLeft(); + start.rx() += 3; + horizontalGradTop.rx() += optRect.width() - 3; + } else { + start = optRect.topRight(); + horizontalGradTop = optRect.topRight(); + start.rx() -= 3; + horizontalGradTop.rx() -= optRect.width() - 3; + } + QLinearGradient gradient(start, horizontalGradTop); + gradient.setColorAt(0, outlineColor); + gradient.setColorAt(1, option.palette.base().color()); + QSize rectSize; + if (leftToRight) { + rectSize = QSize(optRect.width() - 3, 1); + } else { + rectSize = QSize(-optRect.width() + 3, 1); + } + painter->fillRect(QRect(start, rectSize), gradient); + } + //END: horizontal line + + //BEGIN: draw text + { + const QString category = index.model()->data(index, Qt::DisplayRole).toString(); // KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); + QRect textRect = QRect(option.rect.topLeft(), QSize(option.rect.width() - 2 - 3 - 3, height)); + textRect.setTop(textRect.top() + 2 + 3 /* corner */); + textRect.setLeft(textRect.left() + 2 + 3 /* corner */ + 3 /* a bit of margin */); + painter->save(); + painter->setFont(font); + QColor penColor(option.palette.text().color()); + penColor.setAlphaF(0.6); + painter->setPen(penColor); + painter->drawText(textRect, Qt::AlignLeft | Qt::AlignTop, category); + painter->restore(); + } + //END: draw text +} + +int CategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &option) const +{ + Q_UNUSED( index ); + Q_UNUSED( option ); + + QFont font(QApplication::font()); + font.setBold(true); + const QFontMetrics fontMetrics = QFontMetrics(font); + + return fontMetrics.height() + 2 + 12 /* vertical spacing */; +} diff --git a/kde/src/widgets/CategoryDrawer.h b/kde/src/widgets/CategoryDrawer.h new file mode 100644 index 0000000000000000000000000000000000000000..c997268b4eedc828abb6f11556cedff7f5a463a5 --- /dev/null +++ b/kde/src/widgets/CategoryDrawer.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2009 by Rafael Fernández López <ereslibre@kde.org> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to * + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +// this code is taken from SystemSettings/icons/CategoryDrawer.{h,cpp} +// Rafael agreet to relicense it under LGPLv2 or LGPLv3, just as we need it, +// see: http://lists.kde.org/?l=kwrite-devel&m=133061943317199&w=2 + +#ifndef CATEGORYDRAWER_H +#define CATEGORYDRAWER_H + +#include <KCategoryDrawer> + +class QPainter; +class QModelIndex; +class QStyleOption; + +class CategoryDrawer : public KCategoryDrawerV2 +{ +public: + CategoryDrawer(); + + virtual void drawCategory(const QModelIndex &index, + int sortRole, + const QStyleOption &option, + QPainter *painter) const; + + virtual int categoryHeight(const QModelIndex &index, const QStyleOption &option) const; +}; + +#endif diff --git a/kde/src/widgets/ContactDock.cpp b/kde/src/widgets/ContactDock.cpp index bce78d16d87806ea612c74639a3bbb800c750067..349be089f88c4354433e7dec2d28ce51404e426d 100644 --- a/kde/src/widgets/ContactDock.cpp +++ b/kde/src/widgets/ContactDock.cpp @@ -23,6 +23,7 @@ //Qt #include <QtCore/QDateTime> +#include <QtCore/QMap> #include <QtGui/QVBoxLayout> #include <QtGui/QListWidget> #include <QtGui/QTreeWidget> @@ -39,15 +40,19 @@ #include <KIcon> //SFLPhone -#include "AkonadiBackend.h" +#include "klib/AkonadiBackend.h" #include "ContactItemWidget.h" #include "SFLPhone.h" -#include "conf/ConfigurationSkeleton.h" +#include "klib/ConfigurationSkeleton.h" +#include "CallView.h" +#include "SFLPhoneView.h" //SFLPhone library #include "lib/Call.h" #include "lib/Contact.h" +#define CURRENT_SORTING_MODE m_pSortByCBB->currentIndex() + ///@class QNumericTreeWidgetItem_hist TreeWidget using different sorting criterias class QNumericTreeWidgetItem_hist : public QTreeWidgetItem { public: @@ -94,9 +99,10 @@ ContactDock::ContactDock(QWidget* parent) : QDockWidget(parent) QStringList sortType; - sortType << "Name" << "Organisation" << "Phone number type" << "Rencently used" << "Group"; + sortType << "Name" << "Organisation" << "Recently used" << "Group" << "Department"; + m_pSortByCBB->addItems(sortType); - m_pSortByCBB->setDisabled(true); + //m_pSortByCBB->setDisabled(true); QWidget* mainWidget = new QWidget(this); setWidget(mainWidget); @@ -109,7 +115,7 @@ ContactDock::ContactDock(QWidget* parent) : QDockWidget(parent) KeyPressEaterC *keyPressEater = new KeyPressEaterC(this); m_pContactView->installEventFilter(keyPressEater); - m_pContactView->setAlternatingRowColors(true); + //m_pContactView->setAlternatingRowColors(true); m_pFilterLE->setPlaceholderText(i18n("Filter")); m_pFilterLE->setClearButtonShown(true); @@ -131,11 +137,20 @@ ContactDock::ContactDock(QWidget* parent) : QDockWidget(parent) m_pSplitter->setChildrenCollapsible(true); m_pSplitter->setStretchFactor(0,7); + QTimer* timer = new QTimer(this); + + m_pSortByCBB->setCurrentIndex(ConfigurationSkeleton::contactSortMode()); + connect (AkonadiBackend::getInstance(),SIGNAL(collectionChanged()), this, SLOT(reloadContact() )); + connect (m_pSortByCBB ,SIGNAL(currentIndexChanged(int)), this, SLOT(reloadContact() )); connect (m_pContactView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),this, SLOT(loadContactHistory(QTreeWidgetItem*) )); connect (m_pFilterLE, SIGNAL(textChanged(QString)), this, SLOT(filter(QString) )); connect (m_pShowHistoCK, SIGNAL(toggled(bool)), this, SLOT(setHistoryVisible(bool) )); + connect (timer ,SIGNAL(timeout()), this, SLOT(reloadHistoryConst() )); + timer->start(1800*1000); //30 minutes setWindowTitle(i18n("Contact")); + + } ///Destructor @@ -155,31 +170,75 @@ ContactDock::~ContactDock() void ContactDock::reloadContact() { ContactList list = AkonadiBackend::getInstance()->update(); + if (!list.size()) + return; + m_pContactView->clear(); + m_Contacts.clear(); + + QHash<Contact*, QDateTime> recentlyUsed; + switch (CURRENT_SORTING_MODE) { + case Recently_used: + recentlyUsed = getContactListByTime(); + foreach (QString cat, m_slHistoryConst) { + m_pContactView->addCategory(cat); + } + break; + } + foreach (Contact* cont, list) { - ContactItemWidget* aContact = new ContactItemWidget(m_pContactView); - QNumericTreeWidgetItem_hist* item = new QNumericTreeWidgetItem_hist(m_pContactView); - item->widget = aContact; - aContact->setItem(item); - aContact->setContact(cont); - - PhoneNumbers numbers = aContact->getContact()->getPhoneNumbers(); - kDebug() << "Phone count" << numbers.count(); - if (numbers.count() > 1) { - foreach (Contact::PhoneNumber* number, numbers) { - QNumericTreeWidgetItem_hist* item2 = new QNumericTreeWidgetItem_hist(item); - QLabel* numberL = new QLabel("<b>"+number->getType()+":</b>"+number->getNumber(),this); - item2->number = number->getNumber(); - m_pContactView->setItemWidget(item2,0,numberL); + if (cont->getPhoneNumbers().count() && usableNumberCount(cont)) { + ContactItemWidget* aContact = new ContactItemWidget(m_pContactView); + QString category; + switch (CURRENT_SORTING_MODE) { + case Name: + category = QString(cont->getFormattedName()[0]); + break; + case Organisation: + category = (cont->getOrganization().isEmpty())?"Unknow":cont->getOrganization(); + break; + case Recently_used: + if (recentlyUsed.find(cont) != recentlyUsed.end()) + category = timeToHistoryCategory(recentlyUsed[cont].date()); + else + category = m_slHistoryConst[Never]; + break; + case Group: + category = "TODO"; + break; + case Department: + category = (cont->getDepartment().isEmpty())?"Unknow":cont->getDepartment();; + break; + } + QNumericTreeWidgetItem_hist* item = m_pContactView->addItem<QNumericTreeWidgetItem_hist>(category); + item->widget = aContact; + aContact->setItem(item); + aContact->setContact(cont); + + PhoneNumbers numbers = aContact->getContact()->getPhoneNumbers(); + if (numbers.count() > 1) { + foreach (Contact::PhoneNumber* number, numbers) { + QNumericTreeWidgetItem_hist* item2 = new QNumericTreeWidgetItem_hist(item); + QLabel* numberL = new QLabel("<b>"+number->getType()+":</b>"+number->getNumber(),this); + item2->number = number->getNumber(); + m_pContactView->setItemWidget(item2,0,numberL); + } + } + else if (numbers.count() == 1) { + item->number = numbers[0]->getNumber(); } - } - else if (numbers.count() == 1) { - item->number = numbers[0]->getNumber(); - } - m_pContactView->addTopLevelItem(item); - m_pContactView->setItemWidget(item,0,aContact); - m_Contacts << aContact; + m_pContactView->setItemWidget(item,0,aContact); + m_Contacts << aContact; + } + } + switch (CURRENT_SORTING_MODE) { + case Recently_used: + break; + default: + m_pContactView->sortItems(0,Qt::AscendingOrder); } + + ConfigurationSkeleton::setContactSortMode(m_pSortByCBB->currentIndex()); } ///Query the call history for all items related to this contact @@ -208,17 +267,26 @@ void ContactDock::filter(const QString& text) foreach(ContactItemWidget* item, m_Contacts) { bool foundNumber = false; foreach (Contact::PhoneNumber* number, item->getContact()->getPhoneNumbers()) { - foundNumber |= number->getNumber().toLower().indexOf(text) != -1; + foundNumber |= number->getNumber().toLower().indexOf(text.toLower()) != -1; } - bool visible = (item->getContact()->getFormattedName().toLower().indexOf(text) != -1) - || (item->getContact()->getOrganization().toLower().indexOf(text) != -1) - || (item->getContact()->getPreferredEmail().toLower().indexOf(text) != -1) + bool visible = (item->getContact()->getFormattedName ().toLower().indexOf(text.toLower()) != -1) + || (item->getContact()->getOrganization ().toLower().indexOf(text.toLower()) != -1) + || (item->getContact()->getPreferredEmail ().toLower().indexOf(text.toLower()) != -1) + || (item->getContact()->getDepartment ().toLower().indexOf(text.toLower()) != -1) || foundNumber; item->getItem()->setHidden(!visible); } - m_pContactView->expandAll(); + //m_pContactView->expandAll(); } +void ContactDock::reloadHistoryConst() +{ + switch (CURRENT_SORTING_MODE) { + case Recently_used: + reloadContact(); + break; + } +} /***************************************************************************** * * @@ -293,9 +361,23 @@ void ContactDock::keyPressEvent(QKeyEvent* event) { int key = event->key(); if(key == Qt::Key_Escape) m_pFilterLE->setText(QString()); - else if(key == Qt::Key_Return || key == Qt::Key_Enter) {} + else if(key == Qt::Key_Return || key == Qt::Key_Enter) { + if (m_pContactView->selectedItems()[0] && m_pContactView->itemWidget(m_pContactView->selectedItems()[0],0)) { + QNumericTreeWidgetItem_hist* item = dynamic_cast<QNumericTreeWidgetItem_hist*>(m_pContactView->selectedItems()[0]); + if (item) { + Call* call = NULL; + SFLPhone::app()->view()->selectCallPhoneNumber(call,item->widget->getContact()); + } + } + } else if((key == Qt::Key_Backspace) && (m_pFilterLE->text().size())) m_pFilterLE->setText(m_pFilterLE->text().left( m_pFilterLE->text().size()-1 )); else if (!event->text().isEmpty() && !(key == Qt::Key_Backspace)) m_pFilterLE->setText(m_pFilterLE->text()+event->text()); -} \ No newline at end of file +} + +/***************************************************************************** + * * + * Helpers * + * * + ****************************************************************************/ diff --git a/kde/src/widgets/ContactDock.h b/kde/src/widgets/ContactDock.h index b19f9c7514f2670e7e6cabe2104b5d0d197dc894..c7318a0b4f6a1d0a986a0d73a5c8ce80019f412d 100644 --- a/kde/src/widgets/ContactDock.h +++ b/kde/src/widgets/ContactDock.h @@ -20,8 +20,12 @@ #ifndef CONTACT_DOCK_H #define CONTACT_DOCK_H +#include <QtCore/QHash> #include <QtGui/QDockWidget> -#include <QtGui/QTreeWidget> +#include "CategorizedTreeWidget.h" +#include "../klib/SortableDockCommon.h" +#include "CallTreeItem.h" +#include <QtGui/QTreeWidgetItem> //Qt class QSplitter; @@ -29,6 +33,8 @@ class QListWidget; class QComboBox; class QTreeWidgetItem; class QCheckBox; +class QStringList; +class DateTime; //KDE class KLineEdit; @@ -49,9 +55,11 @@ namespace KABC { ///SFLPhone class ContactTree; class ContactItemWidget; +class StaticEventHandler; +class Contact; ///@class ContactDock Dock to access contacts -class ContactDock : public QDockWidget +class ContactDock : public QDockWidget, public SortableDockCommon<CallTreeItem*,QTreeWidgetItem*> { Q_OBJECT public: @@ -61,11 +69,11 @@ public: private: //Attributes - KLineEdit* m_pFilterLE; - QSplitter* m_pSplitter; + KLineEdit* m_pFilterLE ; + QSplitter* m_pSplitter ; ContactTree* m_pContactView; - QListWidget* m_pCallView; - QComboBox* m_pSortByCBB; + QListWidget* m_pCallView ; + QComboBox* m_pSortByCBB ; QCheckBox* m_pShowHistoCK; QList<ContactItemWidget*> m_Contacts; @@ -73,17 +81,18 @@ public slots: virtual void keyPressEvent(QKeyEvent* event); private slots: - void reloadContact(); - void loadContactHistory(QTreeWidgetItem* item); - void filter(const QString& text); - void setHistoryVisible(bool visible); + void reloadContact ( ); + void loadContactHistory ( QTreeWidgetItem* item ); + void filter ( const QString& text ); + void setHistoryVisible ( bool visible ); + void reloadHistoryConst ( ); }; ///@class ContactTree tree view with additinal drag and drop -class ContactTree : public QTreeWidget { +class ContactTree : public CategorizedTreeWidget { Q_OBJECT public: - ContactTree(QWidget* parent) : QTreeWidget(parent) {} + ContactTree(QWidget* parent) : CategorizedTreeWidget(parent) {} virtual QMimeData* mimeData( const QList<QTreeWidgetItem *> items) const; bool dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action); }; diff --git a/kde/src/widgets/ContactItemWidget.cpp b/kde/src/widgets/ContactItemWidget.cpp index db15eaa48bca58d0e31186ffb1d15bb4919b2776..b253adfff36ad505dab9ab0e4bb4a234d1d9c16c 100644 --- a/kde/src/widgets/ContactItemWidget.cpp +++ b/kde/src/widgets/ContactItemWidget.cpp @@ -40,7 +40,7 @@ #include <unistd.h> //SFLPhone -#include "AkonadiBackend.h" +#include "klib/AkonadiBackend.h" #include "widgets/BookmarkDock.h" #include "SFLPhone.h" diff --git a/kde/src/widgets/HistoryDock.cpp b/kde/src/widgets/HistoryDock.cpp index 165759f7c68b6bb8e01948b167273a541d06cb83..6dad617dee1c63ec8ac302b95a594a6824dee54a 100644 --- a/kde/src/widgets/HistoryDock.cpp +++ b/kde/src/widgets/HistoryDock.cpp @@ -42,16 +42,19 @@ //SFLPhone #include "SFLPhone.h" #include "widgets/HistoryTreeItem.h" -#include "AkonadiBackend.h" -#include "conf/ConfigurationSkeleton.h" +#include "klib/AkonadiBackend.h" +#include "klib/ConfigurationSkeleton.h" //SFLPhone library #include "lib/sflphone_const.h" + +#define CURRENT_SORTING_MODE m_pSortByCBB->currentIndex() + ///Qt lack official functional sorting algo, so this hack around it class QNumericTreeWidgetItem : public QTreeWidgetItem { public: - QNumericTreeWidgetItem(QTreeWidget* parent):QTreeWidgetItem(parent),widget(0),weight(-1){} + QNumericTreeWidgetItem(QTreeWidget* parent=0):QTreeWidgetItem(parent),widget(0),weight(-1){} QNumericTreeWidgetItem(QTreeWidgetItem* parent):QTreeWidgetItem(parent),widget(0),weight(-1){} HistoryTreeItem* widget; int weight; @@ -109,7 +112,7 @@ HistoryDock::HistoryDock(QWidget* parent) : QDockWidget(parent) m_pItemView->headerItem()->setText(0,i18n("Calls") ); m_pItemView->header ()->setClickable(true ); m_pItemView->header ()->setSortIndicatorShown(true ); - m_pItemView->setAlternatingRowColors(true ); + //m_pItemView->setAlternatingRowColors(true ); m_pItemView->setAcceptDrops( true ); m_pItemView->setDragEnabled( true ); KeyPressEater *keyPressEater = new KeyPressEater(this); @@ -119,7 +122,7 @@ HistoryDock::HistoryDock(QWidget* parent) : QDockWidget(parent) m_pFilterLE->setClearButtonShown(true); QStringList sortBy; - sortBy << "Date" << "Name" << "Popularity" << "Duration"; + sortBy << "Date" << "Name" << "Popularity" << "Length"; m_pSortByCBB->addItems(sortBy); QWidget* mainWidget = new QWidget(this); @@ -143,16 +146,20 @@ HistoryDock::HistoryDock(QWidget* parent) : QDockWidget(parent) QDate date(2000,1,1); m_pFromDW->setDate(date); - reload(); m_CurrentFromDate = m_pFromDW->date(); m_CurrentToDate = m_pToDW->date(); + + m_pSortByCBB->setCurrentIndex(ConfigurationSkeleton::historySortMode()); + + connect(m_pAllTimeCB, SIGNAL(toggled(bool)), this, SLOT(enableDateRange(bool) )); + connect(m_pFilterLE, SIGNAL(textChanged(QString)), this, SLOT(filter(QString) )); + connect(m_pFromDW , SIGNAL(changed(QDate)), this, SLOT(updateLinkedFromDate(QDate) )); + connect(m_pToDW , SIGNAL(changed(QDate)), this, SLOT(updateLinkedToDate(QDate) )); + connect(m_pSortByCBB, SIGNAL(currentIndexChanged(int)), this, SLOT(reload() )); + connect(AkonadiBackend::getInstance(), SIGNAL(collectionChanged()), this, SLOT(updateContactInfo() )); + connect(SFLPhone::model() , SIGNAL(historyChanged()), this, SLOT(reload() )); - connect(m_pAllTimeCB, SIGNAL(toggled(bool)), this, SLOT(enableDateRange(bool) )); - connect(m_pFilterLE, SIGNAL(textChanged(QString)), this, SLOT(filter(QString) )); - connect(m_pFromDW , SIGNAL(changed(QDate)), this, SLOT(updateLinkedFromDate(QDate) )); - connect(m_pToDW , SIGNAL(changed(QDate)), this, SLOT(updateLinkedToDate(QDate) )); - connect(m_pSortByCBB, SIGNAL(currentIndexChanged(int)), this, SLOT(reload() )); - connect(AkonadiBackend::getInstance(), SIGNAL(collectionChanged()), this, SLOT(updateContactInfo() )); + reload(); } ///Destructor @@ -167,15 +174,6 @@ HistoryDock::~HistoryDock() * * ****************************************************************************/ -///Return the identity of the call caller -QString HistoryDock::getIdentity(HistoryTreeItem* item) -{ - if (item->getName().trimmed().isEmpty()) - return item->getPhoneNumber(); - else - return item->getName(); -} - /***************************************************************************** * * @@ -195,12 +193,22 @@ void HistoryDock::updateContactInfo() void HistoryDock::reload() { m_pItemView->clear(); + + QHash<Contact*, QDateTime> recentlyUsed; + switch (CURRENT_SORTING_MODE) { + case Date: + foreach (QString cat, m_slHistoryConst) { + m_pItemView->addCategory(cat); + } + break; + } + foreach(HistoryTreeItem* hitem, m_History) { delete hitem; } m_History.clear(); foreach (Call* call, SFLPhone::app()->model()->getHistory()) { - if (!m_pAllTimeCB->isChecked() || (QDateTime(m_pFromDW->date()).toTime_t() < call->getStartTimeStamp().toUInt() && QDateTime(m_pToDW->date().addDays(1)).toTime_t() > call->getStartTimeStamp().toUInt() )) { + if (call != nullptr && (!m_pAllTimeCB->isChecked() || (QDateTime(m_pFromDW->date()).toTime_t() < call->getStartTimeStamp().toUInt() && QDateTime(m_pToDW->date().addDays(1)).toTime_t() > call->getStartTimeStamp().toUInt() ))) { HistoryTreeItem* callItem = new HistoryTreeItem(m_pItemView); callItem->setCall(call); m_History << callItem; @@ -209,22 +217,23 @@ void HistoryDock::reload() switch (m_pSortByCBB->currentIndex()) { case Date: foreach(HistoryTreeItem* hitem, m_History) { - QNumericTreeWidgetItem* item = new QNumericTreeWidgetItem(m_pItemView); + //QNumericTreeWidgetItem* item = new QNumericTreeWidgetItem(m_pItemView);//m_pItemView->addItem<QNumericTreeWidgetItem>(timeToHistoryCategory(QDateTime::fromTime_t(hitem->call()->getStartTimeStamp().toUInt()).date())); + QNumericTreeWidgetItem* item = m_pItemView->addItem<QNumericTreeWidgetItem>(timeToHistoryCategory(QDateTime::fromTime_t(hitem->call()->getStartTimeStamp().toUInt()).date())); item->widget = hitem; hitem->setItem(item); - m_pItemView->addTopLevelItem(item); + //m_pItemView->addTopLevelItem(item); m_pItemView->setItemWidget(item,0,hitem); } break; - case Name: { + case Name2: { QHash<QString,QTreeWidgetItem*> group; foreach(HistoryTreeItem* item, m_History) { - if (!group[getIdentity(item)]) { - group[getIdentity(item)] = new QTreeWidgetItem(m_pItemView); - group[getIdentity(item)]->setText(0,getIdentity(item)); - m_pItemView->addTopLevelItem(group[getIdentity(item)]); - } - QNumericTreeWidgetItem* twItem = new QNumericTreeWidgetItem(group[getIdentity(item)]); +// if (!group[getIdentity(item)]) { +// group[getIdentity(item)] = new QTreeWidgetItem(m_pItemView); +// group[getIdentity(item)]->setText(0,getIdentity(item)); +// m_pItemView->addTopLevelItem(group[getIdentity(item)]); +// } + QNumericTreeWidgetItem* twItem = m_pItemView->addItem<QNumericTreeWidgetItem>(getIdentity(item->call())); item->setItem(twItem); twItem->widget = item; m_pItemView->setItemWidget(twItem,0,item); @@ -234,31 +243,48 @@ void HistoryDock::reload() case Popularity: { QHash<QString,QNumericTreeWidgetItem*> group; foreach(HistoryTreeItem* item, m_History) { - if (!group[getIdentity(item)]) { - group[getIdentity(item)] = new QNumericTreeWidgetItem(m_pItemView); - group[getIdentity(item)]->weight = 0; - m_pItemView->addTopLevelItem(group[getIdentity(item)]); + if (!group[getIdentity(item->call())]) { + group[getIdentity(item->call())] = m_pItemView->addCategory<QNumericTreeWidgetItem>(getIdentity(item->call())); + group[getIdentity(item->call())]->weight = 0; + m_pItemView->addTopLevelItem(group[getIdentity(item->call())]); } - group[getIdentity(item)]->weight++; - group[getIdentity(item)]->setText(0,getIdentity(item)+" ("+QString::number(group[getIdentity(item)]->weight)+")"); - QNumericTreeWidgetItem* twItem = new QNumericTreeWidgetItem(group[getIdentity(item)]); + group[getIdentity(item->call())]->weight++; + group[getIdentity(item->call())]->setText(0,getIdentity(item->call())+" ("+QString::number(group[getIdentity(item->call())]->weight)+")"); + QNumericTreeWidgetItem* twItem = m_pItemView->addItem<QNumericTreeWidgetItem>(getIdentity(item->call())); item->setItem(twItem); twItem->widget = item; m_pItemView->setItemWidget(twItem,0,item); } break; } - case Duration: + case Length: foreach(HistoryTreeItem* hitem, m_History) { - QNumericTreeWidgetItem* item = new QNumericTreeWidgetItem(m_pItemView); - item->weight = hitem->getDuration(); + QNumericTreeWidgetItem* item = m_pItemView->addItem<QNumericTreeWidgetItem>(" "); + item->weight = hitem->getLength(); hitem->setItem(item); m_pItemView->addTopLevelItem(item); m_pItemView->setItemWidget(item,0,hitem); } break; } - m_pItemView->sortItems(0,Qt::AscendingOrder); + ConfigurationSkeleton::setHistorySortMode(m_pSortByCBB->currentIndex()); + + switch (m_pSortByCBB->currentIndex()) { + case Date: + break; + default: + m_pItemView->sortItems(0,Qt::AscendingOrder); + } + + int maxWidth = 0; + + //Align all durationwidget + foreach(HistoryTreeItem* item, m_History) { + maxWidth = ((uint)item->getDurWidth() > (uint)maxWidth)?item->getDurWidth():maxWidth; + } + foreach(HistoryTreeItem* item, m_History) { + item->setDurWidth(maxWidth); + } } ///Enable the ability to set a date range like 1 month to limit history @@ -378,7 +404,14 @@ void HistoryDock::keyPressEvent(QKeyEvent* event) { int key = event->key(); if(key == Qt::Key_Escape) m_pFilterLE->setText(QString()); - else if(key == Qt::Key_Return || key == Qt::Key_Enter) {} + else if ((key == Qt::Key_Return || key == Qt::Key_Enter) && m_pItemView->selectedItems().size() > 0) { + if (m_pItemView->selectedItems()[0] && m_pItemView->itemWidget(m_pItemView->selectedItems()[0],0)) { + QNumericTreeWidgetItem* item = dynamic_cast<QNumericTreeWidgetItem*>(m_pItemView->selectedItems()[0]); + if (item) { + SFLPhone::model()->addDialingCall(item->widget->getName(), SFLPhone::app()->model()->getCurrentAccountId())->setCallNumber(item->widget->getPhoneNumber()); + } + } + } else if((key == Qt::Key_Backspace) && (m_pFilterLE->text().size())) m_pFilterLE->setText(m_pFilterLE->text().left( m_pFilterLE->text().size()-1 )); else if (!event->text().isEmpty() && !(key == Qt::Key_Backspace)) diff --git a/kde/src/widgets/HistoryDock.h b/kde/src/widgets/HistoryDock.h index e331b476e37c4d1b29673a947afd5633d7972329..51ce18b1ec07b05ff5a84f19b8b00956703db9c2 100644 --- a/kde/src/widgets/HistoryDock.h +++ b/kde/src/widgets/HistoryDock.h @@ -23,6 +23,10 @@ #include <QtGui/QDockWidget> #include <QtGui/QTreeWidget> #include <QtCore/QDate> +#include "../klib/SortableDockCommon.h" +#include "CategorizedTreeWidget.h" +#include "CallTreeItem.h" +#include <QtGui/QTreeWidgetItem> //Qt class QTreeWidgetItem; @@ -46,7 +50,7 @@ class HistoryTree; typedef QList<HistoryTreeItem*> HistoryList; ///@class HistoryDock Dock to see the previous SFLPhone calls -class HistoryDock : public QDockWidget { +class HistoryDock : public QDockWidget, public SortableDockCommon<CallTreeItem*,QTreeWidgetItem*> { Q_OBJECT public: @@ -58,17 +62,6 @@ public: virtual ~HistoryDock(); private: - //Enum - enum SortBy { - Date = 0, - Name = 1, - Popularity = 2, - Duration = 3 - }; - - //Getters - QString getIdentity(HistoryTreeItem* item); - //Attributes HistoryTree* m_pItemView ; KLineEdit* m_pFilterLE ; @@ -101,10 +94,10 @@ private slots: ///@class HistoryTree Simple tree view with additional keybpard filter -class HistoryTree : public QTreeWidget { +class HistoryTree : public CategorizedTreeWidget { Q_OBJECT public: - HistoryTree(QWidget* parent) : QTreeWidget(parent) {} + HistoryTree(QWidget* parent) : CategorizedTreeWidget(parent) {} virtual QMimeData* mimeData( const QList<QTreeWidgetItem *> items) const; bool dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action); }; diff --git a/kde/src/widgets/HistoryTreeItem.cpp b/kde/src/widgets/HistoryTreeItem.cpp index 86d24c424a4310dde988b3dd5a4eaf6528d2b3a8..656b957513ddb499a47ef3dbe46c61a44ba3a77c 100644 --- a/kde/src/widgets/HistoryTreeItem.cpp +++ b/kde/src/widgets/HistoryTreeItem.cpp @@ -22,17 +22,29 @@ #include "HistoryTreeItem.h" //Qt -#include <QtCore/QStringList> #include <QtGui/QGridLayout> #include <QtGui/QMenu> #include <QtGui/QLabel> #include <QtGui/QSpacerItem> +#include <QtGui/QHBoxLayout> +#include <QtGui/QToolButton> +#include <QtGui/QMessageBox> +#include <QtGui/QPainter> +#include <QtGui/QColor> +#include <QtGui/QFontMetrics> +#include <QtCore/QStringList> +#include <QtCore/QFile> +#include <Phonon/MediaObject> +#include <Phonon/BackendCapabilities> +#include <Phonon/AudioOutput> +#include <Phonon/SeekSlider> //KDE #include <KLocale> #include <KDebug> #include <KAction> #include <KIcon> +#include <KMessageBox> //SFLPhone library #include "lib/sflphone_const.h" @@ -40,15 +52,29 @@ #include "lib/Call.h" //SFLPhone -#include "AkonadiBackend.h" +#include "klib/AkonadiBackend.h" #include "SFLPhone.h" #include "widgets/BookmarkDock.h" const char * HistoryTreeItem::callStateIcons[12] = {ICON_INCOMING, ICON_RINGING, ICON_CURRENT, ICON_DIALING, ICON_HOLD, ICON_FAILURE, ICON_BUSY, ICON_TRANSFER, ICON_TRANSF_HOLD, "", "", ICON_CONFERENCE}; +class PlayerWidget : public QWidget { +public: + PlayerWidget(QWidget* parent = 0) : QWidget(parent) {} +protected: + virtual void paintEvent(QPaintEvent* /*event*/) + { + QColor backgroundColor = palette().light().color(); + backgroundColor.setAlpha(200); + QPainter customPainter(this); + customPainter.fillRect(rect(),backgroundColor); + } +}; + + ///Constructor HistoryTreeItem::HistoryTreeItem(QWidget *parent ,QString phone) - : QWidget(parent), m_pItemCall(0),m_pMenu(0) + : QWidget(parent), m_pItemCall(0),m_pMenu(0),m_pAudioSlider(0),m_pTimeLeftL(0),m_pTimePlayedL(0),m_pPlayer(0),m_pContact(0) { setContextMenuPolicy(Qt::CustomContextMenu); @@ -59,7 +85,7 @@ HistoryTreeItem::HistoryTreeItem(QWidget *parent ,QString phone) m_pAddToContact = new KAction(this); m_pBookmark = new KAction(this); - m_pCallAgain->setShortcut ( Qt::CTRL + Qt::Key_Enter ); + m_pCallAgain->setShortcut ( Qt::Key_Enter ); m_pCallAgain->setText ( i18n("Call Again") ); m_pCallAgain->setIcon ( KIcon(ICON_DIALING) ); @@ -86,33 +112,54 @@ HistoryTreeItem::HistoryTreeItem(QWidget *parent ,QString phone) m_pBookmark->setText ( i18n("Bookmark") ); m_pBookmark->setIcon ( KIcon("bookmarks") ); + m_pPlay = new QToolButton(this); + + m_pPlay->setIcon(KIcon("media-playback-start")); + m_pPlay->setMinimumSize(30,30); + m_pPlay->setMaximumSize(30,30); + m_pPlay->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed)); + m_pPlay->setVisible(false); + + m_pRemove = new QToolButton(this); + m_pRemove->setIcon(KIcon("list-remove")); + m_pRemove->setMinimumSize(30,30); + m_pRemove->setMaximumSize(30,30); + m_pRemove->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed)); + m_pRemove->setVisible(false); + connect(m_pCallAgain , SIGNAL(triggered()) , this , SLOT(callAgain() )); connect(m_pAddContact , SIGNAL(triggered()) , this , SLOT(addContact() )); connect(m_pCopy , SIGNAL(triggered()) , this , SLOT(copy() )); connect(m_pEmail , SIGNAL(triggered()) , this , SLOT(sendEmail() )); connect(m_pAddToContact , SIGNAL(triggered()) , this , SLOT(addToContact() )); connect(m_pBookmark , SIGNAL(triggered()) , this , SLOT(bookmark() )); + connect(m_pPlay , SIGNAL(clicked() ) , this , SLOT(showRecordPlayer() )); + connect(m_pRemove , SIGNAL(clicked() ) , this , SLOT(removeRecording() )); connect(this , SIGNAL(customContextMenuRequested(QPoint)) , this , SLOT(showContext(QPoint) )); m_pIconL = new QLabel( this ); m_pPeerNameL = new QLabel( this ); m_pCallNumberL = new QLabel( this ); - m_pDurationL = new QLabel( this ); + m_pLengthL = new QLabel( this ); m_pTimeL = new QLabel( this ); - m_pIconL->setMinimumSize(70,48); - m_pIconL->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + m_pIconL->setMinimumSize(70,0); + m_pIconL->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::MinimumExpanding); QSpacerItem* verticalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); - QGridLayout* mainLayout = new QGridLayout(this); - mainLayout->addWidget ( m_pIconL,0,0,4,1 ); - mainLayout->addWidget ( m_pPeerNameL,0,1 ); - mainLayout->addWidget ( m_pCallNumberL,1,1 ); - mainLayout->addWidget ( m_pTimeL,2,1 ); - mainLayout->addItem ( verticalSpacer,3,1 ); - mainLayout->addWidget ( m_pDurationL,0,2,4,1 ); - setLayout(mainLayout); + m_pMainLayout = new QGridLayout(this); + m_pMainLayout->addWidget ( m_pIconL , 0 , 0 , 4 , 1 ); + m_pMainLayout->addWidget ( m_pPeerNameL , 0 , 1 ); + m_pMainLayout->addWidget ( m_pCallNumberL , 1 , 1 ); + m_pMainLayout->addWidget ( m_pTimeL , 2 , 1 ); + m_pMainLayout->addItem ( verticalSpacer , 4 , 1 ); + m_pMainLayout->addWidget ( m_pPlay , 0 , 2 , 4 , 1 ); + m_pMainLayout->addWidget ( m_pRemove , 0 , 3 , 4 , 1 ); + m_pMainLayout->addWidget ( m_pLengthL , 0 , 4 , 4 , 1 ); + setLayout(m_pMainLayout); setMinimumSize(QSize(50, 30)); + setMaximumSize(QSize(300,99999)); + setSizePolicy(QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum)); if (!phone.isEmpty()) { getContactInfo(phone); @@ -143,7 +190,7 @@ Call* HistoryTreeItem::call() const ///The item have to be updated void HistoryTreeItem::updated() { - if (!getContactInfo(m_pItemCall->getPeerPhoneNumber())) { + if (!getContactInfo(m_pItemCall->getPeerPhoneNumber()),true) { if(! m_pItemCall->getPeerName().trimmed().isEmpty()) { m_pPeerNameL->setText("<b>"+m_pItemCall->getPeerName()+"</b>"); } @@ -228,6 +275,192 @@ void HistoryTreeItem::bookmark() SFLPhone::app()->bookmarkDock()->addBookmark(m_PhoneNumber); } +void HistoryTreeItem::removeRecording() +{ + int ret = KMessageBox::questionYesNo(this, "Are you sure you want to delete this recording?", "Delete recording"); + if (ret == KMessageBox::Yes) { + kDebug() << "Deleting file"; + QFile::remove(m_pItemCall->getRecordingPath()); + } +} + +///Hide or show the media player +void HistoryTreeItem::showRecordPlayer() +{ + if (!m_pAudioSlider) { + m_pPlayer = new PlayerWidget ( this ); + QWidget* r1w = new QWidget ( this ); + QWidget* r2w = new QWidget ( this ); + QVBoxLayout* l = new QVBoxLayout ( m_pPlayer ); + QHBoxLayout* r1= new QHBoxLayout ( r1w ); + QHBoxLayout* r2= new QHBoxLayout ( r2w ); + m_pAudioSlider = new Phonon::SeekSlider ( this ); + m_pTimeLeftL = new QLabel ( "00:00" ); + m_pTimePlayedL = new QLabel ( "00:00" ); + m_pPause = new QToolButton ( ); + m_pStop = new QToolButton ( ); + m_pNote = new QToolButton ( ); + + l->addWidget(r1w); + l->addWidget(r2w); + + m_pPlayer->setAttribute( Qt::WA_TranslucentBackground, true ); + m_pPlayer->setMinimumSize(0,25); + m_pPlayer->setStyleSheet("margin-top:5px"); + + l-> setContentsMargins(0,0,0,0); + r1->setContentsMargins(0,0,0,0); + r2->setContentsMargins(0,0,0,0); + + m_pPause->setIcon ( KIcon( "media-playback-pause" )); + m_pStop->setIcon ( KIcon( "media-playback-stop" )); + m_pNote->setIcon ( KIcon( "view-pim-notes" )); + + m_pPause->setMinimumSize(30,30); + m_pStop->setMinimumSize (30,30); + m_pNote->setMinimumSize (30,30); + QSpacerItem* hSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + + r1->addWidget( m_pTimePlayedL ); + r1->addWidget( m_pAudioSlider ); + r1->addWidget( m_pTimeLeftL ); + r2->addWidget( m_pPause ); + r2->addWidget( m_pStop ); + r2->addItem ( hSpacer ); + r2->addWidget( m_pNote ); + + m_pPlayer->setMinimumSize(width(),height()); + m_pPlayer->setMaximumSize(width(),height()); + + l->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding)); + m_pPlayer->setVisible(true); + + m_pAudioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this); + m_pMediaObject = new Phonon::MediaObject(this); + m_pMetaInformationResolver = new Phonon::MediaObject(this); + Phonon::createPath(m_pMediaObject, m_pAudioOutput); + + m_pAudioSlider->setMediaObject(m_pMediaObject); + + m_pMediaObject->setTickInterval(1000); + + connect( m_pStop , SIGNAL(clicked() ) , this , SLOT( stopPlayer() )); + connect( m_pPause , SIGNAL(clicked() ) , this , SLOT( playPausePlayer() )); + connect( m_pNote , SIGNAL(clicked() ) , this , SLOT( editNote() )); + connect( m_pMediaObject , SIGNAL(tick(qint64) ) , this , SLOT( tick(qint64) )); + + connect(m_pMediaObject , SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this, SLOT(stateChanged(Phonon::State,Phonon::State))); + + } + kDebug() << "Path:" << m_pItemCall->getRecordingPath(); + m_pPlayer->setVisible(true); + Phonon::MediaSource source(m_pItemCall->getRecordingPath()); + m_lSources.append(source); + if (m_lSources.size() > 0) + m_pMetaInformationResolver->setCurrentSource(m_lSources.first()); + m_pMediaObject->play(); + +} + +///Called when the user press the stop button +void HistoryTreeItem::stopPlayer() +{ + m_pPlayer->setVisible(false); + m_pMediaObject->stop(); +} + +///Called then the user press the Play/Pause button +void HistoryTreeItem::playPausePlayer() +{ + if (m_pMediaObject->state() == Phonon::PlayingState) + m_pMediaObject->pause(); + else + m_pMediaObject->play(); +} + +///Add or edit the note associated with this call +void HistoryTreeItem::editNote() +{ + +} + +///Update player labels +void HistoryTreeItem::tick(qint64 time) +{ + QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60); + m_pTimePlayedL->setText(displayTime.toString("mm:ss")); +} + +///Called on player state change +void HistoryTreeItem::stateChanged(Phonon::State newState, Phonon::State /* oldState */) +{ + kDebug() << "Player state changed"; + switch (newState) { + case Phonon::ErrorState: + if (m_pMediaObject->errorType() == Phonon::FatalError) { + QMessageBox::warning(this, tr("Fatal Error"), + m_pMediaObject->errorString()); + } else { + QMessageBox::warning(this, tr("Error"), + m_pMediaObject->errorString()); + } + break; + case Phonon::PlayingState: + m_pPause->setIcon(KIcon("media-playback-pause")); + break; + case Phonon::StoppedState: + m_pPause->setIcon(KIcon("media-playback-play")); + m_pTimePlayedL->setText("00:00"); + break; + case Phonon::PausedState: + m_pPause->setIcon(KIcon("media-playback-play")); + break; + case Phonon::BufferingState: + break; + default: + ; + } +} + +///Reference code for metastate change +void HistoryTreeItem::metaStateChanged(Phonon::State newState, Phonon::State oldState) +{ + Q_UNUSED(oldState); + if (newState == Phonon::ErrorState) { + QMessageBox::warning(this, tr("Error opening files"), + m_pMetaInformationResolver->errorString()); + while (!m_lSources.isEmpty() && + !(m_lSources.takeLast() == m_pMetaInformationResolver->currentSource())) {} /* loop */; + return; + } + + if (newState != Phonon::StoppedState && newState != Phonon::PausedState) + return; + + if (m_pMetaInformationResolver->currentSource().type() == Phonon::MediaSource::Invalid) + return; + + QMap<QString, QString> metaData = m_pMetaInformationResolver->metaData(); + + m_pMediaObject->setCurrentSource(m_pMetaInformationResolver->currentSource()); + + Phonon::MediaSource source = m_pMetaInformationResolver->currentSource(); + int index = m_lSources.indexOf(m_pMetaInformationResolver->currentSource()) + 1; + if (m_lSources.size() > index) { + m_pMetaInformationResolver->setCurrentSource(m_lSources.at(index)); + } +} + +///Resize the player +void HistoryTreeItem::resizeEvent(QResizeEvent* event) +{ + Q_UNUSED(event); + if (m_pPlayer) { + m_pPlayer->setMinimumSize(width(),height()); + m_pPlayer->setMaximumSize(width(),height()); + } +} /***************************************************************************** * * @@ -250,15 +483,18 @@ void HistoryTreeItem::setCall(Call *call) m_pTimeL->setText(QDateTime::fromTime_t(m_pItemCall->getStartTimeStamp().toUInt()).toString()); int dur = m_pItemCall->getStopTimeStamp().toInt() - m_pItemCall->getStartTimeStamp().toInt(); - m_pDurationL->setText(QString("%1").arg(dur/3600,2)+":"+QString("%1").arg((dur%3600)/60,2)+":"+QString("%1").arg((dur%3600)%60,2)+" "); + m_pLengthL->setText(QString("%1").arg(dur/3600,2).trimmed()+":"+QString("%1").arg((dur%3600)/60,2).trimmed()+":"+QString("%1").arg((dur%3600)%60,2).trimmed()+" "); connect(m_pItemCall , SIGNAL(changed()) , this , SLOT(updated() )); updated(); m_TimeStamp = m_pItemCall->getStartTimeStamp().toUInt(); - m_Duration = dur; + m_Length = dur; m_Name = m_pItemCall->getPeerName(); m_PhoneNumber = m_pItemCall->getPeerPhoneNumber(); + + m_pPlay-> setVisible(!m_pItemCall->getRecordingPath().isEmpty() && QFile::exists(m_pItemCall->getRecordingPath())); + m_pRemove->setVisible(!m_pItemCall->getRecordingPath().isEmpty() && QFile::exists(m_pItemCall->getRecordingPath())); } ///Set the index associed with this widget @@ -267,6 +503,12 @@ void HistoryTreeItem::setItem(QTreeWidgetItem* item) m_pItem = item; } +void HistoryTreeItem::setDurWidth(uint width) +{ + m_pLengthL->setMaximumSize(width, 9999 ); + m_pLengthL->setMinimumSize(width, 0 ); +} + /***************************************************************************** * * @@ -277,11 +519,14 @@ void HistoryTreeItem::setItem(QTreeWidgetItem* item) ///Can a contact be associed with this call? bool HistoryTreeItem::getContactInfo(QString phoneNumber) { - Contact* contact = AkonadiBackend::getInstance()->getContactByPhone(phoneNumber); + Contact* contact = AkonadiBackend::getInstance()->getContactByPhone(phoneNumber,true); if (contact) { if (contact->getPhoto() != NULL) m_pIconL->setPixmap(*contact->getPhoto()); + else + m_pIconL->setPixmap(QPixmap(KIcon("user-identity").pixmap(QSize(48,48)))); m_pPeerNameL->setText("<b>"+contact->getFormattedName()+"</b>"); + m_pContact = contact; } else { m_pIconL->setPixmap(QPixmap(KIcon("user-identity").pixmap(QSize(48,48)))); @@ -298,15 +543,21 @@ uint HistoryTreeItem::getTimeStamp() } ///Return the duration -uint HistoryTreeItem::getDuration() +uint HistoryTreeItem::getLength() { - return m_Duration; + return m_Length; } ///Return the caller name QString HistoryTreeItem::getName() { - return m_Name; + if (m_pContact) { + return m_pContact->getFormattedName(); + } + else if (!m_Name.isEmpty()){ + return m_Name; + } + return "Unknow"; } ///Return the caller peer number @@ -319,4 +570,11 @@ QString HistoryTreeItem::getPhoneNumber() QTreeWidgetItem* HistoryTreeItem::getItem() { return m_pItem; -} \ No newline at end of file +} + +///Get the width of the durationWidget +uint HistoryTreeItem::getDurWidth() +{ + QFontMetrics fm(m_pLengthL->font()); + return fm.width(m_pLengthL->text()); +} diff --git a/kde/src/widgets/HistoryTreeItem.h b/kde/src/widgets/HistoryTreeItem.h index 808d394abc5588e40d2612475665f22047f61977..8533ed91fc09b0d48beb8097970551fc2041c073 100644 --- a/kde/src/widgets/HistoryTreeItem.h +++ b/kde/src/widgets/HistoryTreeItem.h @@ -29,14 +29,26 @@ #define HISTORYTREE_ITEM_H #include <QtGui/QWidget> +#include <QtCore/QList> +#include <Phonon/MediaObject> //SFLPhone class Call; +class Contact; //Qt class QTreeWidgetItem; class QMenu; class QLabel; +class QToolButton; +class QGridLayout; + +namespace Phonon{ + class SeekSlider; + class MediaObject; + class AudioOutput; + class MediaSource; +} //KDE class KAction; @@ -53,45 +65,70 @@ class HistoryTreeItem : public QWidget //Getters Call* call () const; uint getTimeStamp (); - uint getDuration (); + uint getLength (); QString getName (); QString getPhoneNumber (); QTreeWidgetItem* getItem (); + uint getDurWidth (); //Setters - void setCall (Call* call); - void setItem (QTreeWidgetItem* item); + void setCall ( Call* call ); + void setItem ( QTreeWidgetItem* item ); + void setDurWidth ( uint width ); //Const static const char * callStateIcons[12]; private: //Attributes - Call* m_pItemCall ; - - QLabel* m_pIconL ; - QLabel* m_pPeerNameL ; - QLabel* m_pCallNumberL ; - QLabel* m_pTimeL ; - QLabel* m_pDurationL ; - - KAction* m_pCallAgain ; - KAction* m_pAddContact ; - KAction* m_pAddToContact ; - KAction* m_pCopy ; - KAction* m_pEmail ; - KAction* m_pBookmark ; - QMenu* m_pMenu ; - - uint m_TimeStamp ; - uint m_Duration ; - QString m_Name ; - QString m_PhoneNumber ; + Call* m_pItemCall ; + + QLabel* m_pIconL ; + QLabel* m_pPeerNameL ; + QLabel* m_pCallNumberL ; + QLabel* m_pTimeL ; + QLabel* m_pLengthL ; + + KAction* m_pCallAgain ; + KAction* m_pAddContact ; + KAction* m_pAddToContact ; + KAction* m_pCopy ; + KAction* m_pEmail ; + KAction* m_pBookmark ; + QMenu* m_pMenu ; + + QToolButton* m_pPlay ; + QToolButton* m_pRemove ; + + uint m_TimeStamp ; + uint m_Length ; + QString m_Name ; + QString m_PhoneNumber ; + QGridLayout* m_pMainLayout ; + Contact* m_pContact; QTreeWidgetItem* m_pItem; + Phonon::MediaObject* m_pMediaObject ; + Phonon::MediaObject* m_pMetaInformationResolver ; + Phonon::AudioOutput* m_pAudioOutput ; + QList<Phonon::MediaSource> m_lSources ; + + //Recorded call player + Phonon::SeekSlider* m_pAudioSlider ; + QLabel* m_pTimeLeftL ; + QLabel* m_pTimePlayedL ; + QToolButton* m_pPause ; + QToolButton* m_pStop ; + QToolButton* m_pNote ; + QWidget* m_pPlayer ; + +protected: + virtual void resizeEvent(QResizeEvent* event); + public slots: void updated(); + bool getContactInfo(QString phone); private slots: void showContext(const QPoint& pos); @@ -101,7 +138,14 @@ private slots: void addContact(); void addToContact(); void bookmark(); - bool getContactInfo(QString phone); + void removeRecording(); + void showRecordPlayer(); + void stopPlayer(); + void playPausePlayer(); + void editNote(); + void metaStateChanged(Phonon::State newState, Phonon::State oldState); + void tick(qint64 time); + void stateChanged(Phonon::State newState, Phonon::State /* oldState */); signals: void over(Call*); diff --git a/plugins/.gitignore b/plugins/.gitignore index 2e55b18e4baa7ea3d7a1e4ecc8480d49679eefc0..ad90355f8e8c80a17399279d88ae038db1ea8f0e 100644 --- a/plugins/.gitignore +++ b/plugins/.gitignore @@ -1,3 +1,5 @@ +m4 +aclocal.m4 .cproject .project .settings/* diff --git a/plugins/addressbook/evolution/eds.h b/plugins/addressbook/evolution/eds.h index 0ce1783831d585eca4bef8bc2422771fe67d39ce..5bbf71e1af469ff4049cb08d9a6f1c72a681d584 100644 --- a/plugins/addressbook/evolution/eds.h +++ b/plugins/addressbook/evolution/eds.h @@ -38,7 +38,7 @@ #ifndef __EDS_H__ #define __EDS_H__ -#include <glib/gtypes.h> +#include <glib.h> #include <gdk-pixbuf/gdk-pixbuf.h> #include <libebook/e-book.h> diff --git a/plugins/configure.ac b/plugins/configure.ac index 413d6be4d060bf9f29ee8853526cfcf73203ae22..5c9157abce7feb4ce046d7537bbd642f26919813 100644 --- a/plugins/configure.ac +++ b/plugins/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([sflphone],[1.0.2],[sflphoneteam@savoirfairelinux.com],[sflphone-plugins]) +AC_INIT([sflphone],[1.1.0],[sflphoneteam@savoirfairelinux.com],[sflphone-plugins]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE diff --git a/tools/asterisk/extensions.conf b/tools/asterisk/extensions.conf new file mode 100644 index 0000000000000000000000000000000000000000..7c92a2d2f166c3fe6f3fe1fbd57418c6c18968b8 --- /dev/null +++ b/tools/asterisk/extensions.conf @@ -0,0 +1,838 @@ +; extensions.conf - the Asterisk dial plan +; +; Static extension configuration file, used by +; the pbx_config module. This is where you configure all your +; inbound and outbound calls in Asterisk. +; +; This configuration file is reloaded +; - With the "dialplan reload" command in the CLI +; - With the "reload" command (that reloads everything) in the CLI + +; +; The "General" category is for certain variables. +; +[general] +; +; If static is set to no, or omitted, then the pbx_config will rewrite +; this file when extensions are modified. Remember that all comments +; made in the file will be lost when that happens. +; +; XXX Not yet implemented XXX +; +static=yes +; +; if static=yes and writeprotect=no, you can save dialplan by +; CLI command "dialplan save" too +; +writeprotect=no +; +; If autofallthrough is set, then if an extension runs out of +; things to do, it will terminate the call with BUSY, CONGESTION +; or HANGUP depending on Asterisk's best guess. This is the default. +; +; If autofallthrough is not set, then if an extension runs out of +; things to do, Asterisk will wait for a new extension to be dialed +; (this is the original behavior of Asterisk 1.0 and earlier). +; +;autofallthrough=no +; +; +; +; If extenpatternmatchnew is set (true, yes, etc), then a new algorithm that uses +; a Trie to find the best matching pattern is used. In dialplans +; with more than about 20-40 extensions in a single context, this +; new algorithm can provide a noticeable speedup. +; With 50 extensions, the speedup is 1.32x +; with 88 extensions, the speedup is 2.23x +; with 138 extensions, the speedup is 3.44x +; with 238 extensions, the speedup is 5.8x +; with 438 extensions, the speedup is 10.4x +; With 1000 extensions, the speedup is ~25x +; with 10,000 extensions, the speedup is 374x +; Basically, the new algorithm provides a flat response +; time, no matter the number of extensions. +; +; By default, the old pattern matcher is used. +; +; ****This is a new feature! ********************* +; The new pattern matcher is for the brave, the bold, and +; the desperate. If you have large dialplans (more than about 50 extensions +; in a context), and/or high call volume, you might consider setting +; this value to "yes" !! +; Please, if you try this out, and are forced to return to the +; old pattern matcher, please report your reasons in a bug report +; on https://issues.asterisk.org. We have made good progress in providing +; something compatible with the old matcher; help us finish the job! +; +; This value can be switched at runtime using the cli command "dialplan set extenpatternmatchnew true" +; or "dialplan set extenpatternmatchnew false", so you can experiment to your hearts content. +; +;extenpatternmatchnew=no +; +; If clearglobalvars is set, global variables will be cleared +; and reparsed on a dialplan reload, or Asterisk reload. +; +; If clearglobalvars is not set, then global variables will persist +; through reloads, and even if deleted from the extensions.conf or +; one of its included files, will remain set to the previous value. +; +; NOTE: A complication sets in, if you put your global variables into +; the AEL file, instead of the extensions.conf file. With clearglobalvars +; set, a "reload" will often leave the globals vars cleared, because it +; is not unusual to have extensions.conf (which will have no globals) +; load after the extensions.ael file (where the global vars are stored). +; So, with "reload" in this particular situation, first the AEL file will +; clear and then set all the global vars, then, later, when the extensions.conf +; file is loaded, the global vars are all cleared, and then not set, because +; they are not stored in the extensions.conf file. +; +clearglobalvars=no +; +; User context is where entries from users.conf are registered. The +; default value is 'default' +; +;userscontext=default +; +; You can include other config files, use the #include command +; (without the ';'). Note that this is different from the "include" command +; that includes contexts within other contexts. The #include command works +; in all asterisk configuration files. +;#include "filename.conf" +;#include <filename.conf> +;#include filename.conf +; +; You can execute a program or script that produces config files, and they +; will be inserted where you insert the #exec command. The #exec command +; works on all asterisk configuration files. However, you will need to +; activate them within asterisk.conf with the "execincludes" option. They +; are otherwise considered a security risk. +;#exec /opt/bin/build-extra-contexts.sh +;#exec /opt/bin/build-extra-contexts.sh --foo="bar" +;#exec </opt/bin/build-extra-contexts.sh --foo="bar"> +;#exec "/opt/bin/build-extra-contexts.sh --foo=\"bar\"" +; + +; The "Globals" category contains global variables that can be referenced +; in the dialplan with the GLOBAL dialplan function: +; ${GLOBAL(VARIABLE)} +; ${${GLOBAL(VARIABLE)}} or ${text${GLOBAL(VARIABLE)}} or any hybrid +; Unix/Linux environmental variables can be reached with the ENV dialplan +; function: ${ENV(VARIABLE)} +; +[globals] +CONSOLE=Console/dsp ; Console interface for demo +;CONSOLE=DAHDI/1 +;CONSOLE=Phone/phone0 +IAXINFO=guest ; IAXtel username/password +;IAXINFO=myuser:mypass +TRUNK=DAHDI/G2 ; Trunk interface +; +; Note the 'G2' in the TRUNK variable above. It specifies which group (defined +; in chan_dahdi.conf) to dial, i.e. group 2, and how to choose a channel to use +; in the specified group. The four possible options are: +; +; g: select the lowest-numbered non-busy DAHDI channel +; (aka. ascending sequential hunt group). +; G: select the highest-numbered non-busy DAHDI channel +; (aka. descending sequential hunt group). +; r: use a round-robin search, starting at the next highest channel than last +; time (aka. ascending rotary hunt group). +; R: use a round-robin search, starting at the next lowest channel than last +; time (aka. descending rotary hunt group). +; +TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0) +;TRUNK=IAX2/user:pass@provider + +;FREENUMDOMAIN=mydomain.com ; domain to send on outbound + ; freenum calls (uses outbound-freenum + ; context) + +; +; WARNING WARNING WARNING WARNING +; If you load any other extension configuration engine, such as pbx_ael.so, +; your global variables may be overridden by that file. Please take care to +; use only one location to set global variables, and you will likely save +; yourself a ton of grief. +; WARNING WARNING WARNING WARNING +; +; Any category other than "General" and "Globals" represent +; extension contexts, which are collections of extensions. +; +; Extension names may be numbers, letters, or combinations +; thereof. If an extension name is prefixed by a '_' +; character, it is interpreted as a pattern rather than a +; literal. In patterns, some characters have special meanings: +; +; X - any digit from 0-9 +; Z - any digit from 1-9 +; N - any digit from 2-9 +; [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9) +; . - wildcard, matches anything remaining (e.g. _9011. matches +; anything starting with 9011 excluding 9011 itself) +; ! - wildcard, causes the matching process to complete as soon as +; it can unambiguously determine that no other matches are possible +; +; For example, the extension _NXXXXXX would match normal 7 digit dialings, +; while _1NXXNXXXXXX would represent an area code plus phone number +; preceded by a one. +; +; Each step of an extension is ordered by priority, which must always start +; with 1 to be considered a valid extension. The priority "next" or "n" means +; the previous priority plus one, regardless of whether the previous priority +; was associated with the current extension or not. The priority "same" or "s" +; means the same as the previously specified priority, again regardless of +; whether the previous entry was for the same extension. Priorities may be +; immediately followed by a plus sign and another integer to add that amount +; (most useful with 's' or 'n'). Priorities may then also have an alias, or +; label, in parentheses after their name which can be used in goto situations. +; +; Contexts contain several lines, one for each step of each extension. One may +; include another context in the current one as well, optionally with a date +; and time. Included contexts are included in the order they are listed. +; Switches may also be included within a context. The order of matching within +; a context is always exact extensions, pattern match extensions, includes, and +; switches. Includes are always processed depth-first. So for example, if you +; would like a switch "A" to match before context "B", simply put switch "A" in +; an included context "C", where "C" is included in your original context +; before "B". +; +;[context] +;exten => someexten,{priority|label{+|-}offset}[(alias)],application(arg1,arg2,...) +; +; Timing list for includes is +; +; <time range>,<days of week>,<days of month>,<months>[,<timezone>] +; +; Note that ranges may be specified to wrap around the ends. Also, minutes are +; fine-grained only down to the closest even minute. +; +;include => daytime,9:00-17:00,mon-fri,*,* +;include => weekend,*,sat-sun,*,* +;include => weeknights,17:02-8:58,mon-fri,*,* +; +; ignorepat can be used to instruct drivers to not cancel dialtone upon receipt +; of a particular pattern. The most commonly used example is of course '9' +; like this: +; +;ignorepat => 9 +; +; so that dialtone remains even after dialing a 9. Please note that ignorepat +; only works with channels which receive dialtone from the PBX, such as DAHDI, +; Phone, and VPB. Other channels, such as SIP and MGCP, which generate their +; own dialtone and converse with the PBX only after a number is complete, are +; generally unaffected by ignorepat (unless DISA or another method is used to +; generate a dialtone after answering the channel). +; + +; +; Sample entries for extensions.conf +; +; +[dundi-e164-canonical] +;include => stdexten +; +; List canonical entries here +; +;exten => 12564286000,1,Gosub(6000,stdexten(IAX2/foo)) +;exten => 12564286000,n,Goto(default,s,1) ; exited Voicemail +;exten => _125642860XX,1,Dial(IAX2/otherbox/${EXTEN:7}) + +[dundi-e164-customers] +; +; If you are an ITSP or Reseller, list your customers here. +; +;exten => _12564286000,1,Dial(SIP/customer1) +;exten => _12564286001,1,Dial(IAX2/customer2) + +[dundi-e164-via-pstn] +; +; If you are freely delivering calls to the PSTN, list them here +; +;exten => _1256428XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Expose all of 256-428 +;exten => _1256325XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Ditto for 256-325 + +[dundi-e164-local] +; +; Context to put your dundi IAX2 or SIP user in for +; full access +; +include => dundi-e164-canonical +include => dundi-e164-customers +include => dundi-e164-via-pstn + +[dundi-e164-switch] +; +; Just a wrapper for the switch +; +switch => DUNDi/e164 + +[dundi-e164-lookup] +; +; Locally to lookup, try looking for a local E.164 solution +; then try DUNDi if we don't have one. +; +include => dundi-e164-local +include => dundi-e164-switch +; +; DUNDi can also be implemented as a Macro instead of using +; the Local channel driver. +; +[macro-dundi-e164] +; +; ARG1 is the extension to Dial +; +; Extension "s" is not a wildcard extension that matches "anything". +; In macros, it is the start extension. In most other cases, +; you have to goto "s" to execute that extension. +; +; For wildcard matches, see above - all pattern matches start with +; an underscore. +exten => s,1,Goto(${ARG1},1) +include => dundi-e164-lookup + +; +; Here are the entries you need to participate in the IAXTEL +; call routing system. Most IAXTEL numbers begin with 1-700, but +; there are exceptions. For more information, and to sign +; up, please go to www.gnophone.com or www.iaxtel.com +; +[iaxtel700] +exten => _91700XXXXXXX,1,Dial(IAX2/${GLOBAL(IAXINFO)}@iaxtel.com/${EXTEN:1}@iaxtel) + +; +; The SWITCH statement permits a server to share the dialplan with +; another server. Use with care: Reciprocal switch statements are not +; allowed (e.g. both A -> B and B -> A), and the switched server needs +; to be on-line or else dialing can be severly delayed. +; +[iaxprovider] +;switch => IAX2/user:[key]@myserver/mycontext + +[trunkint] +; +; International long distance through trunk +; +exten => _9011.,1,Macro(dundi-e164,${EXTEN:4}) +exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})}) + +[trunkld] +; +; Long distance context accessed through trunk +; +exten => _91NXXNXXXXXX,1,Macro(dundi-e164,${EXTEN:1}) +exten => _91NXXNXXXXXX,n,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) + +[trunklocal] +; +; Local seven-digit dialing accessed through trunk interface +; +exten => _9NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) + +[trunktollfree] +; +; Long distance context accessed through trunk interface +; +exten => _91800NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) +exten => _91888NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) +exten => _91877NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) +exten => _91866NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) + +[international] +; +; Master context for international long distance +; +ignorepat => 9 +include => longdistance +include => trunkint + +[longdistance] +; +; Master context for long distance +; +ignorepat => 9 +include => local +include => trunkld + +[local] +; +; Master context for local, toll-free, and iaxtel calls only +; +ignorepat => 9 +include => default +include => trunklocal +include => iaxtel700 +include => trunktollfree +include => iaxprovider + +;Include parkedcalls (or the context you define in features conf) +;to enable call parking. +include => parkedcalls +; +; You can use an alternative switch type as well, to resolve +; extensions that are not known here, for example with remote +; IAX switching you transparently get access to the remote +; Asterisk PBX +; +; switch => IAX2/user:password@bigserver/local +; +; An "lswitch" is like a switch but is literal, in that +; variable substitution is not performed at load time +; but is passed to the switch directly (presumably to +; be substituted in the switch routine itself) +; +; lswitch => Loopback/12${EXTEN}@othercontext +; +; An "eswitch" is like a switch but the evaluation of +; variable substitution is performed at runtime before +; being passed to the switch routine. +; +; eswitch => IAX2/context@${CURSERVER} + +; The following two contexts are a template to enable the ability to dial +; ISN numbers. For more information about what an ISN number is, please see +; http://www.freenum.org. +; +; This is the dialing hook. use: +; include => outbound-freenum + +[outbound-freenum] +; We'll add more digits as needed. The purpose is to dial things +; like extension numbers at domains (ITAD number) so we're matching +; on lengths of 1 through 6 prior to the separator (the asterisk [*]) +; +exten => _X*X!,1,Goto(outbound-freenum2,${EXTEN},1) +exten => _XX*X!,1,Goto(outbound-freenum2,${EXTEN},1) +exten => _XXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) +exten => _XXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) +exten => _XXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) +exten => _XXXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) + +[outbound-freenum2] +; This is the handler which performs the dialing logic. It is called +; from the [outbound-freenum] context +; +exten => _X!,1,Verbose(2,Performing ISN lookup for ${EXTEN}) +same => n,Set(SUFFIX=${CUT(EXTEN,*,2-)}) ; make sure the suffix is all digits as well +same => n,GotoIf($["${FILTER(0-9,${SUFFIX})}" != "${SUFFIX}"]?fn-CONGESTION,1) + ; filter out bad characters per the README-SERIOUSLY.best-practices.txt document +same => n,Set(TIMEOUT(absolute)=10800) +same => n,Set(isnresult=${ENUMLOOKUP(${EXTEN},sip,,1,freenum.org)}) ; perform our lookup with freenum.org +same => n,GotoIf($["${isnresult}" != ""]?from) +same => n,Set(DIALSTATUS=CONGESTION) +same => n,Goto(fn-CONGESTION,1) +same => n(from),Set(__SIPFROMUSER=${CALLERID(num)}) +same => n,GotoIf($["${GLOBAL(FREENUMDOMAIN)}" = ""]?dial) ; check if we set the FREENUMDOMAIN global variable in [global] +same => n,Set(__SIPFROMDOMAIN=${GLOBAL(FREENUMDOMAIN)}) ; if we did set it, then we'll use it for our outbound dialing domain +same => n(dial),Dial(SIP/${isnresult},40) +same => n,Goto(fn-${DIALSTATUS},1) + +exten => fn-BUSY,1,Busy() + +exten => _f[n]-.,1,NoOp(ISN: ${DIALSTATUS}) +same => n,Congestion() + +[macro-trunkdial] +; +; Standard trunk dial macro (hangs up on a dialstatus that should +; terminate call) +; ${ARG1} - What to dial +; +exten => s,1,Dial(${ARG1}) +exten => s,n,Goto(s-${DIALSTATUS},1) +exten => s-NOANSWER,1,Hangup +exten => s-BUSY,1,Hangup +exten => _s-.,1,NoOp + +[stdexten] +; +; Standard extension subroutine: +; ${EXTEN} - Extension +; ${ARG1} - Device(s) to ring +; ${ARG2} - Optional context in Voicemail +; +; Note that the current version will drop through to the next priority in the +; case of their pressing '#'. This gives more flexibility in what do to next: +; you can prompt for a new extension, or drop the call, or send them to a +; general delivery mailbox, or... +; +; The use of the LOCAL() function is purely for convenience. Any variable +; initially declared as LOCAL() will disappear when the innermost Gosub context +; in which it was declared returns. Note also that you can declare a LOCAL() +; variable on top of an existing variable, and its value will revert to its +; previous value (before being declared as LOCAL()) upon Return. +; +exten => _X.,50000(stdexten),NoOp(Start stdexten) +exten => _X.,n,Set(LOCAL(ext)=${EXTEN}) +exten => _X.,n,Set(LOCAL(dev)=${ARG1}) +exten => _X.,n,Set(LOCAL(cntx)=${ARG2}) +exten => _X.,n,Set(LOCAL(mbx)=${ext}${IF($[!${ISNULL(${cntx})}]?@${cntx})}) +exten => _X.,n,Dial(${dev},20) ; Ring the interface, 20 seconds maximum +exten => _X.,n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER) + +exten => stdexten-NOANSWER,1,Voicemail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce +exten => stdexten-NOANSWER,n,Return() ; If they press #, return to start + +exten => stdexten-BUSY,1,Voicemail(${mbx},b) ; If busy, send to voicemail w/ busy announce +exten => stdexten-BUSY,n,Return() ; If they press #, return to start + +exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer + +exten => a,1,VoicemailMain(${mbx}) ; If they press *, send the user into VoicemailMain +exten => a,n,Return() + +[stdPrivacyexten] +; +; Standard extension subroutine: +; ${ARG1} - Extension +; ${ARG2} - Device(s) to ring +; ${ARG3} - Optional DONTCALL context name to jump to (assumes the s,1 extension-priority) +; ${ARG4} - Optional TORTURE context name to jump to (assumes the s,1 extension-priority)` +; ${ARG5} - Context in voicemail (if empty, then "default") +; +; See above note in stdexten about priority handling on exit. +; +exten => _X.,60000(stdPrivacyexten),NoOp(Start stdPrivacyexten) +exten => _X.,n,Set(LOCAL(ext)=${ARG1}) +exten => _X.,n,Set(LOCAL(dev)=${ARG2}) +exten => _X.,n,Set(LOCAL(dontcntx)=${ARG3}) +exten => _X.,n,Set(LOCAL(tortcntx)=${ARG4}) +exten => _X.,n,Set(LOCAL(cntx)=${ARG5}) + +exten => _X.,n,Set(LOCAL(mbx)="${ext}"$["${cntx}" ? "@${cntx}" :: ""]) +exten => _X.,n,Dial(${dev},20,p) ; Ring the interface, 20 seconds maximum, call screening + ; option (or use P for databased call _X.creening) +exten => _X.,n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER) + +exten => stdexten-NOANSWER,1,Voicemail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce +exten => stdexten-NOANSWER,n,NoOp(Finish stdPrivacyexten NOANSWER) +exten => stdexten-NOANSWER,n,Return() ; If they press #, return to start + +exten => stdexten-BUSY,1,Voicemail(${mbx},b) ; If busy, send to voicemail w/ busy announce +exten => stdexten-BUSY,n,NoOp(Finish stdPrivacyexten BUSY) +exten => stdexten-BUSY,n,Return() ; If they press #, return to start + +exten => stdexten-DONTCALL,1,Goto(${dontcntx},s,1) ; Callee chose to send this call to a polite "Don't call again" script. + +exten => stdexten-TORTURE,1,Goto(${tortcntx},s,1) ; Callee chose to send this call to a telemarketer torture script. + +exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer + +exten => a,1,VoicemailMain(${mbx}) ; If they press *, send the user into VoicemailMain +exten => a,n,Return + +[macro-page]; +; +; Paging macro: +; +; Check to see if SIP device is in use and DO NOT PAGE if they are +; +; ${ARG1} - Device to page + +exten => s,1,ChanIsAvail(${ARG1},s) ; s is for ANY call +exten => s,n,GoToIf($[${AVAILSTATUS} = "1"]?autoanswer:fail) +exten => s,n(autoanswer),Set(_ALERT_INFO="RA") ; This is for the PolyComs +exten => s,n,SIPAddHeader(Call-Info: Answer-After=0) ; This is for the Grandstream, Snoms, and Others +exten => s,n,NoOp() ; Add others here and Post on the Wiki!!!! +exten => s,n,Dial(${ARG1}) +exten => s,n(fail),Hangup + + +[demo] +include => stdexten +; +; We start with what to do when a call first comes in. +; +exten => s,1,Wait(1) ; Wait a second, just for fun +exten => s,n,Answer ; Answer the line +exten => s,n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds +exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds +exten => s,n(restart),BackGround(demo-congrats) ; Play a congratulatory message +exten => s,n(instruct),BackGround(demo-instruct) ; Play some instructions +exten => s,n,WaitExten ; Wait for an extension to be dialed. + +exten => 2,1,BackGround(demo-moreinfo) ; Give some more information. +exten => 2,n,Goto(s,instruct) + +exten => 3,1,Set(LANGUAGE()=fr) ; Set language to french +exten => 3,n,Goto(s,restart) ; Start with the congratulations + +exten => 1000,1,Goto(default,s,1) +; +; We also create an example user, 1234, who is on the console and has +; voicemail, etc. +; +exten => 1234,1,Playback(transfer,skip) ; "Please hold while..." + ; (but skip if channel is not up) +exten => 1234,n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)})) +exten => 1234,n,Goto(default,s,1) ; exited Voicemail + +exten => 1235,1,Voicemail(1234,u) ; Right to voicemail + +exten => 1236,1,Dial(Console/dsp) ; Ring forever +exten => 1236,n,Voicemail(1234,b) ; Unless busy + +; +; # for when they're done with the demo +; +exten => #,1,Playback(demo-thanks) ; "Thanks for trying the demo" +exten => #,n,Hangup ; Hang them up. + +; +; A timeout and "invalid extension rule" +; +exten => t,1,Goto(#,1) ; If they take too long, give up +exten => i,1,Playback(invalid) ; "That's not valid, try again" + +; +; Create an extension, 500, for dialing the +; Asterisk demo. +; +exten => 500,1,Playback(demo-abouttotry); Let them know what's going on +exten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default) ; Call the Asterisk demo +exten => 500,n,Playback(demo-nogo) ; Couldn't connect to the demo site +exten => 500,n,Goto(s,6) ; Return to the start over message. + +; +; Create an extension, 600, for evaluating echo latency. +; +exten => 600,1,Playback(demo-echotest) ; Let them know what's going on +exten => 600,n,Echo ; Do the echo test +exten => 600,n,Playback(demo-echodone) ; Let them know it's over +exten => 600,n,Goto(s,6) ; Start over + +; +; You can use the Macro Page to intercom a individual user +exten => 76245,1,Macro(page,SIP/Grandstream1) +; or if your peernames are the same as extensions +exten => _7XXX,1,Macro(page,SIP/${EXTEN}) +; +; +; System Wide Page at extension 7999 +; +exten => 7999,1,Set(TIMEOUT(absolute)=60) +exten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d) + +; Give voicemail at extension 8500 +; +exten => 8500,1,VoicemailMain +exten => 8500,n,Goto(s,6) +; +; Here's what a phone entry would look like (IXJ for example) +; +;exten => 1265,1,Dial(Phone/phone0,15) +;exten => 1265,n,Goto(s,5) + +; +; The page context calls up the page macro that sets variables needed for auto-answer +; It is in is own context to make calling it from the Page() application as simple as +; Local/{peername}@page +; +[page] +exten => _X.,1,Macro(page,SIP/${EXTEN}) + +;[mainmenu] +; +; Example "main menu" context with submenu +; +;exten => s,1,Answer +;exten => s,n,Background(thanks) ; "Thanks for calling press 1 for sales, 2 for support, ..." +;exten => s,n,WaitExten +;exten => 1,1,Goto(submenu,s,1) +;exten => 2,1,Hangup +;include => default +; +;[submenu] +;exten => s,1,Ringing ; Make them comfortable with 2 seconds of ringback +;exten => s,n,Wait,2 +;exten => s,n,Background(submenuopts) ; "Thanks for calling the sales department. Press 1 for steve, 2 for..." +;exten => s,n,WaitExten +;exten => 1,1,Goto(default,steve,1) +;exten => 2,1,Goto(default,mark,2) + +[default] +; +; By default we include the demo. In a production system, you +; probably don't want to have the demo there. +; +include => demo + +exten => 100,1,Dial(SIP/100) +exten => 200,1,Dial(SIP/200) +exten => 300,1,Dial(SIP/300) + +; +; An extension like the one below can be used for FWD, Nikotel, sipgate etc. +; Note that you must have a [sipprovider] section in sip.conf +; +;exten => _41X.,1,Dial(SIP/${FILTER(0-9,${EXTEN:2})}@sipprovider,,r) + +; Real extensions would go here. Generally you want real extensions to be +; 4 or 5 digits long (although there is no such requirement) and start with a +; single digit that is fairly large (like 6 or 7) so that you have plenty of +; room to overlap extensions and menu options without conflict. You can alias +; them with names, too, and use global variables + +;exten => 6245,hint,SIP/Grandstream1&SIP/Xlite1(Joe Schmoe) ; Channel hints for presence +;exten => 6245,1,Dial(SIP/Grandstream1,20,rt) ; permit transfer +;exten => 6245,n(dial),Dial(${HINT},20,rtT) ; Use hint as listed +;exten => 6245,n,Voicemail(6245,u) ; Voicemail (unavailable) +;exten => 6245,s+1,Hangup ; s+1, same as n +;exten => 6245,dial+101,Voicemail(6245,b) ; Voicemail (busy) +;exten => 6361,1,Dial(IAX2/JaneDoe,,rm) ; ring without time limit +;exten => 6389,1,Dial(MGCP/aaln/1@192.168.0.14) +;exten => 6390,1,Dial(JINGLE/caller/callee) ; Dial via jingle using labels +;exten => 6391,1,Dial(JINGLE/asterisk@digium.com/mogorman@astjab.org) ;Dial via jingle using asterisk as the transport and calling mogorman. +;exten => 6394,1,Dial(Local/6275/n) ; this will dial ${MARK} + +;exten => 6275,1,Gosub(${EXTEN},stdexten(${MARK})) + ; assuming ${MARK} is something like DAHDI/2 +;exten => 6275,n,Goto(default,s,1) ; exited Voicemail +;exten => mark,1,Goto(6275,1) ; alias mark to 6275 +;exten => 6536,1,Gosub(${EXTEN},stdexten(${WIL})) + ; Ditto for wil +;exten => 6536,n,Goto(default,s,1) ; exited Voicemail +;exten => wil,1,Goto(6236,1) + +;If you want to subscribe to the status of a parking space, this is +;how you do it. Subscribe to extension 6600 in sip, and you will see +;the status of the first parking lot with this extensions' help +;exten => 6600,hint,park:701@parkedcalls +;exten => 6600,1,noop +; +; Some other handy things are an extension for checking voicemail via +; voicemailmain +; +;exten => 8500,1,VoicemailMain +;exten => 8500,n,Hangup +; +; Or a conference room (you'll need to edit meetme.conf to enable this room) +; +;exten => 8600,1,Meetme(1234) +; +; Or playing an announcement to the called party, as soon it answers +; +;exten = 8700,1,Dial(${MARK},30,A(/path/to/my/announcemsg)) +; + +; example of a compartmentalized company called "acme" +; +; this is the context that your incoming IAX/SIP trunk dumps you in... +;[acme-incoming] +;exten => s,1,Wait(1) +;exten => s,n,Answer() +;exten => s,n(menu),Playback(acme/vm-brief-menu) +;exten => s,n(exten),Background(vm-enter-num-to-call) +;exten => s,n,WaitExten(5) +;exten => s,n(goodbye),Playback(vm-goodbye) +;exten => s,n(end),Hangup() +; +;include => acme-extens +; +;exten => i,1,Playback(vm-invalid) +;exten => i,n,Goto(s,exten) ; optionally, transfer to operator +; +;exten => t,1,Goto(s,goodbye) +; +; this is the context our internal SIP hardphones use (see sip.conf) +; +;[acme-internal] +;exten => s,1,Answer() +;exten => s,n(exten),Background(vm-enter-num-to-call) +;exten => s,n,WaitExten(5) +;exten => s,n(goodbye),Playback(vm-goodbye) +;exten => s,n(end),Hangup() +; +;include => trunkint +;include => trunkld +;include => trunklocal +; +;include => acme-extens +; +; you can test what your system sounds like to outside callers by dialing this +;exten => 777,1,DISA(no-password,acme-incoming) +; +; grouping of acme's extensions... never used directly, always included. +; +;[acme-extens] +;include => stdexten +;exten => 111,1,Gosub(111,stdexten(SIP/pete_1,acme)) +;exten => 111,n,Goto(s,exten) +; +;exten => 112,1,Gosub(112,stdexten(SIP/nancy_1,acme)) +;exten => 112,n,Goto(s,end) +; +; end of acme example + +; +; Time context: you can patch this in via the following. +; +; [acme-internal] +; ... +; exten => 777,1,Gosub(time) +; exten => 777,n,Hangup() +; +; ... +; include => time +; +; Note: if you're geographically spread out, you can have SIP extensions +; specify their own local timezone in sip.conf as: +; +; [boi] +; type=friend +; context=acme-internal +; callerid="Boise Ofc. <2083451111>" +; ... +; ; use system-wide default timezone of MST7MDT +; +; [lws] +; type=friend +; context=acme-internal +; callerid="Lewiston Ofc. <2087431111>" +; ... +; setvar=timezone=PST8PDT +; +; "timezone" isn't a 'reserved' name in any way, and other places where +; the timezone is significant (e.g. calls to "SayUnixTime()", etc) will +; require modification as well. Note that voicemail.conf already has +; a mechanism for timezones. +; + +[time] +exten => _X.,30000(time),NoOp(Time: ${EXTEN} ${timezone}) +exten => _X.,n,Wait(0.25) +exten => _X.,n,Answer() +; the amount of delay is set for English; you may need to adjust this time +; for other languages if there's no pause before the synchronizing beep. +exten => _X.,n,Set(FUTURETIME=$[${EPOCH} + 12]) +exten => _X.,n,SayUnixTime(${FUTURETIME},Zulu,HNS) +exten => _X.,n,SayPhonetic(z) +; use the timezone associated with the extension (sip only), or system-wide +; default if one hasn't been set. +exten => _X.,n,SayUnixTime(${FUTURETIME},${timezone},HNS) +exten => _X.,n,Playback(spy-local) +exten => _X.,n,WaitUntil(${FUTURETIME}) +exten => _X.,n,Playback(beep) +exten => _X.,n,Return() + +; +; ANI context: use in the same way as "time" above +; + +[ani] +exten => _X.,40000(ani),NoOp(ANI: ${EXTEN}) +exten => _X.,n,Wait(0.25) +exten => _X.,n,Answer() +exten => _X.,n,Playback(vm-from) +exten => _X.,n,SayDigits(${CALLERID(ani)}) +exten => _X.,n,Wait(1.25) +exten => _X.,n,SayDigits(${CALLERID(ani)}) ; playback again in case of missed digit +exten => _X.,n,Return() + +; For more information on applications, just type "core show applications" at your +; friendly Asterisk CLI prompt. +; +; "core show application <command>" will show details of how you +; use that particular application in this file, the dial plan. +; "core show functions" will list all dialplan functions +; "core show function <COMMAND>" will show you more information about +; one function. Remember that function names are UPPER CASE. diff --git a/tools/asterisk/keys/500.crt b/tools/asterisk/keys/500.crt new file mode 100644 index 0000000000000000000000000000000000000000..ebb4a7539d913322258112902d58c0838d0fff60 --- /dev/null +++ b/tools/asterisk/keys/500.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDYTCCAUkCAQEwDQYJKoZIhvcNAQEFBQAwQDEcMBoGA1UEAxMTQXN0ZXJpc2sg +UHJpdmF0ZSBDQTEgMB4GA1UEChMXVGVzdCBTYXZvaXItRmFpcmUgTGludXgwHhcN +MTIwNDI3MTMyNzM2WhcNMTMwNDI3MTMyNzM2WjAxMRIwEAYDVQQDEwkxMjcuMC4w +LjExGzAZBgNVBAoTElNhdm9pci1GYWlyZSBMaW51eDCBnzANBgkqhkiG9w0BAQEF +AAOBjQAwgYkCgYEA0Ht4X+Iitm1akm/m7YRKh2uh14xHyTNbpQDDLfIS4qzhzl1Z +n+WflXxoGN2WFUj1lBtI2tbM3rbg702eoj4WzkNQY4ipNjKcdoMmZ9fJT3IYa8GI +XBL8CMjS9aqNBc3yJ8jT8Y4IhDhGiZoUyL7DblsXbGVH6m5xP9uf9dEA7JsCAwEA +ATANBgkqhkiG9w0BAQUFAAOCAgEAl845XKxQTKmqNAE2vRbWNsKWuOUU0biDmNYr +mc/63vPt3yNA+rNaLD3dfkJq+qQfVMfo47eUfcikq5YE6/vazUAWyE6jrWoMIPrL +ylt0lgX6f0b19LyECBlrfJ61BpjGBxmqAbWNmMzxv85e0f98ANWg2JkQgUGrwpW1 +NY1zr8v7m3U+JWQgBb0yhXvlyLmAHGpHvyaU9jKxKXHa2d/69rs+3Y3C82/eCJAM +ZMp0BLKUxXG1EkSBkLs/2Ag3AGPWTUi5a4HT4LlS1zpigFISdUsICNfsfQ9W5Nry +2EYpsPooh6GTeKqFUtWloA6AgARWAMxCMouXsHg1RpITdxFreWB58sQtW9vfKkrd +Qzj3NJPwaa2HkP6XJ8kulaPGboS/CFYFT5brIHBnZQcuy/mdHMTAXgB0mwW1hajy +A7LUFBgRBZNYWLRTQ9Mc4K0QlS4Nc0tgel6KkLhxz8jdigp/qMahC54krz/vG8zJ +a6TOmQelgIxCdRhyaocrsilXrfkY61BOCO6FiBQ3V4LDHMXr3Pz+Gc3J+9MIdxSC +YqLTrZbvrW9uufOPjslK3MPeD1Eughscfj513wMF2tuvfChBJ/nwIJ3etM3Q5i3b +OnoYHipWxGDj0JDOTkqd9GbZmhS34qQWIUMOZ9oNC+rWHOnM5PR2j8eVQOGQAQCt +fXLPgfc= +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/500.csr b/tools/asterisk/keys/500.csr new file mode 100644 index 0000000000000000000000000000000000000000..86a11bf429db7d7b2565420bb9a978a1bad4bbf6 --- /dev/null +++ b/tools/asterisk/keys/500.csr @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBcDCB2gIBADAxMRIwEAYDVQQDEwkxMjcuMC4wLjExGzAZBgNVBAoTElNhdm9p +ci1GYWlyZSBMaW51eDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0Ht4X+Ii +tm1akm/m7YRKh2uh14xHyTNbpQDDLfIS4qzhzl1Zn+WflXxoGN2WFUj1lBtI2tbM +3rbg702eoj4WzkNQY4ipNjKcdoMmZ9fJT3IYa8GIXBL8CMjS9aqNBc3yJ8jT8Y4I +hDhGiZoUyL7DblsXbGVH6m5xP9uf9dEA7JsCAwEAAaAAMA0GCSqGSIb3DQEBBQUA +A4GBAFIQ8XAzHEZ16KCtV0EkePMArJt/xgSZ1Gydw/F/Wxoxevjq5Ft6A9AZYBWJ +aWLO0lJ2eqJikhdXXL75suBhDMcs4CKPJyl/LvDbNds5ua9UixLwQV7sOB4IzpEJ +dfLO1U1/WPc+7LpCwTurP1sXHSrHWKZj0EEygZq+DVQNoGaw +-----END CERTIFICATE REQUEST----- diff --git a/tools/asterisk/keys/500.key b/tools/asterisk/keys/500.key new file mode 100644 index 0000000000000000000000000000000000000000..39dcde1a5608dca46cf6c522920c46678a530fca --- /dev/null +++ b/tools/asterisk/keys/500.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDQe3hf4iK2bVqSb+bthEqHa6HXjEfJM1ulAMMt8hLirOHOXVmf +5Z+VfGgY3ZYVSPWUG0ja1szetuDvTZ6iPhbOQ1BjiKk2Mpx2gyZn18lPchhrwYhc +EvwIyNL1qo0FzfInyNPxjgiEOEaJmhTIvsNuWxdsZUfqbnE/25/10QDsmwIDAQAB +AoGBALZAKYPQgL3vLK0067AY5Loraiiu9hY6MlQ1LWqd4sqLjT5EttOj/XTFc47B +LrFevWgCzhaYjjHntw0bUqDMHEwRWTRP6RGLn4geDnA/LzjSka1fUbAi2hvbPWQF +Uz98Kidpi/Z1LSx0hW3hG+aZIbouRQzx7eEXUBpdwMQuePrZAkEA9FkxnkkgQY8y +6hGLPvOLvzb/s9FnpYpTcXyBPBf9SwfJTuBg4kABIRtXOzdlTqmOcVrG5+hMCC/V +IALDJQrXLQJBANpsc8L3eBig02FJT4R0+oE60UWq+1wufKBgmNGtWFZ5aM3hR8Sp +GvAEWd1O/F1j7sr5rNO0PviZiReIgmxFr+cCQQCHaH5Et0V2z0Jp0DsYMaL53iKp +pZwIcrV3KIX9pVWqpK/8U/+codd+X0Zh/HrZssDLNIERtvubddZnnOBDwNQpAkEA +tTuLidggE/9NpMlZa0RMnnGZNr86NTB1Q/Uil8fHJmkyprEoBWty6HgTwGdLSooi +ltQ3rKlAHrH2aEpiPUhNPQJARWuoMI7fayI1wLOjWXu23rXXP6ObAGpJDuPLM7aB +oGmRYVVe9eMe1SfNuNib1fw5I4GSLLhEe0qzoCZ6jv3L6g== +-----END RSA PRIVATE KEY----- diff --git a/tools/asterisk/keys/500.pem b/tools/asterisk/keys/500.pem new file mode 100644 index 0000000000000000000000000000000000000000..179f66ad74beb47c4da7496a6a8bb272bd4aeb2f --- /dev/null +++ b/tools/asterisk/keys/500.pem @@ -0,0 +1,36 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDQe3hf4iK2bVqSb+bthEqHa6HXjEfJM1ulAMMt8hLirOHOXVmf +5Z+VfGgY3ZYVSPWUG0ja1szetuDvTZ6iPhbOQ1BjiKk2Mpx2gyZn18lPchhrwYhc +EvwIyNL1qo0FzfInyNPxjgiEOEaJmhTIvsNuWxdsZUfqbnE/25/10QDsmwIDAQAB +AoGBALZAKYPQgL3vLK0067AY5Loraiiu9hY6MlQ1LWqd4sqLjT5EttOj/XTFc47B +LrFevWgCzhaYjjHntw0bUqDMHEwRWTRP6RGLn4geDnA/LzjSka1fUbAi2hvbPWQF +Uz98Kidpi/Z1LSx0hW3hG+aZIbouRQzx7eEXUBpdwMQuePrZAkEA9FkxnkkgQY8y +6hGLPvOLvzb/s9FnpYpTcXyBPBf9SwfJTuBg4kABIRtXOzdlTqmOcVrG5+hMCC/V +IALDJQrXLQJBANpsc8L3eBig02FJT4R0+oE60UWq+1wufKBgmNGtWFZ5aM3hR8Sp +GvAEWd1O/F1j7sr5rNO0PviZiReIgmxFr+cCQQCHaH5Et0V2z0Jp0DsYMaL53iKp +pZwIcrV3KIX9pVWqpK/8U/+codd+X0Zh/HrZssDLNIERtvubddZnnOBDwNQpAkEA +tTuLidggE/9NpMlZa0RMnnGZNr86NTB1Q/Uil8fHJmkyprEoBWty6HgTwGdLSooi +ltQ3rKlAHrH2aEpiPUhNPQJARWuoMI7fayI1wLOjWXu23rXXP6ObAGpJDuPLM7aB +oGmRYVVe9eMe1SfNuNib1fw5I4GSLLhEe0qzoCZ6jv3L6g== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDYTCCAUkCAQEwDQYJKoZIhvcNAQEFBQAwQDEcMBoGA1UEAxMTQXN0ZXJpc2sg +UHJpdmF0ZSBDQTEgMB4GA1UEChMXVGVzdCBTYXZvaXItRmFpcmUgTGludXgwHhcN +MTIwNDI3MTMyNzM2WhcNMTMwNDI3MTMyNzM2WjAxMRIwEAYDVQQDEwkxMjcuMC4w +LjExGzAZBgNVBAoTElNhdm9pci1GYWlyZSBMaW51eDCBnzANBgkqhkiG9w0BAQEF +AAOBjQAwgYkCgYEA0Ht4X+Iitm1akm/m7YRKh2uh14xHyTNbpQDDLfIS4qzhzl1Z +n+WflXxoGN2WFUj1lBtI2tbM3rbg702eoj4WzkNQY4ipNjKcdoMmZ9fJT3IYa8GI +XBL8CMjS9aqNBc3yJ8jT8Y4IhDhGiZoUyL7DblsXbGVH6m5xP9uf9dEA7JsCAwEA +ATANBgkqhkiG9w0BAQUFAAOCAgEAl845XKxQTKmqNAE2vRbWNsKWuOUU0biDmNYr +mc/63vPt3yNA+rNaLD3dfkJq+qQfVMfo47eUfcikq5YE6/vazUAWyE6jrWoMIPrL +ylt0lgX6f0b19LyECBlrfJ61BpjGBxmqAbWNmMzxv85e0f98ANWg2JkQgUGrwpW1 +NY1zr8v7m3U+JWQgBb0yhXvlyLmAHGpHvyaU9jKxKXHa2d/69rs+3Y3C82/eCJAM +ZMp0BLKUxXG1EkSBkLs/2Ag3AGPWTUi5a4HT4LlS1zpigFISdUsICNfsfQ9W5Nry +2EYpsPooh6GTeKqFUtWloA6AgARWAMxCMouXsHg1RpITdxFreWB58sQtW9vfKkrd +Qzj3NJPwaa2HkP6XJ8kulaPGboS/CFYFT5brIHBnZQcuy/mdHMTAXgB0mwW1hajy +A7LUFBgRBZNYWLRTQ9Mc4K0QlS4Nc0tgel6KkLhxz8jdigp/qMahC54krz/vG8zJ +a6TOmQelgIxCdRhyaocrsilXrfkY61BOCO6FiBQ3V4LDHMXr3Pz+Gc3J+9MIdxSC +YqLTrZbvrW9uufOPjslK3MPeD1Eughscfj513wMF2tuvfChBJ/nwIJ3etM3Q5i3b +OnoYHipWxGDj0JDOTkqd9GbZmhS34qQWIUMOZ9oNC+rWHOnM5PR2j8eVQOGQAQCt +fXLPgfc= +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/600.crt b/tools/asterisk/keys/600.crt new file mode 100644 index 0000000000000000000000000000000000000000..32e6b9c9378f164cc771a52df0ecf07465265267 --- /dev/null +++ b/tools/asterisk/keys/600.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDZjCCAU4CAQEwDQYJKoZIhvcNAQEFBQAwQDEcMBoGA1UEAxMTQXN0ZXJpc2sg +UHJpdmF0ZSBDQTEgMB4GA1UEChMXVGVzdCBTYXZvaXItRmFpcmUgTGludXgwHhcN +MTIwNDI3MTMzMDI2WhcNMTMwNDI3MTMzMDI2WjA2MRcwFQYDVQQDEw4xOTIuMTY4 +LjUwLjE3MjEbMBkGA1UEChMSU2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQDQsm0AjqfDmwoCGcGNz4jgU54/yz4pWip1A2OlHUYX +XOxKoFJQPjMSRUVuVw0ZpdL3phw4GyL7CNtAbALRg6qKLj6Sf5ZCn8sFnmsVrW+v +Md0sYnf+b/u8KQyJdpuga9vKWn31e6P3RsdGVZBhSkx28V7/5iFF6TpZDhM+Ql3N +FQIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQBnCugdLIWsZrHtv3jEC1D3RVume58O +z98q3OVap3ZxfSo5V9I1iU5W6t4wz/YP7QmGFbThFkE4Sj4CQGmKJMh9oEwBqzuY +wuPjfgymrBk7yKy0XCkVDZ+q4yidPd1tS8WMQlklnb0TR4bNB07C2QAQoKb50fLm +K5GycOfNb5sjAl790ugM5z7QW912XCHkF1/ymTcCso+rK8vAaO9tkpk6l22igIEE +Pq1W/OLkm5u+u2HSISxdozXj4keK/0kuvzVnTuvqtwftESJaA4mfehE6Z5dW/AlU +dLyZnZIUEQmLN2zET2E5rABNLAeRCKCyPITmj8/v9yr10MDI3I/BZXM3BI4QgqoS +JOhNFCeRFtyy/bzBAh7o6tq9YEohvVztjFwCZWthDiPPKxTO6HnTlUFDbG3Gv9Wb +BP/f/v52Tm7LvY4jHo5LFILaF/HXHRrryCkdw3wjjtpAkl5zGh+E0C4yeqmdjsP9 +bH9a9mAa1N3LgtL52cxadfCacoH3oI+FwymOdnf6+tyv+D6BZWtX5t4WINVkdGuD +RzUZi08VH9Vd3d0qjzO7Vve028w/cM3QE+si4SVHHfV08a4zIGOTP5edJYJ58QWC +jWajYyTw1mhCzSEFofxw29aDO5cXw1lKmjCjoVi+Ae3tKUyhPTK1+9e0MAsR+cLG +OKKct2tGWeuGHA== +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/600.csr b/tools/asterisk/keys/600.csr new file mode 100644 index 0000000000000000000000000000000000000000..47395498bcbd81163324ab4195b9c1c735d8aa0b --- /dev/null +++ b/tools/asterisk/keys/600.csr @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBdTCB3wIBADA2MRcwFQYDVQQDEw4xOTIuMTY4LjUwLjE3MjEbMBkGA1UEChMS +U2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ +sm0AjqfDmwoCGcGNz4jgU54/yz4pWip1A2OlHUYXXOxKoFJQPjMSRUVuVw0ZpdL3 +phw4GyL7CNtAbALRg6qKLj6Sf5ZCn8sFnmsVrW+vMd0sYnf+b/u8KQyJdpuga9vK +Wn31e6P3RsdGVZBhSkx28V7/5iFF6TpZDhM+Ql3NFQIDAQABoAAwDQYJKoZIhvcN +AQEFBQADgYEAForeBGuC/JjnLQ7/aafWGZZJWkGqqTtkO8ksuMfm09Hy0viyMzJr +DXcCE8lGNukB8NXWkl7khLnuxNHCsbFsbpzI9dx1b6GiKI+95U+Nu9HvHh4o7Vmv +7O4kt75M/HtM15nXbKEGiYmRLcJKWkenQUEasVMfp/giZx7hjaQO10I= +-----END CERTIFICATE REQUEST----- diff --git a/tools/asterisk/keys/600.key b/tools/asterisk/keys/600.key new file mode 100644 index 0000000000000000000000000000000000000000..50c29340161eb08a1bd87928e69c5d8f8d8001bc --- /dev/null +++ b/tools/asterisk/keys/600.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDQsm0AjqfDmwoCGcGNz4jgU54/yz4pWip1A2OlHUYXXOxKoFJQ +PjMSRUVuVw0ZpdL3phw4GyL7CNtAbALRg6qKLj6Sf5ZCn8sFnmsVrW+vMd0sYnf+ +b/u8KQyJdpuga9vKWn31e6P3RsdGVZBhSkx28V7/5iFF6TpZDhM+Ql3NFQIDAQAB +AoGAIJOZfDrIaTosR8OpeO9qWEn1K9QX8fCHLBjJVx7IsCDrKYL5Fll/M1zox56D +BvvhgJLHWOKzhSgOwXGaxwWcewkrhy4UbQ7+8wm/LdgT8nKU7OyU+oKAz/6+bFX3 +M9aA8cKOwDQCrZvKCHDPJzab71HAe8uWA54T798S3HyFOgkCQQDsFiST3XH6ortD +YLQIwIl+LUCeb9UpksjitYvtjA+CANPpjdpPASNpTNVoS7adecfU01cC6spw/1EF +7izTkm23AkEA4kzbL/LLDdwD3pBFvA/tu+kwcfRDtryRymiHz4qKg7xtHphAV3Sx +K2nRs0WRJ/br1CE3kz1PEvFcVsDUyf2bkwJBALqFnAx+zohYfV70TgkEJRzdH8qN +THp2D+Sdzpm1KKNriAFkI3B708BkBc9K0lKEXo8VEg+p9Jtl/FuVGzFk5O0CQA6k +Cko/2wM6iMWNb/WK0kal/4xf0UGxUX1W5fJ3dB6xwh2InCEMW6oDXp3KkmmTgA5p +V78e6E7BbsfuEdY/oiECQBlR/WfYeoZpHueRwx8M3jICOR5WBjmu7c+rLjaEvGCB +kXhsM8UrMHncz1fNHDLgLcPneiw+tReeuKVHBSDYwBg= +-----END RSA PRIVATE KEY----- diff --git a/tools/asterisk/keys/600.pem b/tools/asterisk/keys/600.pem new file mode 100644 index 0000000000000000000000000000000000000000..b2d4d0cc32a0d1b10e2813e429f67d15410a9f40 --- /dev/null +++ b/tools/asterisk/keys/600.pem @@ -0,0 +1,36 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDQsm0AjqfDmwoCGcGNz4jgU54/yz4pWip1A2OlHUYXXOxKoFJQ +PjMSRUVuVw0ZpdL3phw4GyL7CNtAbALRg6qKLj6Sf5ZCn8sFnmsVrW+vMd0sYnf+ +b/u8KQyJdpuga9vKWn31e6P3RsdGVZBhSkx28V7/5iFF6TpZDhM+Ql3NFQIDAQAB +AoGAIJOZfDrIaTosR8OpeO9qWEn1K9QX8fCHLBjJVx7IsCDrKYL5Fll/M1zox56D +BvvhgJLHWOKzhSgOwXGaxwWcewkrhy4UbQ7+8wm/LdgT8nKU7OyU+oKAz/6+bFX3 +M9aA8cKOwDQCrZvKCHDPJzab71HAe8uWA54T798S3HyFOgkCQQDsFiST3XH6ortD +YLQIwIl+LUCeb9UpksjitYvtjA+CANPpjdpPASNpTNVoS7adecfU01cC6spw/1EF +7izTkm23AkEA4kzbL/LLDdwD3pBFvA/tu+kwcfRDtryRymiHz4qKg7xtHphAV3Sx +K2nRs0WRJ/br1CE3kz1PEvFcVsDUyf2bkwJBALqFnAx+zohYfV70TgkEJRzdH8qN +THp2D+Sdzpm1KKNriAFkI3B708BkBc9K0lKEXo8VEg+p9Jtl/FuVGzFk5O0CQA6k +Cko/2wM6iMWNb/WK0kal/4xf0UGxUX1W5fJ3dB6xwh2InCEMW6oDXp3KkmmTgA5p +V78e6E7BbsfuEdY/oiECQBlR/WfYeoZpHueRwx8M3jICOR5WBjmu7c+rLjaEvGCB +kXhsM8UrMHncz1fNHDLgLcPneiw+tReeuKVHBSDYwBg= +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDZjCCAU4CAQEwDQYJKoZIhvcNAQEFBQAwQDEcMBoGA1UEAxMTQXN0ZXJpc2sg +UHJpdmF0ZSBDQTEgMB4GA1UEChMXVGVzdCBTYXZvaXItRmFpcmUgTGludXgwHhcN +MTIwNDI3MTMzMDI2WhcNMTMwNDI3MTMzMDI2WjA2MRcwFQYDVQQDEw4xOTIuMTY4 +LjUwLjE3MjEbMBkGA1UEChMSU2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQDQsm0AjqfDmwoCGcGNz4jgU54/yz4pWip1A2OlHUYX +XOxKoFJQPjMSRUVuVw0ZpdL3phw4GyL7CNtAbALRg6qKLj6Sf5ZCn8sFnmsVrW+v +Md0sYnf+b/u8KQyJdpuga9vKWn31e6P3RsdGVZBhSkx28V7/5iFF6TpZDhM+Ql3N +FQIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQBnCugdLIWsZrHtv3jEC1D3RVume58O +z98q3OVap3ZxfSo5V9I1iU5W6t4wz/YP7QmGFbThFkE4Sj4CQGmKJMh9oEwBqzuY +wuPjfgymrBk7yKy0XCkVDZ+q4yidPd1tS8WMQlklnb0TR4bNB07C2QAQoKb50fLm +K5GycOfNb5sjAl790ugM5z7QW912XCHkF1/ymTcCso+rK8vAaO9tkpk6l22igIEE +Pq1W/OLkm5u+u2HSISxdozXj4keK/0kuvzVnTuvqtwftESJaA4mfehE6Z5dW/AlU +dLyZnZIUEQmLN2zET2E5rABNLAeRCKCyPITmj8/v9yr10MDI3I/BZXM3BI4QgqoS +JOhNFCeRFtyy/bzBAh7o6tq9YEohvVztjFwCZWthDiPPKxTO6HnTlUFDbG3Gv9Wb +BP/f/v52Tm7LvY4jHo5LFILaF/HXHRrryCkdw3wjjtpAkl5zGh+E0C4yeqmdjsP9 +bH9a9mAa1N3LgtL52cxadfCacoH3oI+FwymOdnf6+tyv+D6BZWtX5t4WINVkdGuD +RzUZi08VH9Vd3d0qjzO7Vve028w/cM3QE+si4SVHHfV08a4zIGOTP5edJYJ58QWC +jWajYyTw1mhCzSEFofxw29aDO5cXw1lKmjCjoVi+Ae3tKUyhPTK1+9e0MAsR+cLG +OKKct2tGWeuGHA== +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/asterisk.crt b/tools/asterisk/keys/asterisk.crt new file mode 100644 index 0000000000000000000000000000000000000000..088853a120ae05be43adcb5bed59341347dd2cca --- /dev/null +++ b/tools/asterisk/keys/asterisk.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDZjCCAU4CAQEwDQYJKoZIhvcNAQEFBQAwQDEcMBoGA1UEAxMTQXN0ZXJpc2sg +UHJpdmF0ZSBDQTEgMB4GA1UEChMXVGVzdCBTYXZvaXItRmFpcmUgTGludXgwHhcN +MTIwNDE2MjEwNzU3WhcNMTMwNDE2MjEwNzU3WjA2MRIwEAYDVQQDEwkxMjcuMC4w +LjExIDAeBgNVBAoTF1Rlc3QgU2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQCdxgF7K/c/esDIl4NEqlOPghD1UNDejt0miKrkCGmn +xnWauKY45me+LfRmHqsmFz8F2657/B0Xh1cLD46jYC7vwRrFC7vkkxXaf7/EjLJj +qNFUl0yjKrBSZOii3goxeekdDFv7MNqZn2dxaJL18jEtbXUBrFBZ5sVN2ftmWqU2 +QwIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCGBJTTqtPXDZmqdjp1tt+LiC9Jc4fs +6ounWAiHKgyboVGCk8ouDeNhbHnAqxkjAFzFPiuhuiYnKHQcOZ71YHHbMO8Mo8xV +BvT1KGlDSg/BfRkLMzFea3kIomSXUxPPqHx+EVD7HpsZVQ+4LNwAdg+C3S/9JaNE +7KWY4dXuaIsS51uiNhxwSKuD7Mqp25FH/cIVl6D9m+4l6RHRDSleISv/PKEh4400 +hM4dUe4K7fCziTI0DDDz1WMGrlGg9pq2PGqqMaNg7tog7wyEq5VDZc0CYggEfMO8 +3BK6FLrVOAf6FHOHlzhX/YpFhouaJtIQ+Ke8/X4j8O48nhJN+qvUovEvGRBYF1JC +NSsH26dAYvFMzwLxc9QIEn/35ygOpH7FV3eTIryZ4qgulQznKtUF8jsnhkQR8S1N +vTKCr2JkevxU1c24mmBvd+NUYU9JL9BAoAPyCcSzvQf3imnJ3nMhRAG9c0C/7JAI +IzmRVYBvoeTCYJdEctQX/Y0SaDque2JJVWhGkeeneJirh1LGwH5yEstFp7Rvus+t +MERVZOupPx9NRc6STfd3TLtNqPuhU5AoLknxtvpyBeWCiwCL1+/NNSAXdUDO0MrF +UFfAOdKWORTL8p0ZrVcy7N3UwK+P2bkjhrz+3PWh2airczYIycEXeDvmT20/6X/A +1jHWfYG7WWPECA== +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/asterisk.csr b/tools/asterisk/keys/asterisk.csr new file mode 100644 index 0000000000000000000000000000000000000000..8d6f41a562210502aa66b5ebe97d7395b60ff26e --- /dev/null +++ b/tools/asterisk/keys/asterisk.csr @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBdTCB3wIBADA2MRIwEAYDVQQDEwkxMjcuMC4wLjExIDAeBgNVBAoTF1Rlc3Qg +U2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCd +xgF7K/c/esDIl4NEqlOPghD1UNDejt0miKrkCGmnxnWauKY45me+LfRmHqsmFz8F +2657/B0Xh1cLD46jYC7vwRrFC7vkkxXaf7/EjLJjqNFUl0yjKrBSZOii3goxeekd +DFv7MNqZn2dxaJL18jEtbXUBrFBZ5sVN2ftmWqU2QwIDAQABoAAwDQYJKoZIhvcN +AQEFBQADgYEAnMwWYJhhXUF2pu9YPxrNX7D3/EatZNugzFR1e/BCusH6LXUaGKbD +ionzVVjkxCBEysK8B4Dcrw1+65mHAQehs3TesaEfZ3ykf9rC8cPY+kwzsqL96H3z +OOTfz6XuhANUKkSwD3coqauGwIubCCsE2qiBYib5OJwfchbDsIcIBdc= +-----END CERTIFICATE REQUEST----- diff --git a/tools/asterisk/keys/asterisk.key b/tools/asterisk/keys/asterisk.key new file mode 100644 index 0000000000000000000000000000000000000000..3d5bbcb1b691eed25149cabf8316d08d6aea418b --- /dev/null +++ b/tools/asterisk/keys/asterisk.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQCdxgF7K/c/esDIl4NEqlOPghD1UNDejt0miKrkCGmnxnWauKY4 +5me+LfRmHqsmFz8F2657/B0Xh1cLD46jYC7vwRrFC7vkkxXaf7/EjLJjqNFUl0yj +KrBSZOii3goxeekdDFv7MNqZn2dxaJL18jEtbXUBrFBZ5sVN2ftmWqU2QwIDAQAB +AoGASC+NA+70u+2NAPoZjDQl8TYATk1Ak2NoGbZUAes7dBDgQ/8RxlzcwG3EMWj8 +w3vFUQfXCFEselRo5d2jVGqwbjemjynm9S0bzRdlM2zW3ORv8mKZkKRNVmr5QlJo +TD9+HbPCFSPEOOYQ2EDITBXvti2Ch16GNgVLZXd+fwePsdkCQQDR8o3HbkteyZsC +OTi14El04LEE2JLCtPeeeqNYgZw9NrLuS/QInBX0PCN08DY3RemmWsH4/KqFhS/t +xSMIKJLHAkEAwGGokL0+d1F2eIdQ8BkcpF+AUM7kwSpzTQ2oRSnK+6vj341YAESf +H4Nki54QHBQiHuFQBiDOCuonX/CBnLCEpQJAByjpcuKtCVeAxMukxncWqji7cLne +D2vSggIWrf8FkATch0np0Z1ZFlIyt1s1zh7BQB4aPV6IhjMrlkVB05ZmowJAcZT2 +9cWVbNLe1Fhn8+mPnIh59LvCGT3b50FJ+NOs8RvSJPmJXFcnb26e3UOMFVfZsUur +eILDw3PtnVoc3ArntQJANA/uYKQtNcFuDHPR7mYpLLcAxNW1pNh5Ynq5tSivoXsu +ED3RTExmskv2sXsjE69K75JD823zdVu0mUmAkYMQiQ== +-----END RSA PRIVATE KEY----- diff --git a/tools/asterisk/keys/asterisk.pem b/tools/asterisk/keys/asterisk.pem new file mode 100644 index 0000000000000000000000000000000000000000..2c43c07fae9e47346531a7d0e14e3181ba9ff963 --- /dev/null +++ b/tools/asterisk/keys/asterisk.pem @@ -0,0 +1,36 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQCdxgF7K/c/esDIl4NEqlOPghD1UNDejt0miKrkCGmnxnWauKY4 +5me+LfRmHqsmFz8F2657/B0Xh1cLD46jYC7vwRrFC7vkkxXaf7/EjLJjqNFUl0yj +KrBSZOii3goxeekdDFv7MNqZn2dxaJL18jEtbXUBrFBZ5sVN2ftmWqU2QwIDAQAB +AoGASC+NA+70u+2NAPoZjDQl8TYATk1Ak2NoGbZUAes7dBDgQ/8RxlzcwG3EMWj8 +w3vFUQfXCFEselRo5d2jVGqwbjemjynm9S0bzRdlM2zW3ORv8mKZkKRNVmr5QlJo +TD9+HbPCFSPEOOYQ2EDITBXvti2Ch16GNgVLZXd+fwePsdkCQQDR8o3HbkteyZsC +OTi14El04LEE2JLCtPeeeqNYgZw9NrLuS/QInBX0PCN08DY3RemmWsH4/KqFhS/t +xSMIKJLHAkEAwGGokL0+d1F2eIdQ8BkcpF+AUM7kwSpzTQ2oRSnK+6vj341YAESf +H4Nki54QHBQiHuFQBiDOCuonX/CBnLCEpQJAByjpcuKtCVeAxMukxncWqji7cLne +D2vSggIWrf8FkATch0np0Z1ZFlIyt1s1zh7BQB4aPV6IhjMrlkVB05ZmowJAcZT2 +9cWVbNLe1Fhn8+mPnIh59LvCGT3b50FJ+NOs8RvSJPmJXFcnb26e3UOMFVfZsUur +eILDw3PtnVoc3ArntQJANA/uYKQtNcFuDHPR7mYpLLcAxNW1pNh5Ynq5tSivoXsu +ED3RTExmskv2sXsjE69K75JD823zdVu0mUmAkYMQiQ== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDZjCCAU4CAQEwDQYJKoZIhvcNAQEFBQAwQDEcMBoGA1UEAxMTQXN0ZXJpc2sg +UHJpdmF0ZSBDQTEgMB4GA1UEChMXVGVzdCBTYXZvaXItRmFpcmUgTGludXgwHhcN +MTIwNDE2MjEwNzU3WhcNMTMwNDE2MjEwNzU3WjA2MRIwEAYDVQQDEwkxMjcuMC4w +LjExIDAeBgNVBAoTF1Rlc3QgU2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQCdxgF7K/c/esDIl4NEqlOPghD1UNDejt0miKrkCGmn +xnWauKY45me+LfRmHqsmFz8F2657/B0Xh1cLD46jYC7vwRrFC7vkkxXaf7/EjLJj +qNFUl0yjKrBSZOii3goxeekdDFv7MNqZn2dxaJL18jEtbXUBrFBZ5sVN2ftmWqU2 +QwIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCGBJTTqtPXDZmqdjp1tt+LiC9Jc4fs +6ounWAiHKgyboVGCk8ouDeNhbHnAqxkjAFzFPiuhuiYnKHQcOZ71YHHbMO8Mo8xV +BvT1KGlDSg/BfRkLMzFea3kIomSXUxPPqHx+EVD7HpsZVQ+4LNwAdg+C3S/9JaNE +7KWY4dXuaIsS51uiNhxwSKuD7Mqp25FH/cIVl6D9m+4l6RHRDSleISv/PKEh4400 +hM4dUe4K7fCziTI0DDDz1WMGrlGg9pq2PGqqMaNg7tog7wyEq5VDZc0CYggEfMO8 +3BK6FLrVOAf6FHOHlzhX/YpFhouaJtIQ+Ke8/X4j8O48nhJN+qvUovEvGRBYF1JC +NSsH26dAYvFMzwLxc9QIEn/35ygOpH7FV3eTIryZ4qgulQznKtUF8jsnhkQR8S1N +vTKCr2JkevxU1c24mmBvd+NUYU9JL9BAoAPyCcSzvQf3imnJ3nMhRAG9c0C/7JAI +IzmRVYBvoeTCYJdEctQX/Y0SaDque2JJVWhGkeeneJirh1LGwH5yEstFp7Rvus+t +MERVZOupPx9NRc6STfd3TLtNqPuhU5AoLknxtvpyBeWCiwCL1+/NNSAXdUDO0MrF +UFfAOdKWORTL8p0ZrVcy7N3UwK+P2bkjhrz+3PWh2airczYIycEXeDvmT20/6X/A +1jHWfYG7WWPECA== +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/ca.cfg b/tools/asterisk/keys/ca.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f362441845dd96792477e6e592f397923b57d711 --- /dev/null +++ b/tools/asterisk/keys/ca.cfg @@ -0,0 +1,10 @@ +[req] +distinguished_name = req_distinguished_name +prompt = no + +[req_distinguished_name] +CN=Asterisk Private CA +O=Test Savoir-Faire Linux + +[ext] +basicConstraints=CA:TRUE diff --git a/tools/asterisk/keys/ca.crt b/tools/asterisk/keys/ca.crt new file mode 100644 index 0000000000000000000000000000000000000000..bce248b454f3c0b4dfde1ab2762981a60d7caf57 --- /dev/null +++ b/tools/asterisk/keys/ca.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE/DCCAuQCCQCHJx9CtI2lVDANBgkqhkiG9w0BAQUFADBAMRwwGgYDVQQDExNB +c3RlcmlzayBQcml2YXRlIENBMSAwHgYDVQQKExdUZXN0IFNhdm9pci1GYWlyZSBM +aW51eDAeFw0xMjA0MTYyMTA3NTJaFw0xMzA0MTYyMTA3NTJaMEAxHDAaBgNVBAMT +E0FzdGVyaXNrIFByaXZhdGUgQ0ExIDAeBgNVBAoTF1Rlc3QgU2F2b2lyLUZhaXJl +IExpbnV4MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArD4kMmNp/EmP +aqsg9/UWviUXPHjze8TpJfFB4eNJy7HsBHAJSyfrf8NU9Bv8zWsPFs27GKC1EH+N +i+KIqmz5LZuh6e3q9QwC1ii17ruTZBAAxZXUcH1uX13MhJtaKEvT1pnnGFAA7eRT +VIvN27R6uTVzBsJKe+qEwxr5ozN5g3JqpM0yF+lQtUWTw9g7JQnw4a/78/qDSnHm +DnBb8zDccAZiyyhPAzUunrlEIAfTZObrx8xbQRNuRbv55jgcBLwqVUbr0b9Tvx5y +lM/jqrCYQee1ayNpaHLqYgk8/e2zicM1NBwTLSTITwaaDIJL/YHkDo13UAhGZ3D/ +P9tIGCcGea4zoVhzkakCfSHMR+WUad4Y2sG9wR46S5SDuVUQgrEGgMBFykMYfSCL +Xs8h6flD5BfaE4FKeQcwfZvaFxieV/5hW6y7splL10pRbmsOleK1rn+aoA9b2Lo7 +HFLbaDMjkOOTGsAxlWMJcbOoPKzsX+4VsUU7/dAMK8QDMGuJOBZ3uX5ESIHj23qv +oZ3KmreW/VsAlU7J0n7ElQIEbBuqcw/xPZfJpG364Tm9V560JXmNKIlsGbUsT3zA +NV68EOZlcSXEGOIr8adC7geHtL+cJ8TejiUIFjDWIcJaU0Gg6nFeyY1jhBnEBVxm +Qg9KT2vKloSlCNyMki0kwXld2l48SG8CAwEAATANBgkqhkiG9w0BAQUFAAOCAgEA +VkmvTg1DbX0/70A+UijAk+GwJpOak3FaKwgF1zFu1zVQGOnPXxeOa2B7cffgXxSq +CNccHB3yZyU0skxRkRLjyHRTgtObvH3KmEDMUSBlH06hKzOGbnhhNFkJGmXSEN/Y +4QytlApqP3Ugpu931xtS3JDfSwwQCbdoUU5Jnn4pRgcGXZI9jTP8wz9w3YVvFUn3 +7bF5WEwtbtMh9Umtx5EpZa9CFAnABY+qU18kucHwu7wtucIaEyPdTT9I0H8Wzn0P +6elhzJlhru/xaekhZU+Qk1kDwHndLUUfl6/KpLO7gYKqUyAW6rGjgKGuT/0O3Iw6 +yVsz/zmvkUYK6lCMLDY8Kva3Gc0QmRxnO/GcdwAd3WP85V6Nh5bx1Vrsjlro9oZ7 +AZOsUP6ghmNFBGQUl9UsFUNJjYrpZtr8AwYzY4sa46a7nEK1Pe9QxMgGMPXGSwT3 +0PYVXPABgpgEJJTBnejRi7/xsr60qLrEqPlnAWvq8/g6MrEVz2OUPK3c/pBS9xMf +pgo+adR3zgKHtfE7Ud+Vlw19ASZy/5P7pqkFUuCqOKziJMYSTq92SGqry1svPlqo +YvpTNBhgCv4WrgdcgceRMOONNyeo55lR417VtY0wiE6pkzcwU5m1O0MceYndk5Tq +f1fpnAn3GkgKbphiPEU7megH4rdjt2XUa+N/QiRzjyU= +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/ca.key b/tools/asterisk/keys/ca.key new file mode 100644 index 0000000000000000000000000000000000000000..723a1be63c23af685165d4a153d70a5529cb1f76 --- /dev/null +++ b/tools/asterisk/keys/ca.key @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,2C7C01E8719BBC40 + +nHi+LlUabC/JCdra5WRyWl2F2Y6O/YpBmekFldvtTMb+4Z2BHE3WDBU+p3VaP+Uw +vEyKmeKKfGsL5VTVNNZCbbxL5BGy/I/72kO8dhgdy1wwzE84LQjHG6DOBUnr/p2v +AIlUxzK7KcUbXyJyFlIf+B0pwCaFASh6EXHWA4u6FkhyYY7buaf15mGtQncmvPem +pVyFyddcPpW7w6+HrSCWr1xBNFw73zlV8sjhxNW1n7+ORNe6yu5lce35nwxsYrAx +xxul94nNHH7JCbF2rYMIKb+/ycer52Qww4W7fHRJC8odjJy3Np5Bfa1LMvGqHlyq +tVjR8Bs0feyNlxebqgmiozCJhudBS9P7jbjtp3nbzLxQG/BYlH6jgeD5nhruUS8p +2nXRZ+oAsnclP9sAHdro1SXsbv9w+cvN9MENoYCSlA/8KUctrjdhLnPCGT20PPMr +27viMTV4vOEnQwUFVzIE4lvC6X9nqxKHxW2tcoz//A/IN1IcB11nSFH3l1ZdTsd1 +BrfWxW5/gWL4K+wgNEFlm6QG6bDU7Ek+dKeT4e1PzVbM8okqhTzj6KO2rGVcc6WK +PcVd+Hcq/fvdxUGoFNnfqpmoBSmXiDkoDnkrGluflP8Zi0HpzGnUkN3EA38YnpAW +fPqqrXjVOtgSvcBD6RJL5/MZn98fMXECNwfZEs8/CMW91whHApjgyQyMmX1MN3xS +NgkLlBa24rvzBLzaQyCATQ1PKundV8d8NiLIV4V8QL5zxHFG6IQiJJV0+zukdCR6 +0DcH5tfj4almm9w4WbqcUzaAlkW1CQdZDVhK62aVAe7rubG4EPVd6iHUMzOwGHbT +GB1AdIsAQfN9h46KmNtLu2OBwqzJtBOMeQf0McWvkQeEOQ9VhJL2VvQdHhtYbDb4 +ZS3VkbEvVxUmCO71HeYLQ88nSkS4hhIZ2nfaeOk1BBeFf2tC6P7agq4Dpxp+4vFW +TqBiJ6lbFJi8DWKlTbjzVu+daX/iFECGm95AZ8DFdWy5O6wiczc1MEkUAzF6pUzz +WZm671L6UJiPSgEW7kIp8Af/jW8An5mcjGD1IsQurcUdtCcCM2HfA1AVu57O9jfD +KKsOgLcyJBqneVzeZ1j/WoqKwzElG1nmUnVCoUQa3xAdKUba0BIUduEKoKSD1Amh +sCKzJxfMDgRdLymfcan4wj89+GkZzAtVLdeVDaUrtNwUIuQf/A3pXeqi/EjFgsaC +tGSqKA5VghHvaEtE29of0VMkqHH0whP00Mhq6F8wUlvU9WxjTkBg3juUAHsQ0EAy +KLnrfd2gLDiZ6FtUVlitTuPlD2kPq+RYt+lhK5EYQYJ2Cm31cn/cFJSsGlTybhhj +hsTfqV3dcVfkEmexhbys6sWtwzHhH/A67UqFWZkytjbhnD1X5Cq7lmMisIoQ3fE2 +945iLyO9ox+IGV7yqq55264Co9Xnw72XnJlNkSiPxIXL6mOzqwQHVB1m4D71Zojk +vqHnlnKyGinafXsEGh4TTWk/zUJAaZvjwUHl43q7bFwmI3FpKFXpRsDmcVk1YsEl +2ChEfbNIvbVyECOGJU5evPHwuKirB2OmVOzfxJp39TgEkGDiCSv9PYIwoUY+2Qfg +ZBW/gTUBGOWMuzDqgqKVpWW53qBb5E6Zp8O7umfbOtw+c5a3vD/Jv8u/zsZwBh0b +DOK7+tDAR05asleYmieSPpd3Jtfn77HkOWIDT47A8dWzOtDRJNZXOIlJE/tCar5F +1GNJMr/e/oNZyJ/DrdVHuD9TJrCA8zjqHwk2RMo9wilClgNlsc6m69ipxhG2mzVF +KlrJQc4pvlYoQp/d5NwEO0t/JGKO5SFlsgL9K7+C6t7eS5EupiAYwYjbH+/rdCBc +yyWIf4eWLlRssFY3A8QD5LoO6jpt9/oKZe88P2IFNNcKNTWXzHhkx8XskIrqw5tw +Og7iQiyF64CbAg1I9hDbs8z+pOs47BkHJa6nxbK128ZDj+c0qCCao+GX50Erv0gr +MhhAgN5XqSrcpr943sS7OzdEppz6lxcxuHDbZywGG4v2smBbzWl4reFk5e8ZyWxf +ZIOpErx8sLG44neZb4AbNbfVK9JMRvNz/kSjhZXeLvsohkAYomrGi9LUJ6TGjN7i +MHP9Hsu0nGKd10UZ7t8ZsMrxX0KAsj/Su/qMgfivLjhmj11Uzr48hZob+TaVLuRF +GAqzZcmIHYA6/NDjp0e/GwDrMd92N8SNfqPdJ0LH2a3b93teh4qlLscE8VoY7XF6 +o85t28DfgpL00+tB3VUWkFCd0f7sOgvA1TYjRITNCVNoSVFzVZjk7r8SiE3bYOd/ +IIjLJMEt2MKVDg7jrIQyMtkpqEVR+83dP3rmMz2utqkTGw33VYqrNdaLikST0nZO +uaw3RUMFfWXzKFyyVA01RepccAkls6uz/Cf3I8491b06ledxByyazCHkFLGnRuJZ +/KDfutbStKoqRIQEfHpk43mu4pfT/8xGT5SygAATpIPGstlKOJ7e4/qjex8zmthW +gUcechy56Fdo5rewG/Qa2uUTv0OsjIjThM98nmWZk8VtWthWi43op2j93tsrQAkh +bH/3UBgQZ/tROp620lUwAZt2JlT5aVcYtSZvC+iwUd/Pw7ztdyenZGHmBNSq6ggM +YweVtfubWSsaL09kPEaL4Lsh8OhwIWDpbZ/DsdkDrkeXeInYhNwV3Ilx6zb9HiBk +y0kMSgro9Ob1vi62liYxN3ziFWSjxr43tjrw83oCBf9m/7o2lIOh3w/7uwXSs8K5 +ehcUEU/UmqjG+VYiu0sQZHoZzORJh5IBfRAIEpWNI53WIEYtNi1mspwWZuKc6B1J +xXU1Wq6OJwIQzitghA7CHfu7dbYidFKa8Hxv63rp5k7fZpoBWxFDzPzJZToPLfoR +eUbGWXP0hmSTZw3JHMeP5g6TvpRcvrRntl4wsiGP8HxO/yID//Anvvsaxn8/fVrv +h0Mjq1gFvzyF0ht3yfk2/MaEtpp9B6H4Y5CQj7M/xAKlCK0xF8lq91Ocxh+0k2Iq +1qM4rz1okjBwT6zA87dahK7BXY8Nh4LWSDikgzLc0fiWR1DdlGFzDrq060912uNK +B7pziHHdES0bE/8c7i3V/u4zwbM9Rj36nsC+r8d7BTyOb6Y4wN315IsG9AH8WYvt +-----END RSA PRIVATE KEY----- diff --git a/tools/asterisk/keys/testphone1.crt b/tools/asterisk/keys/testphone1.crt new file mode 100644 index 0000000000000000000000000000000000000000..c4bdbc7b8324219ba403c1cbab7b002b2b569448 --- /dev/null +++ b/tools/asterisk/keys/testphone1.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDZjCCAU4CAQEwDQYJKoZIhvcNAQEFBQAwQDEcMBoGA1UEAxMTQXN0ZXJpc2sg +UHJpdmF0ZSBDQTEgMB4GA1UEChMXVGVzdCBTYXZvaXItRmFpcmUgTGludXgwHhcN +MTIwNDE2MjExMDQ3WhcNMTMwNDE2MjExMDQ3WjA2MRIwEAYDVQQDEwkxMjcuMC4w +LjExIDAeBgNVBAoTF1Rlc3QgU2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQDcD0nVaHoNVpEVLTyN0JOVuEDUZovaMK/XXmQYnP1M +v9Ru5fU4977DpPQdjqmTSv+VD83QGbUnORdjDSgK8vAmWLnZxJJxxF1pTpbKpKDp +FO9f74xhh/ekJCWPqfeJqRbjJ5rhXqqbWPtjuI1vXgwBL7MdWQVAuzgz9+kHITxj +tQIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCqs3JJxwXqiRksCf7fGA6mt19Kp6EJ +kYv7tA2xO0qR6dHX5pE6IQ2bk22jlIHsg269oX4XAtg1OiGMCyLOfrDOve86+qlW +7+sARNmtDXHT1kQPa8FJbwmdS5Gl4PXzFrRrB6hDlBBtKu5CEMkHuscjpnt9BPA5 +RvXhb3MREs9n0VM0R8hhtgiEVPOLKZpfASSLU8iiTurBdybSAb1hPLRwJF+PIak8 +pohqbEo2lNZq/OdxEIvOnNO7UISfYcojmFFUatPgl35O3hTRA6/RIkPtdXOtTqzX +agZDgHvn2tnkmSPfO9Zx/8KKa9u1XyXBdNXjdoq0cEaKv7sYCKzPGPbuvoemSbmz +6u1CrZY+IkFDPLe5mkUBMzNFuHYpy5Xfafs8zo2F+NEpHHKT4PhVFWKQ+FEFoRgi +P70oA0mXtjoSIhcZiYkbwV5algr7aWP1pAO7A6mjT4SQpk/LSN96eBvy5Llkgety +Fl+TZizCKMN+PVELgMjQwkHGNDFCyrxGS9j5SSvYj8lIIqlqyOkpsLarfK73JEfZ +Ad52SK+2/6LamoQbouwVVx7grDEtP+jfqYlr4Mrif8IgoDw9vHSVtlDZ6o5kJh7y +ZWQz0EDQJXlxnKb4UkftilOUoDPinc1nkRvk6s/DQ6JrHDKYaVyHckjj5xEiqzuP +USftzxBPTlP4dA== +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/testphone1.csr b/tools/asterisk/keys/testphone1.csr new file mode 100644 index 0000000000000000000000000000000000000000..7599b6114a5cc643e1f223de57125820635a691f --- /dev/null +++ b/tools/asterisk/keys/testphone1.csr @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBdTCB3wIBADA2MRIwEAYDVQQDEwkxMjcuMC4wLjExIDAeBgNVBAoTF1Rlc3Qg +U2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDc +D0nVaHoNVpEVLTyN0JOVuEDUZovaMK/XXmQYnP1Mv9Ru5fU4977DpPQdjqmTSv+V +D83QGbUnORdjDSgK8vAmWLnZxJJxxF1pTpbKpKDpFO9f74xhh/ekJCWPqfeJqRbj +J5rhXqqbWPtjuI1vXgwBL7MdWQVAuzgz9+kHITxjtQIDAQABoAAwDQYJKoZIhvcN +AQEFBQADgYEAyqOCNC90ONkad55VRJDnxxhGDtOHlmy/87+5XF09luqF2i2aRjV5 +sY8fkHmkcMH0ppMTakrTxLsfJUJ6k5CCg3zXRzUB8Eg89gmPQuPEbBWEXm5ahZIS +ceJUoOTSfNAfiYaTTaap2dCTb4ENrOyyu6WMbH22FBgr/OQrRB9NLS8= +-----END CERTIFICATE REQUEST----- diff --git a/tools/asterisk/keys/testphone1.key b/tools/asterisk/keys/testphone1.key new file mode 100644 index 0000000000000000000000000000000000000000..8562655775cc80ae5709620d8e85e17410207436 --- /dev/null +++ b/tools/asterisk/keys/testphone1.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDcD0nVaHoNVpEVLTyN0JOVuEDUZovaMK/XXmQYnP1Mv9Ru5fU4 +977DpPQdjqmTSv+VD83QGbUnORdjDSgK8vAmWLnZxJJxxF1pTpbKpKDpFO9f74xh +h/ekJCWPqfeJqRbjJ5rhXqqbWPtjuI1vXgwBL7MdWQVAuzgz9+kHITxjtQIDAQAB +AoGAEJIaJjbK0gxNuoGAiNFG+8Q3JYdfSpvV8erKsMvJiyj6zysDzzlgpQzb0Qn4 +HP5NxqS9A8mbyYtUBoJsHH70tFrBufsr/ewWL9W/o5SuLOVk4mtGl5aALQSa9OO8 +ue/UwOG5Wnbggdl/RqNlAtqROPfraKmK7RJxHU1MqIUs27UCQQDz2p+y5O8N+NH8 +LRDMK9Y/pk1KAKVwj20escn+Km9NThjAeF6ejhP8RcAXUdxyxPQmktc74udnGlfk +RqVa68u7AkEA5wVDq8xEaEO08g7F6msiuqImnCfvfn5j52sVXbLEh4fOlHX3gfep +B0QURCLrsq28ACHaD+AtXzVEr5IaTOi/TwJBALw4PlXdwOre6G2l9zYwi+F7ImMB +VrEn84jin8+vv1NC+XXuMtJdRe3NhLQ7OlXX0b/ITZtqy0PYoIiRQuaH5CsCQQDB +tUBQxS523o7SiGCbdsngBCaruTCvt/q9CKUZs9PmcJFfGqs2Zxtr5EG6AC3x3ItO +8ROPTEG/G0NElBVJd78xAkEAmHAZd/+5qcBlz7BLLcD1Rc598gRxaOnMNkjHw15i +KOyDNgk5m4OtZ5npbTJDrEW1wjw912ga0jb2J/urCl1X4A== +-----END RSA PRIVATE KEY----- diff --git a/tools/asterisk/keys/testphone1.pem b/tools/asterisk/keys/testphone1.pem new file mode 100644 index 0000000000000000000000000000000000000000..f704ed61e732fc1b0f17608bc01dad82f5a0ec51 --- /dev/null +++ b/tools/asterisk/keys/testphone1.pem @@ -0,0 +1,36 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDcD0nVaHoNVpEVLTyN0JOVuEDUZovaMK/XXmQYnP1Mv9Ru5fU4 +977DpPQdjqmTSv+VD83QGbUnORdjDSgK8vAmWLnZxJJxxF1pTpbKpKDpFO9f74xh +h/ekJCWPqfeJqRbjJ5rhXqqbWPtjuI1vXgwBL7MdWQVAuzgz9+kHITxjtQIDAQAB +AoGAEJIaJjbK0gxNuoGAiNFG+8Q3JYdfSpvV8erKsMvJiyj6zysDzzlgpQzb0Qn4 +HP5NxqS9A8mbyYtUBoJsHH70tFrBufsr/ewWL9W/o5SuLOVk4mtGl5aALQSa9OO8 +ue/UwOG5Wnbggdl/RqNlAtqROPfraKmK7RJxHU1MqIUs27UCQQDz2p+y5O8N+NH8 +LRDMK9Y/pk1KAKVwj20escn+Km9NThjAeF6ejhP8RcAXUdxyxPQmktc74udnGlfk +RqVa68u7AkEA5wVDq8xEaEO08g7F6msiuqImnCfvfn5j52sVXbLEh4fOlHX3gfep +B0QURCLrsq28ACHaD+AtXzVEr5IaTOi/TwJBALw4PlXdwOre6G2l9zYwi+F7ImMB +VrEn84jin8+vv1NC+XXuMtJdRe3NhLQ7OlXX0b/ITZtqy0PYoIiRQuaH5CsCQQDB +tUBQxS523o7SiGCbdsngBCaruTCvt/q9CKUZs9PmcJFfGqs2Zxtr5EG6AC3x3ItO +8ROPTEG/G0NElBVJd78xAkEAmHAZd/+5qcBlz7BLLcD1Rc598gRxaOnMNkjHw15i +KOyDNgk5m4OtZ5npbTJDrEW1wjw912ga0jb2J/urCl1X4A== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDZjCCAU4CAQEwDQYJKoZIhvcNAQEFBQAwQDEcMBoGA1UEAxMTQXN0ZXJpc2sg +UHJpdmF0ZSBDQTEgMB4GA1UEChMXVGVzdCBTYXZvaXItRmFpcmUgTGludXgwHhcN +MTIwNDE2MjExMDQ3WhcNMTMwNDE2MjExMDQ3WjA2MRIwEAYDVQQDEwkxMjcuMC4w +LjExIDAeBgNVBAoTF1Rlc3QgU2F2b2lyLUZhaXJlIExpbnV4MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQDcD0nVaHoNVpEVLTyN0JOVuEDUZovaMK/XXmQYnP1M +v9Ru5fU4977DpPQdjqmTSv+VD83QGbUnORdjDSgK8vAmWLnZxJJxxF1pTpbKpKDp +FO9f74xhh/ekJCWPqfeJqRbjJ5rhXqqbWPtjuI1vXgwBL7MdWQVAuzgz9+kHITxj +tQIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCqs3JJxwXqiRksCf7fGA6mt19Kp6EJ +kYv7tA2xO0qR6dHX5pE6IQ2bk22jlIHsg269oX4XAtg1OiGMCyLOfrDOve86+qlW +7+sARNmtDXHT1kQPa8FJbwmdS5Gl4PXzFrRrB6hDlBBtKu5CEMkHuscjpnt9BPA5 +RvXhb3MREs9n0VM0R8hhtgiEVPOLKZpfASSLU8iiTurBdybSAb1hPLRwJF+PIak8 +pohqbEo2lNZq/OdxEIvOnNO7UISfYcojmFFUatPgl35O3hTRA6/RIkPtdXOtTqzX +agZDgHvn2tnkmSPfO9Zx/8KKa9u1XyXBdNXjdoq0cEaKv7sYCKzPGPbuvoemSbmz +6u1CrZY+IkFDPLe5mkUBMzNFuHYpy5Xfafs8zo2F+NEpHHKT4PhVFWKQ+FEFoRgi +P70oA0mXtjoSIhcZiYkbwV5algr7aWP1pAO7A6mjT4SQpk/LSN96eBvy5Llkgety +Fl+TZizCKMN+PVELgMjQwkHGNDFCyrxGS9j5SSvYj8lIIqlqyOkpsLarfK73JEfZ +Ad52SK+2/6LamoQbouwVVx7grDEtP+jfqYlr4Mrif8IgoDw9vHSVtlDZ6o5kJh7y +ZWQz0EDQJXlxnKb4UkftilOUoDPinc1nkRvk6s/DQ6JrHDKYaVyHckjj5xEiqzuP +USftzxBPTlP4dA== +-----END CERTIFICATE----- diff --git a/tools/asterisk/keys/tmp.cfg b/tools/asterisk/keys/tmp.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f9d4477e978ba4a795440491b0922beff81e1ab9 --- /dev/null +++ b/tools/asterisk/keys/tmp.cfg @@ -0,0 +1,7 @@ +[req] +distinguished_name = req_distinguished_name +prompt = no + +[req_distinguished_name] +CN=127.0.0.1 +O=Test Savoir-Faire Linux diff --git a/tools/asterisk/sip.conf b/tools/asterisk/sip.conf new file mode 100644 index 0000000000000000000000000000000000000000..5ec53dfb8774ddf14ef30c7515b44efdd7a8cf24 --- /dev/null +++ b/tools/asterisk/sip.conf @@ -0,0 +1,1378 @@ +; +; SIP Configuration example for Asterisk +; +; Note: Please read the security documentation for Asterisk in order to +; understand the risks of installing Asterisk with the sample +; configuration. If your Asterisk is installed on a public +; IP address connected to the Internet, you will want to learn +; about the various security settings BEFORE you start +; Asterisk. +; +; Especially note the following settings: +; - allowguest (default enabled) +; - permit/deny - IP address filters +; - contactpermit/contactdeny - IP address filters for registrations +; - context - Which set of services you offer various users +; +; SIP dial strings +;----------------------------------------------------------- +; In the dialplan (extensions.conf) you can use several +; syntaxes for dialing SIP devices. +; SIP/devicename +; SIP/username@domain (SIP uri) +; SIP/username[:password[:md5secret[:authname[:transport]]]]@host[:port] +; SIP/devicename/extension +; SIP/devicename/extension/IPorHost +; SIP/username@domain//IPorHost +; +; +; Devicename +; devicename is defined as a peer in a section below. +; +; username@domain +; Call any SIP user on the Internet +; (Don't forget to enable DNS SRV records if you want to use this) +; +; devicename/extension +; If you define a SIP proxy as a peer below, you may call +; SIP/proxyhostname/user or SIP/user@proxyhostname +; where the proxyhostname is defined in a section below +; This syntax also works with ATA's with FXO ports +; +; SIP/username[:password[:md5secret[:authname]]]@host[:port] +; This form allows you to specify password or md5secret and authname +; without altering any authentication data in config. +; Examples: +; +; SIP/*98@mysipproxy +; SIP/sales:topsecret::account02@domain.com:5062 +; SIP/12345678::bc53f0ba8ceb1ded2b70e05c3f91de4f:myname@192.168.0.1 +; +; IPorHost +; The next server for this call regardless of domain/peer +; +; All of these dial strings specify the SIP request URI. +; In addition, you can specify a specific To: header by adding an +; exclamation mark after the dial string, like +; +; SIP/sales@mysipproxy!sales@edvina.net +; +; A new feature for 1.8 allows one to specify a host or IP address to use +; when routing the call. This is typically used in tandem with func_srv if +; multiple methods of reaching the same domain exist. The host or IP address +; is specified after the third slash in the dialstring. Examples: +; +; SIP/devicename/extension/IPorHost +; SIP/username@domain//IPorHost +; +; CLI Commands +; ------------------------------------------------------------- +; Useful CLI commands to check peers/users: +; sip show peers Show all SIP peers (including friends) +; sip show registry Show status of hosts we register with +; +; sip set debug on Show all SIP messages +; +; sip reload Reload configuration file +; sip show settings Show the current channel configuration +; +;------- Naming devices ------------------------------------------------------ +; +; When naming devices, make sure you understand how Asterisk matches calls +; that come in. +; 1. Asterisk checks the SIP From: address username and matches against +; names of devices with type=user +; The name is the text between square brackets [name] +; 2. Asterisk checks the From: addres and matches the list of devices +; with a type=peer +; 3. Asterisk checks the IP address (and port number) that the INVITE +; was sent from and matches against any devices with type=peer +; +; Don't mix extensions with the names of the devices. Devices need a unique +; name. The device name is *not* used as phone numbers. Phone numbers are +; anything you declare as an extension in the dialplan (extensions.conf). +; +; When setting up trunks, make sure there's no risk that any From: username +; (caller ID) will match any of your device names, because then Asterisk +; might match the wrong device. +; +; Note: The parameter "username" is not the username and in most cases is +; not needed at all. Check below. In later releases, it's renamed +; to "defaultuser" which is a better name, since it is used in +; combination with the "defaultip" setting. +;----------------------------------------------------------------------------- + +; ** Old configuration options ** +; The "call-limit" configuation option is considered old is replaced +; by new functionality. To enable callcounters, you use the new +; "callcounter" setting (for extension states in queue and subscriptions) +; You are encouraged to use the dialplan groupcount functionality +; to enforce call limits instead of using this channel-specific method. +; You can still set limits per device in sip.conf or in a database by using +; "setvar" to set variables that can be used in the dialplan for various limits. + +[general] +context=default ; Default context for incoming calls +;allowguest=no ; Allow or reject guest calls (default is yes) + ; If your Asterisk is connected to the Internet + ; and you have allowguest=yes + ; you want to check which services you offer everyone + ; out there, by enabling them in the default context (see below). +;match_auth_username=yes ; if available, match user entry using the + ; 'username' field from the authentication line + ; instead of the From: field. +allowoverlap=no ; Disable overlap dialing support. (Default is yes) +;allowtransfer=no ; Disable all transfers (unless enabled in peers or users) + ; Default is enabled. The Dial() options 't' and 'T' are not + ; related as to whether SIP transfers are allowed or not. +;realm=mydomain.tld ; Realm for digest authentication + ; defaults to "asterisk". If you set a system name in + ; asterisk.conf, it defaults to that system name + ; Realms MUST be globally unique according to RFC 3261 + ; Set this to your host name or domain name +;domainsasrealm=no ; Use domans list as realms + ; You can serve multiple Realms specifying several + ; 'domain=...' directives (see below). + ; In this case Realm will be based on request 'From'/'To' header + ; and should match one of domain names. + ; Otherwise default 'realm=...' will be used. + +; With the current situation, you can do one of four things: +; a) Listen on a specific IPv4 address. Example: bindaddr=192.0.2.1 +; b) Listen on a specific IPv6 address. Example: bindaddr=2001:db8::1 +; c) Listen on the IPv4 wildcard. Example: bindaddr=0.0.0.0 +; d) Listen on the IPv4 and IPv6 wildcards. Example: bindaddr=:: +; (You can choose independently for UDP, TCP, and TLS, by specifying different values for +; "udpbindaddr", "tcpbindaddr", and "tlsbindaddr".) +; (Note that using bindaddr=:: will show only a single IPv6 socket in netstat. +; IPv4 is supported at the same time using IPv4-mapped IPv6 addresses.) +; +; You may optionally add a port number. (The default is port 5060 for UDP and TCP, 5061 +; for TLS). +; IPv4 example: bindaddr=0.0.0.0:5062 +; IPv6 example: bindaddr=[::]:5062 +; +; The address family of the bound UDP address is used to determine how Asterisk performs +; DNS lookups. In cases a) and c) above, only A records are considered. In case b), only +; AAAA records are considered. In case d), both A and AAAA records are considered. Note, +; however, that Asterisk ignores all records except the first one. In case d), when both A +; and AAAA records are available, either an A or AAAA record will be first, and which one +; depends on the operating system. On systems using glibc, AAAA records are given +; priority. + +udpbindaddr=0.0.0.0:5062 ; IP address to bind UDP listen socket to (0.0.0.0 binds to all) + ; Optionally add a port number, 192.168.1.1:5062 (default is port 5060) + +; When a dialog is started with another SIP endpoint, the other endpoint +; should include an Allow header telling us what SIP methods the endpoint +; implements. However, some endpoints either do not include an Allow header +; or lie about what methods they implement. In the former case, Asterisk +; makes the assumption that the endpoint supports all known SIP methods. +; If you know that your SIP endpoint does not provide support for a specific +; method, then you may provide a comma-separated list of methods that your +; endpoint does not implement in the disallowed_methods option. Note that +; if your endpoint is truthful with its Allow header, then there is no need +; to set this option. This option may be set in the general section or may +; be set per endpoint. If this option is set both in the general section and +; in a peer section, then the peer setting completely overrides the general +; setting (i.e. the result is *not* the union of the two options). +; +; Note also that while Asterisk currently will parse an Allow header to learn +; what methods an endpoint supports, the only actual use for this currently +; is for determining if Asterisk may send connected line UPDATE requests. Its +; use may be expanded in the future. +; +; disallowed_methods = UPDATE + +; +; Note that the TCP and TLS support for chan_sip is currently considered +; experimental. Since it is new, all of the related configuration options are +; subject to change in any release. If they are changed, the changes will +; be reflected in this sample configuration file, as well as in the UPGRADE.txt file. +; +tcpenable=no ; Enable server for incoming TCP connections (default is no) +tcpbindaddr=0.0.0.0 ; IP address for TCP server to bind to (0.0.0.0 binds to all interfaces) + ; Optionally add a port number, 192.168.1.1:5062 (default is port 5060) + +tlsenable=yes ; Enable server for incoming TLS (secure) connections (default is no) +tlsbindaddr=0.0.0.0:5061 ; IP address for TLS server to bind to (0.0.0.0) binds to all interfaces) + ; Optionally add a port number, 192.168.1.1:5063 (default is port 5061) + ; Remember that the IP address must match the common name (hostname) in the + ; certificate, so you don't want to bind a TLS socket to multiple IP addresses. + ; For details how to construct a certificate for SIP see + ; http://tools.ietf.org/html/draft-ietf-sip-domain-certs + +;tcpauthtimeout = 30 ; tcpauthtimeout specifies the maximum number + ; of seconds a client has to authenticate. If + ; the client does not authenticate beofre this + ; timeout expires, the client will be + ; disconnected. (default: 30 seconds) + +;tcpauthlimit = 100 ; tcpauthlimit specifies the maximum number of + ; unauthenticated sessions that will be allowed + ; to connect at any given time. (default: 100) + +;srvlookup=yes ; Enable DNS SRV lookups on outbound calls + ; Note: Asterisk only uses the first host + ; in SRV records + ; Disabling DNS SRV lookups disables the + ; ability to place SIP calls based on domain + ; names to some other SIP users on the Internet + ; Specifying a port in a SIP peer definition or + ; when dialing outbound calls will supress SRV + ; lookups for that peer or call. + +;pedantic=yes ; Enable checking of tags in headers, + ; international character conversions in URIs + ; and multiline formatted headers for strict + ; SIP compatibility (defaults to "yes") + +; See https://wiki.asterisk.org/wiki/display/AST/IP+Quality+of+Service for a description of these parameters. +;tos_sip=cs3 ; Sets TOS for SIP packets. +;tos_audio=ef ; Sets TOS for RTP audio packets. +;tos_video=af41 ; Sets TOS for RTP video packets. +;tos_text=af41 ; Sets TOS for RTP text packets. + +;cos_sip=3 ; Sets 802.1p priority for SIP packets. +;cos_audio=5 ; Sets 802.1p priority for RTP audio packets. +;cos_video=4 ; Sets 802.1p priority for RTP video packets. +;cos_text=3 ; Sets 802.1p priority for RTP text packets. + +;maxexpiry=3600 ; Maximum allowed time of incoming registrations + ; and subscriptions (seconds) +;minexpiry=60 ; Minimum length of registrations/subscriptions (default 60) +;defaultexpiry=120 ; Default length of incoming/outgoing registration +;mwiexpiry=3600 ; Expiry time for outgoing MWI subscriptions +;maxforwards=70 ; Setting for the SIP Max-Forwards: header (loop prevention) + ; Default value is 70 +;qualifyfreq=60 ; Qualification: How often to check for the host to be up in seconds + ; and reported in milliseconds with sip show settings. + ; Set to low value if you use low timeout for NAT of UDP sessions + ; Default: 60 +;qualifygap=100 ; Number of milliseconds between each group of peers being qualified + ; Default: 100 +;qualifypeers=1 ; Number of peers in a group to be qualified at the same time + ; Default: 1 +;notifymimetype=text/plain ; Allow overriding of mime type in MWI NOTIFY +;buggymwi=no ; Cisco SIP firmware doesn't support the MWI RFC + ; fully. Enable this option to not get error messages + ; when sending MWI to phones with this bug. +;mwi_from=asterisk ; When sending MWI NOTIFY requests, use this setting in + ; the From: header as the "name" portion. Also fill the + ; "user" portion of the URI in the From: header with this + ; value if no fromuser is set + ; Default: empty +;vmexten=voicemail ; dialplan extension to reach mailbox sets the + ; Message-Account in the MWI notify message + ; defaults to "asterisk" + +; Codec negotiation +; +; When Asterisk is receiving a call, the codec will initially be set to the +; first codec in the allowed codecs defined for the user receiving the call +; that the caller also indicates that it supports. But, after the caller +; starts sending RTP, Asterisk will switch to using whatever codec the caller +; is sending. +; +; When Asterisk is placing a call, the codec used will be the first codec in +; the allowed codecs that the callee indicates that it supports. Asterisk will +; *not* switch to whatever codec the callee is sending. +; +;preferred_codec_only=yes ; Respond to a SIP invite with the single most preferred codec + ; rather than advertising all joint codec capabilities. This + ; limits the other side's codec choice to exactly what we prefer. + +;disallow=all ; First disallow all codecs +;allow=ulaw ; Allow codecs in order of preference +;allow=ilbc ; see https://wiki.asterisk.org/wiki/display/AST/RTP+Packetization + ; for framing options +; +; This option specifies a preference for which music on hold class this channel +; should listen to when put on hold if the music class has not been set on the +; channel with Set(CHANNEL(musicclass)=whatever) in the dialplan, and the peer +; channel putting this one on hold did not suggest a music class. +; +; This option may be specified globally, or on a per-user or per-peer basis. +; +;mohinterpret=default +; +; This option specifies which music on hold class to suggest to the peer channel +; when this channel places the peer on hold. It may be specified globally or on +; a per-user or per-peer basis. +; +;mohsuggest=default +; +;parkinglot=plaza ; Sets the default parking lot for call parking + ; This may also be set for individual users/peers + ; Parkinglots are configured in features.conf +;language=en ; Default language setting for all users/peers + ; This may also be set for individual users/peers +;relaxdtmf=yes ; Relax dtmf handling +;trustrpid = no ; If Remote-Party-ID should be trusted +;sendrpid = yes ; If Remote-Party-ID should be sent (defaults to no) +;sendrpid = rpid ; Use the "Remote-Party-ID" header + ; to send the identity of the remote party + ; This is identical to sendrpid=yes +;sendrpid = pai ; Use the "P-Asserted-Identity" header + ; to send the identity of the remote party +;rpid_update = no ; In certain cases, the only method by which a connected line + ; change may be immediately transmitted is with a SIP UPDATE request. + ; If communicating with another Asterisk server, and you wish to be able + ; transmit such UPDATE messages to it, then you must enable this option. + ; Otherwise, we will have to wait until we can send a reinvite to + ; transmit the information. +;prematuremedia=no ; Some ISDN links send empty media frames before + ; the call is in ringing or progress state. The SIP + ; channel will then send 183 indicating early media + ; which will be empty - thus users get no ring signal. + ; Setting this to "yes" will stop any media before we have + ; call progress (meaning the SIP channel will not send 183 Session + ; Progress for early media). Default is "yes". Also make sure that + ; the SIP peer is configured with progressinband=never. + ; + ; In order for "noanswer" applications to work, you need to run + ; the progress() application in the priority before the app. + +;progressinband=never ; If we should generate in-band ringing always + ; use 'never' to never use in-band signalling, even in cases + ; where some buggy devices might not render it + ; Valid values: yes, no, never Default: never +;useragent=Asterisk PBX ; Allows you to change the user agent string + ; The default user agent string also contains the Asterisk + ; version. If you don't want to expose this, change the + ; useragent string. +;promiscredir = no ; If yes, allows 302 or REDIR to non-local SIP address + ; Note that promiscredir when redirects are made to the + ; local system will cause loops since Asterisk is incapable + ; of performing a "hairpin" call. +;usereqphone = no ; If yes, ";user=phone" is added to uri that contains + ; a valid phone number +;dtmfmode = rfc2833 ; Set default dtmfmode for sending DTMF. Default: rfc2833 + ; Other options: + ; info : SIP INFO messages (application/dtmf-relay) + ; shortinfo : SIP INFO messages (application/dtmf) + ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw) + ; auto : Use rfc2833 if offered, inband otherwise + +;compactheaders = yes ; send compact sip headers. +; +;videosupport=yes ; Turn on support for SIP video. You need to turn this + ; on in this section to get any video support at all. + ; You can turn it off on a per peer basis if the general + ; video support is enabled, but you can't enable it for + ; one peer only without enabling in the general section. + ; If you set videosupport to "always", then RTP ports will + ; always be set up for video, even on clients that don't + ; support it. This assists callfile-derived calls and + ; certain transferred calls to use always use video when + ; available. [yes|NO|always] + +;maxcallbitrate=384 ; Maximum bitrate for video calls (default 384 kb/s) + ; Videosupport and maxcallbitrate is settable + ; for peers and users as well +;callevents=no ; generate manager events when sip ua + ; performs events (e.g. hold) +;authfailureevents=no ; generate manager "peerstatus" events when peer can't + ; authenticate with Asterisk. Peerstatus will be "rejected". +;alwaysauthreject = yes ; When an incoming INVITE or REGISTER is to be rejected, + ; for any reason, always reject with an identical response + ; equivalent to valid username and invalid password/hash + ; instead of letting the requester know whether there was + ; a matching user or peer for their request. This reduces + ; the ability of an attacker to scan for valid SIP usernames. + ; This option is set to "yes" by default. + +;auth_options_requests = yes ; Enabling this option will authenticate OPTIONS requests just like + ; INVITE requests are. By default this option is disabled. + +;g726nonstandard = yes ; If the peer negotiates G726-32 audio, use AAL2 packing + ; order instead of RFC3551 packing order (this is required + ; for Sipura and Grandstream ATAs, among others). This is + ; contrary to the RFC3551 specification, the peer _should_ + ; be negotiating AAL2-G726-32 instead :-( +;outboundproxy=proxy.provider.domain ; send outbound signaling to this proxy, not directly to the devices +;outboundproxy=proxy.provider.domain:8080 ; send outbound signaling to this proxy, not directly to the devices +;outboundproxy=proxy.provider.domain,force ; Send ALL outbound signalling to proxy, ignoring route: headers +;outboundproxy=tls://proxy.provider.domain ; same as '=proxy.provider.domain' except we try to connect with tls +;outboundproxy=192.0.2.1 ; IPv4 address literal (default port is 5060) +;outboundproxy=2001:db8::1 ; IPv6 address literal (default port is 5060) +;outboundproxy=192.168.0.2.1:5062 ; IPv4 address literal with explicit port +;outboundproxy=[2001:db8::1]:5062 ; IPv6 address literal with explicit port +; ; (could also be tcp,udp) - defining transports on the proxy line only +; ; applies for the global proxy, otherwise use the transport= option +;matchexternaddrlocally = yes ; Only substitute the externaddr or externhost setting if it matches + ; your localnet setting. Unless you have some sort of strange network + ; setup you will not need to enable this. + +;dynamic_exclude_static = yes ; Disallow all dynamic hosts from registering + ; as any IP address used for staticly defined + ; hosts. This helps avoid the configuration + ; error of allowing your users to register at + ; the same address as a SIP provider. + +;contactdeny=0.0.0.0/0.0.0.0 ; Use contactpermit and contactdeny to +;contactpermit=172.16.0.0/255.255.0.0 ; restrict at what IPs your users may + ; register their phones. + +;engine=asterisk ; RTP engine to use when communicating with the device + +; +; If regcontext is specified, Asterisk will dynamically create and destroy a +; NoOp priority 1 extension for a given peer who registers or unregisters with +; us and have a "regexten=" configuration item. +; Multiple contexts may be specified by separating them with '&'. The +; actual extension is the 'regexten' parameter of the registering peer or its +; name if 'regexten' is not provided. If more than one context is provided, +; the context must be specified within regexten by appending the desired +; context after '@'. More than one regexten may be supplied if they are +; separated by '&'. Patterns may be used in regexten. +; +;regcontext=sipregistrations +;regextenonqualify=yes ; Default "no" + ; If you have qualify on and the peer becomes unreachable + ; this setting will enforce inactivation of the regexten + ; extension for the peer + +; The shrinkcallerid function removes '(', ' ', ')', non-trailing '.', and '-' not +; in square brackets. For example, the caller id value 555.5555 becomes 5555555 +; when this option is enabled. Disabling this option results in no modification +; of the caller id value, which is necessary when the caller id represents something +; that must be preserved. This option can only be used in the [general] section. +; By default this option is on. +; +;shrinkcallerid=yes ; on by default + + +;use_q850_reason = no ; Default "no" + ; Set to yes add Reason header and use Reason header if it is available. +; +;------------------------ TLS settings ------------------------------------------------------------ +tlscertfile=/etc/asterisk/keys/asterisk.pem ; Certificate file (*.pem format only) to use for TLS connections + ; default is to look for "asterisk.pem" in current directory + +; tlsprivatekey=/etc/asterisk/keys/asterisk.key ; Private key file (*.pem format only) for TLS connections. + ; If no tlsprivatekey is specified, tlscertfile is searched for + ; for both public and private key. + +; tlscafile=/etc/asterisk/keys/ca.crt +; If the server your connecting to uses a self signed certificate +; you should have their certificate installed here so the code can +; verify the authenticity of their certificate. + +; tlscapath=/etc/asterisk/keys/ +; A directory full of CA certificates. The files must be named with +; the CA subject name hash value. +; (see man SSL_CTX_load_verify_locations for more info) + +; tlsdontverifyserver=[yes|no] +; If set to yes, don't verify the servers certificate when acting as +; a client. If you don't have the server's CA certificate you can +; set this and it will connect without requiring tlscafile to be set. +; Default is no. + +; tlscipher=ALL +; A string specifying which SSL ciphers to use or not use +; A list of valid SSL cipher strings can be found at: +; http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS +; +; tlsclientmethod=tlsv1 ; values include tlsv1, sslv3, sslv2. + ; Specify protocol for outbound client connections. + ; If left unspecified, the default is sslv2. +; +;--------------------------- SIP timers ---------------------------------------------------- +; These timers are used primarily in INVITE transactions. +; The default for Timer T1 is 500 ms or the measured run-trip time between +; Asterisk and the device if you have qualify=yes for the device. +; +;t1min=100 ; Minimum roundtrip time for messages to monitored hosts + ; Defaults to 100 ms +;timert1=500 ; Default T1 timer + ; Defaults to 500 ms or the measured round-trip + ; time to a peer (qualify=yes). +;timerb=32000 ; Call setup timer. If a provisional response is not received + ; in this amount of time, the call will autocongest + ; Defaults to 64*timert1 + +;--------------------------- RTP timers ---------------------------------------------------- +; These timers are currently used for both audio and video streams. The RTP timeouts +; are only applied to the audio channel. +; The settings are settable in the global section as well as per device +; +;rtptimeout=60 ; Terminate call if 60 seconds of no RTP or RTCP activity + ; on the audio channel + ; when we're not on hold. This is to be able to hangup + ; a call in the case of a phone disappearing from the net, + ; like a powerloss or grandma tripping over a cable. +;rtpholdtimeout=300 ; Terminate call if 300 seconds of no RTP or RTCP activity + ; on the audio channel + ; when we're on hold (must be > rtptimeout) +;rtpkeepalive=<secs> ; Send keepalives in the RTP stream to keep NAT open + ; (default is off - zero) + +;--------------------------- SIP Session-Timers (RFC 4028)------------------------------------ +; SIP Session-Timers provide an end-to-end keep-alive mechanism for active SIP sessions. +; This mechanism can detect and reclaim SIP channels that do not terminate through normal +; signaling procedures. Session-Timers can be configured globally or at a user/peer level. +; The operation of Session-Timers is driven by the following configuration parameters: +; +; * session-timers - Session-Timers feature operates in the following three modes: +; originate : Request and run session-timers always +; accept : Run session-timers only when requested by other UA +; refuse : Do not run session timers in any case +; The default mode of operation is 'accept'. +; * session-expires - Maximum session refresh interval in seconds. Defaults to 1800 secs. +; * session-minse - Minimum session refresh interval in seconds. Defualts to 90 secs. +; * session-refresher - The session refresher (uac|uas). Defaults to 'uas'. +; +;session-timers=originate +;session-expires=600 +;session-minse=90 +;session-refresher=uas +; +;--------------------------- SIP DEBUGGING --------------------------------------------------- +;sipdebug = yes ; Turn on SIP debugging by default, from + ; the moment the channel loads this configuration +;recordhistory=yes ; Record SIP history by default + ; (see sip history / sip no history) +;dumphistory=yes ; Dump SIP history at end of SIP dialogue + ; SIP history is output to the DEBUG logging channel + + +;--------------------------- STATUS NOTIFICATIONS (SUBSCRIPTIONS) ---------------------------- +; You can subscribe to the status of extensions with a "hint" priority +; (See extensions.conf.sample for examples) +; chan_sip support two major formats for notifications: dialog-info and SIMPLE +; +; You will get more detailed reports (busy etc) if you have a call counter enabled +; for a device. +; +; If you set the busylevel, we will indicate busy when we have a number of calls that +; matches the busylevel treshold. +; +; For queues, you will need this level of detail in status reporting, regardless +; if you use SIP subscriptions. Queues and manager use the same internal interface +; for reading status information. +; +; Note: Subscriptions does not work if you have a realtime dialplan and use the +; realtime switch. +; +;allowsubscribe=no ; Disable support for subscriptions. (Default is yes) +;subscribecontext = default ; Set a specific context for SUBSCRIBE requests + ; Useful to limit subscriptions to local extensions + ; Settable per peer/user also +;notifyringing = no ; Control whether subscriptions already INUSE get sent + ; RINGING when another call is sent (default: yes) +;notifyhold = yes ; Notify subscriptions on HOLD state (default: no) + ; Turning on notifyringing and notifyhold will add a lot + ; more database transactions if you are using realtime. +;notifycid = yes ; Control whether caller ID information is sent along with + ; dialog-info+xml notifications (supported by snom phones). + ; Note that this feature will only work properly when the + ; incoming call is using the same extension and context that + ; is being used as the hint for the called extension. This means + ; that it won't work when using subscribecontext for your sip + ; user or peer (if subscribecontext is different than context). + ; This is also limited to a single caller, meaning that if an + ; extension is ringing because multiple calls are incoming, + ; only one will be used as the source of caller ID. Specify + ; 'ignore-context' to ignore the called context when looking + ; for the caller's channel. The default value is 'no.' Setting + ; notifycid to 'ignore-context' also causes call-pickups attempted + ; via SNOM's NOTIFY mechanism to set the context for the call pickup + ; to PICKUPMARK. +;callcounter = yes ; Enable call counters on devices. This can be set per + ; device too. + +;----------------------------------------- T.38 FAX SUPPORT ---------------------------------- +; +; This setting is available in the [general] section as well as in device configurations. +; Setting this to yes enables T.38 FAX (UDPTL) on SIP calls; it defaults to off. +; +; t38pt_udptl = yes ; Enables T.38 with FEC error correction. +; t38pt_udptl = yes,fec ; Enables T.38 with FEC error correction. +; t38pt_udptl = yes,redundancy ; Enables T.38 with redundancy error correction. +; t38pt_udptl = yes,none ; Enables T.38 with no error correction. +; +; In some cases, T.38 endpoints will provide a T38FaxMaxDatagram value (during T.38 setup) that +; is based on an incorrect interpretation of the T.38 recommendation, and results in failures +; because Asterisk does not believe it can send T.38 packets of a reasonable size to that +; endpoint (Cisco media gateways are one example of this situation). In these cases, during a +; T.38 call you will see warning messages on the console/in the logs from the Asterisk UDPTL +; stack complaining about lack of buffer space to send T.38 FAX packets. If this occurs, you +; can set an override (globally, or on a per-device basis) to make Asterisk ignore the +; T38FaxMaxDatagram value specified by the other endpoint, and use a configured value instead. +; This can be done by appending 'maxdatagram=<value>' to the t38pt_udptl configuration option, +; like this: +; +; t38pt_udptl = yes,fec,maxdatagram=400 ; Enables T.38 with FEC error correction and overrides +; ; the other endpoint's provided value to assume we can +; ; send 400 byte T.38 FAX packets to it. +; +; FAX detection will cause the SIP channel to jump to the 'fax' extension (if it exists) +; based one or more events being detected. The events that can be detected are an incoming +; CNG tone or an incoming T.38 re-INVITE request. +; +; faxdetect = yes ; Default 'no', 'yes' enables both CNG and T.38 detection +; faxdetect = cng ; Enables only CNG detection +; faxdetect = t38 ; Enables only T.38 detection +; +;----------------------------------------- OUTBOUND SIP REGISTRATIONS ------------------------ +; Asterisk can register as a SIP user agent to a SIP proxy (provider) +; Format for the register statement is: +; register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] +; +; +; +; domain is either +; - domain in DNS +; - host name in DNS +; - the name of a peer defined below or in realtime +; The domain is where you register your username, so your SIP uri you are registering to +; is username@domain +; +; If no extension is given, the 's' extension is used. The extension needs to +; be defined in extensions.conf to be able to accept calls from this SIP proxy +; (provider). +; +; A similar effect can be achieved by adding a "callbackextension" option in a peer section. +; this is equivalent to having the following line in the general section: +; +; register => username:secret@host/callbackextension +; +; and more readable because you don't have to write the parameters in two places +; (note that the "port" is ignored - this is a bug that should be fixed). +; +; Note that a register= line doesn't mean that we will match the incoming call in any +; other way than described above. If you want to control where the call enters your +; dialplan, which context, you want to define a peer with the hostname of the provider's +; server. If the provider has multiple servers to place calls to your system, you need +; a peer for each server. +; +; Beginning with Asterisk version 1.6.2, the "user" portion of the register line may +; contain a port number. Since the logical separator between a host and port number is a +; ':' character, and this character is already used to separate between the optional "secret" +; and "authuser" portions of the line, there is a bit of a hoop to jump through if you wish +; to use a port here. That is, you must explicitly provide a "secret" and "authuser" even if +; they are blank. See the third example below for an illustration. +; +; +; Examples: +; +;register => 1234:password@mysipprovider.com +; +; This will pass incoming calls to the 's' extension +; +; +;register => 2345:password@sip_proxy/1234 +; +; Register 2345 at sip provider 'sip_proxy'. Calls from this provider +; connect to local extension 1234 in extensions.conf, default context, +; unless you configure a [sip_proxy] section below, and configure a +; context. +; Tip 1: Avoid assigning hostname to a sip.conf section like [provider.com] +; Tip 2: Use separate inbound and outbound sections for SIP providers +; (instead of type=friend) if you have calls in both directions +; +;register => 3456@mydomain:5082::@mysipprovider.com +; +; Note that in this example, the optional authuser and secret portions have +; been left blank because we have specified a port in the user section +; +;register => tls://username:xxxxxx@sip-tls-proxy.example.org +; +; The 'transport' part defaults to 'udp' but may also be 'tcp' or 'tls'. +; Using 'udp://' explicitly is also useful in case the username part +; contains a '/' ('user/name'). + +;registertimeout=20 ; retry registration calls every 20 seconds (default) +;registerattempts=10 ; Number of registration attempts before we give up + ; 0 = continue forever, hammering the other server + ; until it accepts the registration + ; Default is 0 tries, continue forever + +;----------------------------------------- OUTBOUND MWI SUBSCRIPTIONS ------------------------- +; Asterisk can subscribe to receive the MWI from another SIP server and store it locally for retrieval +; by other phones. At this time, you can only subscribe using UDP as the transport. +; Format for the mwi register statement is: +; mwi => user[:secret[:authuser]]@host[:port]/mailbox +; +; Examples: +;mwi => 1234:password@mysipprovider.com/1234 +;mwi => 1234:password@myportprovider.com:6969/1234 +;mwi => 1234:password:authuser@myauthprovider.com/1234 +;mwi => 1234:password:authuser@myauthportprovider.com:6969/1234 +; +; MWI received will be stored in the 1234 mailbox of the SIP_Remote context. It can be used by other phones by following the below: +; mailbox=1234@SIP_Remote +;----------------------------------------- NAT SUPPORT ------------------------ +; +; WARNING: SIP operation behind a NAT is tricky and you really need +; to read and understand well the following section. +; +; When Asterisk is behind a NAT device, the "local" address (and port) that +; a socket is bound to has different values when seen from the inside or +; from the outside of the NATted network. Unfortunately this address must +; be communicated to the outside (e.g. in SIP and SDP messages), and in +; order to determine the correct value Asterisk needs to know: +; +; + whether it is talking to someone "inside" or "outside" of the NATted network. +; This is configured by assigning the "localnet" parameter with a list +; of network addresses that are considered "inside" of the NATted network. +; IF LOCALNET IS NOT SET, THE EXTERNAL ADDRESS WILL NOT BE SET CORRECTLY. +; Multiple entries are allowed, e.g. a reasonable set is the following: +; +; localnet=192.168.0.0/255.255.0.0 ; RFC 1918 addresses +; localnet=10.0.0.0/255.0.0.0 ; Also RFC1918 +; localnet=172.16.0.0/12 ; Another RFC1918 with CIDR notation +; localnet=169.254.0.0/255.255.0.0 ; Zero conf local network +; +; + the "externally visible" address and port number to be used when talking +; to a host outside the NAT. This information is derived by one of the +; following (mutually exclusive) config file parameters: +; +; a. "externaddr = hostname[:port]" specifies a static address[:port] to +; be used in SIP and SDP messages. +; The hostname is looked up only once, when [re]loading sip.conf . +; If a port number is not present, use the port specified in the "udpbindaddr" +; (which is not guaranteed to work correctly, because a NAT box might remap the +; port number as well as the address). +; This approach can be useful if you have a NAT device where you can +; configure the mapping statically. Examples: +; +; externaddr = 12.34.56.78 ; use this address. +; externaddr = 12.34.56.78:9900 ; use this address and port. +; externaddr = mynat.my.org:12600 ; Public address of my nat box. +; externtcpport = 9900 ; The externally mapped tcp port, when Asterisk is behind a static NAT or PAT. +; ; externtcpport will default to the externaddr or externhost port if either one is set. +; externtlsport = 12600 ; The externally mapped tls port, when Asterisk is behind a static NAT or PAT. +; ; externtlsport port will default to the RFC designated port of 5061. +; +; b. "externhost = hostname[:port]" is similar to "externaddr" except +; that the hostname is looked up every "externrefresh" seconds +; (default 10s). This can be useful when your NAT device lets you choose +; the port mapping, but the IP address is dynamic. +; Beware, you might suffer from service disruption when the name server +; resolution fails. Examples: +; +; externhost=foo.dyndns.net ; refreshed periodically +; externrefresh=180 ; change the refresh interval +; +; Note that at the moment all these mechanism work only for the SIP socket. +; The IP address discovered with externaddr/externhost is reused for +; media sessions as well, but the port numbers are not remapped so you +; may still experience problems. +; +; NOTE 1: in some cases, NAT boxes will use different port numbers in +; the internal<->external mapping. In these cases, the "externaddr" and +; "externhost" might not help you configure addresses properly. +; +; NOTE 2: when using "externaddr" or "externhost", the address part is +; also used as the external address for media sessions. Thus, the port +; information in the SDP may be wrong! +; +; In addition to the above, Asterisk has an additional "nat" parameter to +; address NAT-related issues in incoming SIP or media sessions. +; In particular, depending on the 'nat= ' settings described below, Asterisk +; may override the address/port information specified in the SIP/SDP messages, +; and use the information (sender address) supplied by the network stack instead. +; However, this is only useful if the external traffic can reach us. +; The following settings are allowed (both globally and in individual sections): +; +; nat = no ; Default. Use rport if the remote side says to use it. +; nat = force_rport ; Force rport to always be on. +; nat = yes ; Force rport to always be on and perform comedia RTP handling. +; nat = comedia ; Use rport if the remote side says to use it and perform comedia RTP handling. +; +; 'comedia RTP handling' refers to the technique of sending RTP to the port that the +; the other endpoint's RTP arrived from, and means 'connection-oriented media'. This is +; only partially related to RFC 4145 which was referred to as COMEDIA while it was in +; draft form. This method is used to accomodate endpoints that may be located behind +; NAT devices, and as such the port number they tell Asterisk to send RTP packets to +; for their media streams is not actual port number that will be used on the nearer +; side of the NAT. +; +; In addition to these settings, Asterisk *always* uses 'symmetric RTP' mode as defined by +; RFC 4961; Asterisk will always send RTP packets from the same port number it expects +; to receive them on. +; +; The IP address used for media (audio, video, and text) in the SDP can also be overridden by using +; the media_address configuration option. This is only applicable to the general section and +; can not be set per-user or per-peer. +; +; media_address = 172.16.42.1 +; +; Through the use of the res_stun_monitor module, Asterisk has the ability to detect when the +; perceived external network address has changed. When the stun_monitor is installed and +; configured, chan_sip will renew all outbound registrations when the monitor detects any sort +; of network change has occurred. By default this option is enabled, but only takes effect once +; res_stun_monitor is configured. If res_stun_monitor is enabled and you wish to not +; generate all outbound registrations on a network change, use the option below to disable +; this feature. +; +; subscribe_network_change_event = yes ; on by default + +;----------------------------------- MEDIA HANDLING -------------------------------- +; By default, Asterisk tries to re-invite media streams to an optimal path. If there's +; no reason for Asterisk to stay in the media path, the media will be redirected. +; This does not really work well in the case where Asterisk is outside and the +; clients are on the inside of a NAT. In that case, you want to set directmedia=nonat. +; +;directmedia=yes ; Asterisk by default tries to redirect the + ; RTP media stream to go directly from + ; the caller to the callee. Some devices do not + ; support this (especially if one of them is behind a NAT). + ; The default setting is YES. If you have all clients + ; behind a NAT, or for some other reason want Asterisk to + ; stay in the audio path, you may want to turn this off. + + ; This setting also affect direct RTP + ; at call setup (a new feature in 1.4 - setting up the + ; call directly between the endpoints instead of sending + ; a re-INVITE). + + ; Additionally this option does not disable all reINVITE operations. + ; It only controls Asterisk generating reINVITEs for the specific + ; purpose of setting up a direct media path. If a reINVITE is + ; needed to switch a media stream to inactive (when placed on + ; hold) or to T.38, it will still be done, regardless of this + ; setting. Note that direct T.38 is not supported. + +;directmedia=nonat ; An additional option is to allow media path redirection + ; (reinvite) but only when the peer where the media is being + ; sent is known to not be behind a NAT (as the RTP core can + ; determine it based on the apparent IP address the media + ; arrives from). + +;directmedia=update ; Yet a third option... use UPDATE for media path redirection, + ; instead of INVITE. This can be combined with 'nonat', as + ; 'directmedia=update,nonat'. It implies 'yes'. + +;directrtpsetup=yes ; Enable the new experimental direct RTP setup. This sets up + ; the call directly with media peer-2-peer without re-invites. + ; Will not work for video and cases where the callee sends + ; RTP payloads and fmtp headers in the 200 OK that does not match the + ; callers INVITE. This will also fail if directmedia is enabled when + ; the device is actually behind NAT. + +;directmediadeny=0.0.0.0/0 ; Use directmediapermit and directmediadeny to restrict +;directmediapermit=172.16.0.0/16; which peers should be able to pass directmedia to each other + ; (There is no default setting, this is just an example) + ; Use this if some of your phones are on IP addresses that + ; can not reach each other directly. This way you can force + ; RTP to always flow through asterisk in such cases. + +;ignoresdpversion=yes ; By default, Asterisk will honor the session version + ; number in SDP packets and will only modify the SDP + ; session if the version number changes. This option will + ; force asterisk to ignore the SDP session version number + ; and treat all SDP data as new data. This is required + ; for devices that send us non standard SDP packets + ; (observed with Microsoft OCS). By default this option is + ; off. + +;sdpsession=Asterisk PBX ; Allows you to change the SDP session name string, (s=) + ; Like the useragent parameter, the default user agent string + ; also contains the Asterisk version. +;sdpowner=root ; Allows you to change the username field in the SDP owner string, (o=) + ; This field MUST NOT contain spaces +;encryption=no ; Whether to offer SRTP encrypted media (and only SRTP encrypted media) + ; on outgoing calls to a peer. Calls will fail with HANGUPCAUSE=58 if + ; the peer does not support SRTP. Defaults to no. + +;----------------------------------------- REALTIME SUPPORT ------------------------ +; For additional information on ARA, the Asterisk Realtime Architecture, +; please read https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration +; +;rtcachefriends=yes ; Cache realtime friends by adding them to the internal list + ; just like friends added from the config file only on a + ; as-needed basis? (yes|no) + +;rtsavesysname=yes ; Save systemname in realtime database at registration + ; Default= no + +;rtupdate=yes ; Send registry updates to database using realtime? (yes|no) + ; If set to yes, when a SIP UA registers successfully, the ip address, + ; the origination port, the registration period, and the username of + ; the UA will be set to database via realtime. + ; If not present, defaults to 'yes'. Note: realtime peers will + ; probably not function across reloads in the way that you expect, if + ; you turn this option off. +;rtautoclear=yes ; Auto-Expire friends created on the fly on the same schedule + ; as if it had just registered? (yes|no|<seconds>) + ; If set to yes, when the registration expires, the friend will + ; vanish from the configuration until requested again. If set + ; to an integer, friends expire within this number of seconds + ; instead of the registration interval. + +;ignoreregexpire=yes ; Enabling this setting has two functions: + ; + ; For non-realtime peers, when their registration expires, the + ; information will _not_ be removed from memory or the Asterisk database + ; if you attempt to place a call to the peer, the existing information + ; will be used in spite of it having expired + ; + ; For realtime peers, when the peer is retrieved from realtime storage, + ; the registration information will be used regardless of whether + ; it has expired or not; if it expires while the realtime peer + ; is still in memory (due to caching or other reasons), the + ; information will not be removed from realtime storage + +;----------------------------------------- SIP DOMAIN SUPPORT ------------------------ +; Incoming INVITE and REFER messages can be matched against a list of 'allowed' +; domains, each of which can direct the call to a specific context if desired. +; By default, all domains are accepted and sent to the default context or the +; context associated with the user/peer placing the call. +; REGISTER to non-local domains will be automatically denied if a domain +; list is configured. +; +; Domains can be specified using: +; domain=<domain>[,<context>] +; Examples: +; domain=myasterisk.dom +; domain=customer.com,customer-context +; +; In addition, all the 'default' domains associated with a server should be +; added if incoming request filtering is desired. +; autodomain=yes +; +; To disallow requests for domains not serviced by this server: +; allowexternaldomains=no + +;domain=mydomain.tld,mydomain-incoming + ; Add domain and configure incoming context + ; for external calls to this domain +;domain=1.2.3.4 ; Add IP address as local domain + ; You can have several "domain" settings +;allowexternaldomains=no ; Disable INVITE and REFER to non-local domains + ; Default is yes +;autodomain=yes ; Turn this on to have Asterisk add local host + ; name and local IP to domain list. + +; fromdomain=mydomain.tld ; When making outbound SIP INVITEs to + ; non-peers, use your primary domain "identity" + ; for From: headers instead of just your IP + ; address. This is to be polite and + ; it may be a mandatory requirement for some + ; destinations which do not have a prior + ; account relationship with your server. + +;------------------------------ Advice of Charge CONFIGURATION -------------------------- +; snom_aoc_enabled = yes; ; This options turns on and off support for sending AOC-D and + ; AOC-E to snom endpoints. This option can be used both in the + ; peer and global scope. The default for this option is off. + + +;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a + ; SIP channel. Defaults to "no". An enabled jitterbuffer will + ; be used only if the sending side can create and the receiving + ; side can not accept jitter. The SIP channel can accept jitter, + ; thus a jitterbuffer on the receive SIP side will be used only + ; if it is forced and enabled. + +; jbforce = no ; Forces the use of a jitterbuffer on the receive side of a SIP + ; channel. Defaults to "no". + +; jbmaxsize = 200 ; Max length of the jitterbuffer in milliseconds. + +; jbresyncthreshold = 1000 ; Jump in the frame timestamps over which the jitterbuffer is + ; resynchronized. Useful to improve the quality of the voice, with + ; big jumps in/broken timestamps, usually sent from exotic devices + ; and programs. Defaults to 1000. + +; jbimpl = fixed ; Jitterbuffer implementation, used on the receiving side of a SIP + ; channel. Two implementations are currently available - "fixed" + ; (with size always equals to jbmaxsize) and "adaptive" (with + ; variable size, actually the new jb of IAX2). Defaults to fixed. + +; jbtargetextra = 40 ; This option only affects the jb when 'jbimpl = adaptive' is set. + ; The option represents the number of milliseconds by which the new jitter buffer + ; will pad its size. the default is 40, so without modification, the new + ; jitter buffer will set its size to the jitter value plus 40 milliseconds. + ; increasing this value may help if your network normally has low jitter, + ; but occasionally has spikes. + +; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". +;----------------------------------------------------------------------------------- + +[authentication] +; Global credentials for outbound calls, i.e. when a proxy challenges your +; Asterisk server for authentication. These credentials override +; any credentials in peer/register definition if realm is matched. +; +; This way, Asterisk can authenticate for outbound calls to other +; realms. We match realm on the proxy challenge and pick an set of +; credentials from this list +; Syntax: +; auth = <user>:<secret>@<realm> +; auth = <user>#<md5secret>@<realm> +; Example: +;auth=mark:topsecret@digium.com +; +; You may also add auth= statements to [peer] definitions +; Peer auth= override all other authentication settings if we match on realm + +;------------------------------------------------------------------------------ +; DEVICE CONFIGURATION +; +; The SIP channel has two types of devices, the friend and the peer. +; * The type=friend is a device type that accepts both incoming and outbound calls, +; where Asterisk match on the From: username on incoming calls. +; (A synonym for friend is "user"). This is a type you use for your local +; SIP phones. +; * The type=peer also handles both incoming and outbound calls. On inbound calls, +; Asterisk only matches on IP/port, not on names. This is mostly used for SIP +; trunks. +; +; For device names, we recommend using only a-z, numerics (0-9) and underscore +; +; For local phones, type=friend works most of the time +; +; If you have one-way audio, you probably have NAT problems. +; If Asterisk is on a public IP, and the phone is inside of a NAT device +; you will need to configure nat option for those phones. +; Also, turn on qualify=yes to keep the nat session open +; +; Configuration options available +; -------------------- +; context +; callingpres +; permit +; deny +; secret +; md5secret +; remotesecret +; transport +; dtmfmode +; directmedia +; nat +; callgroup +; pickupgroup +; language +; allow +; disallow +; insecure +; trustrpid +; progressinband +; promiscredir +; useclientcode +; accountcode +; setvar +; callerid +; amaflags +; callcounter +; busylevel +; allowoverlap +; allowsubscribe +; allowtransfer +; ignoresdpversion +; subscribecontext +; template +; videosupport +; maxcallbitrate +; rfc2833compensate +; mailbox +; session-timers +; session-expires +; session-minse +; session-refresher +; t38pt_usertpsource +; regexten +; fromdomain +; fromuser +; host +; port +; qualify +; defaultip +; defaultuser +; rtptimeout +; rtpholdtimeout +; sendrpid +; outboundproxy +; rfc2833compensate +; callbackextension +; registertrying +; timert1 +; timerb +; qualifyfreq +; t38pt_usertpsource +; contactpermit ; Limit what a host may register as (a neat trick +; contactdeny ; is to register at the same IP as a SIP provider, +; ; then call oneself, and get redirected to that +; ; same location). +; directmediapermit +; directmediadeny +; unsolicited_mailbox +; use_q850_reason +; maxforwards +; encryption + +;[sip_proxy] +; For incoming calls only. Example: FWD (Free World Dialup) +; We match on IP address of the proxy for incoming calls +; since we can not match on username (caller id) +;type=peer +;context=from-fwd +;host=fwd.pulver.com + +;[sip_proxy-out] +;type=peer ; we only want to call out, not be called +;remotesecret=guessit ; Our password to their service +;defaultuser=yourusername ; Authentication user for outbound proxies +;fromuser=yourusername ; Many SIP providers require this! +;fromdomain=provider.sip.domain +;host=box.provider.com +;transport=udp,tcp ; This sets the default transport type to udp for outgoing, and will +; ; accept both tcp and udp. The default transport type is only used for +; ; outbound messages until a Registration takes place. During the +; ; peer Registration the transport type may change to another supported +; ; type if the peer requests so. + +;usereqphone=yes ; This provider requires ";user=phone" on URI +;callcounter=yes ; Enable call counter +;busylevel=2 ; Signal busy at 2 or more calls +;outboundproxy=proxy.provider.domain ; send outbound signaling to this proxy, not directly to the peer +;port=80 ; The port number we want to connect to on the remote side + ; Also used as "defaultport" in combination with "defaultip" settings + +;--- sample definition for a provider +;[provider1] +;type=peer +;host=sip.provider1.com +;fromuser=4015552299 ; how your provider knows you +;remotesecret=youwillneverguessit ; The password we use to authenticate to them +;secret=gissadetdu ; The password they use to contact us +;callbackextension=123 ; Register with this server and require calls coming back to this extension +;transport=udp,tcp ; This sets the transport type to udp for outgoing, and will +; ; accept both tcp and udp. Default is udp. The first transport +; ; listed will always be used for outgoing connections. +;unsolicited_mailbox=4015552299 ; If the remote SIP server sends an unsolicited MWI NOTIFY message the new/old +; ; message count will be stored in the configured virtual mailbox. It can be used +; ; by any device supporting MWI by specifying <configured value>@SIP_Remote as the +; ; mailbox. + +; +; Because you might have a large number of similar sections, it is generally +; convenient to use templates for the common parameters, and add them +; the the various sections. Examples are below, and we can even leave +; the templates uncommented as they will not harm: + +[basic-options](!) ; a template + dtmfmode=rfc2833 + context=from-office + type=friend + +[natted-phone](!,basic-options) ; another template inheriting basic-options + nat=yes + directmedia=no + host=dynamic + +[public-phone](!,basic-options) ; another template inheriting basic-options + nat=no + directmedia=yes + +[my-codecs](!) ; a template for my preferred codecs + disallow=all + allow=ilbc + allow=g729 + allow=gsm + allow=g723 + allow=ulaw + +[ulaw-phone](!) ; and another one for ulaw-only + disallow=all + allow=ulaw + +; and finally instantiate a few phones +; +; [2133](natted-phone,my-codecs) +; secret = peekaboo +; [2134](natted-phone,ulaw-phone) +; secret = not_very_secret +; [2136](public-phone,ulaw-phone) +; secret = not_very_secret_either +; ... +; + +; Standard configurations not using templates look like this: +; +;[grandstream1] +;type=friend +;context=from-sip ; Where to start in the dialplan when this phone calls +;callerid=John Doe <1234> ; Full caller ID, to override the phones config + ; on incoming calls to Asterisk +;host=192.168.0.23 ; we have a static but private IP address + ; No registration allowed +;nat=no ; there is not NAT between phone and Asterisk +;directmedia=yes ; allow RTP voice traffic to bypass Asterisk +;dtmfmode=info ; either RFC2833 or INFO for the BudgeTone +;call-limit=1 ; permit only 1 outgoing call and 1 incoming call at a time + ; from the phone to asterisk (deprecated) + ; 1 for the explicit peer, 1 for the explicit user, + ; remember that a friend equals 1 peer and 1 user in + ; memory + ; There is no combined call counter for a "friend" + ; so there's currently no way in sip.conf to limit + ; to one inbound or outbound call per phone. Use + ; the group counters in the dial plan for that. + ; +;mailbox=1234@default ; mailbox 1234 in voicemail context "default" +;disallow=all ; need to disallow=all before we can use allow= +;allow=ulaw ; Note: In user sections the order of codecs + ; listed with allow= does NOT matter! +;allow=alaw +;allow=g723.1 ; Asterisk only supports g723.1 pass-thru! +;allow=g729 ; Pass-thru only unless g729 license obtained +;callingpres=allowed_passed_screen ; Set caller ID presentation + ; See README.callingpres for more information + +;[xlite1] +; Turn off silence suppression in X-Lite ("Transmit Silence"=YES)! +; Note that Xlite sends NAT keep-alive packets, so qualify=yes is not needed +;type=friend +;regexten=1234 ; When they register, create extension 1234 +;callerid="Jane Smith" <5678> +;host=dynamic ; This device needs to register +;nat=yes ; X-Lite is behind a NAT router +;directmedia=no ; Typically set to NO if behind NAT +;disallow=all +;allow=gsm ; GSM consumes far less bandwidth than ulaw +;allow=ulaw +;allow=alaw +;mailbox=1234@default,1233@default ; Subscribe to status of multiple mailboxes +;registertrying=yes ; Send a 100 Trying when the device registers. + +;[snom] +;type=friend ; Friends place calls and receive calls +;context=from-sip ; Context for incoming calls from this user +;secret=blah +;subscribecontext=localextensions ; Only allow SUBSCRIBE for local extensions +;language=de ; Use German prompts for this user +;host=dynamic ; This peer register with us +;dtmfmode=inband ; Choices are inband, rfc2833, or info +;defaultip=192.168.0.59 ; IP used until peer registers +;mailbox=1234@context,2345 ; Mailbox(-es) for message waiting indicator +;subscribemwi=yes ; Only send notifications if this phone + ; subscribes for mailbox notification +;vmexten=voicemail ; dialplan extension to reach mailbox + ; sets the Message-Account in the MWI notify message + ; defaults to global vmexten which defaults to "asterisk" +;disallow=all +;allow=ulaw ; dtmfmode=inband only works with ulaw or alaw! + + +;[polycom] +;type=friend ; Friends place calls and receive calls +;context=from-sip ; Context for incoming calls from this user +;secret=blahpoly +;host=dynamic ; This peer register with us +;dtmfmode=rfc2833 ; Choices are inband, rfc2833, or info +;defaultuser=polly ; Username to use in INVITE until peer registers +;defaultip=192.168.40.123 + ; Normally you do NOT need to set this parameter +;disallow=all +;allow=ulaw ; dtmfmode=inband only works with ulaw or alaw! +;progressinband=no ; Polycom phones don't work properly with "never" + + +;[pingtel] +;type=friend +;secret=blah +;host=dynamic +;insecure=port ; Allow matching of peer by IP address without + ; matching port number +;insecure=invite ; Do not require authentication of incoming INVITEs +;insecure=port,invite ; (both) +;qualify=1000 ; Consider it down if it's 1 second to reply + ; Helps with NAT session + ; qualify=yes uses default value +;qualifyfreq=60 ; Qualification: How often to check for the + ; host to be up in seconds + ; Set to low value if you use low timeout for + ; NAT of UDP sessions +; +; Call group and Pickup group should be in the range from 0 to 63 +; +;callgroup=1,3-4 ; We are in caller groups 1,3,4 +;pickupgroup=1,3-5 ; We can do call pick-p for call group 1,3,4,5 +;defaultip=192.168.0.60 ; IP address to use if peer has not registered +;deny=0.0.0.0/0.0.0.0 ; ACL: Control access to this account based on IP address +;permit=192.168.0.60/255.255.255.0 +;permit=192.168.0.60/24 ; we can also use CIDR notation for subnet masks +;permit=2001:db8::/32 ; IPv6 ACLs can be specified if desired. IPv6 ACLs + ; apply only to IPv6 addresses, and IPv4 ACLs apply + ; only to IPv4 addresses. + +;[cisco1] +;type=friend +;secret=blah +;qualify=200 ; Qualify peer is no more than 200ms away +;nat=yes ; This phone may be natted + ; Send SIP and RTP to the IP address that packet is + ; received from instead of trusting SIP headers +;host=dynamic ; This device registers with us +;directmedia=no ; Asterisk by default tries to redirect the + ; RTP media stream (audio) to go directly from + ; the caller to the callee. Some devices do not + ; support this (especially if one of them is + ; behind a NAT). +;defaultip=192.168.0.4 ; IP address to use until registration +;defaultuser=goran ; Username to use when calling this device before registration + ; Normally you do NOT need to set this parameter +;setvar=CUSTID=5678 ; Channel variable to be set for all calls from or to this device +;setvar=ATTENDED_TRANSFER_COMPLETE_SOUND=beep ; This channel variable will + ; cause the given audio file to + ; be played upon completion of + ; an attended transfer. + +;[pre14-asterisk] +;type=friend +;secret=digium +;host=dynamic +;rfc2833compensate=yes ; Compensate for pre-1.4 DTMF transmission from another Asterisk machine. + ; You must have this turned on or DTMF reception will work improperly. +;t38pt_usertpsource=yes ; Use the source IP address of RTP as the destination IP address for UDPTL packets + ; if the nat option is enabled. If a single RTP packet is received Asterisk will know the + ; external IP address of the remote device. If port forwarding is done at the client side + ; then UDPTL will flow to the remote device. + +[100] +type=friend +host=dynamic +username=100 +secret=password +canreinvite=no +allow=all + +[200] +type=friend +host=dynamic +username=200 +secret=password +canreinvite=no +allow=all + +[300] +type=friend +host=dynamic +username=300 +canreinvite=no +allow=all + +[400] +type=friend +host=dynamic +username=400 +canreinvite=no +allow=all + +[testphone1] +context=default +type=friend +secret=savoirfairelinux +host=dynamic +insecure=invite,port +dtmfmode=rfc2833 +transport=tls +allow=all +nat=yes diff --git a/tools/build-system/launch-build-machine-2.sh b/tools/build-system/launch-build-machine-2.sh index 8202380ff7754bd209bf1afe7eb26f97a279b244..b6d2de706818a461bfa8a963707c32138768ea21 100755 --- a/tools/build-system/launch-build-machine-2.sh +++ b/tools/build-system/launch-build-machine-2.sh @@ -22,7 +22,7 @@ DO_LOGGING=1 DO_UPLOAD=1 SNAPSHOT_TAG=`date +%Y%m%d` TAG_NAME_PREFIX= -VERSION_NUMBER="1.0.2" +VERSION_NUMBER="1.1.0" LAUNCHPAD_PACKAGES=( "sflphone-client-gnome" "sflphone-common" "sflphone-plugins") diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/changelog b/tools/build-system/launchpad/sflphone-client-kde/debian/changelog index 4f977e142e383b15914b1bfc7dd7b0904e7e4cf2..68d02ba2a23af7beb17d6fb259e63431080d7668 100644 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/changelog +++ b/tools/build-system/launchpad/sflphone-client-kde/debian/changelog @@ -1,3105 +1,11 @@ -sflphone-client-kde (1.0.0-rc20110930~ppa1~SYSTEM) SYSTEM; urgency=low +sflphone-client-kde (1.1) unstable; urgency=low - ** SNAPSHOT 1.0.0-rc20110930~ppa1~SYSTEM ** + * KDE client now work with sflphone-daemon 1.1 + * Improved contact integration + * Improved history + * Attended transfer support + * Improved libraries (under the hood) + * Configuration cleanup + * Tons of bug fixes - * update kde .gitignore - * Fix bug in volume widget - * More polishing for release - * Bump version to 1.0.0 - * [#7023] Add the ability to load an abstract contact backend in the - library to resolve more data, polish code - * [#7021] More cleanup for release - * Cleanup - * [#7021] Refactor KDE client dbus handling, add a missing call in - daemon and port the DataEngine to the new API - * Remove some annoying debug - * merge language scripts - * remove obsolete 'VERSION' files - * update install instructions - * Add missing translations to gnome - * language update - * Revert "Don't reference count DBus clients, exit core immediately - when one of them request it" - * Don't reference count DBus clients, exit core immediately when one - of them request it - * [7021] Add contact abstraction support - * [#7121] Polishing library (over). Indentation, spacing and naming - are now consistent - * codecs: link to libccrtp, don't use logger - * Fix a daemon bug - * [#7038] Fix adding contact - * * #7037 : stop audio stream after all calls have been hanged up - * [#7025] Add full support for bookmark - * SFLPhone KDE do not destroy history anymore - * Fix config skeleton - * Close the daemon once and for all, no more automatic respawning - * Fix "unregistered account" bug (I hope so) - * Close SFLPhone at the right place, it still respawn, I don't know - why - * Remove dead code - * Fix regressions introduced in the last commit - * Dead code elimination 1/3 - * Fix bug, add "add contact" option, fix warning - * * #7019: Fix IAX codec negociation - * Remove or comment unnecessary/unhelpful debug output - * Fix "same as local" account setting, fix IP2IP LED color - * Add support for some more advanced config options and add missing - config dialog icons - * Fix crash with noise suppressor - * Alternative can now be selected from the call view context menu - * Add drag and drop support, initial context menu and fix 3 bugs in - the account dialog - * Add basic history drag and drop support - * Complete contact support is back - * * #6991 : fix IAX problems - * Fix IAX accounts being disabled by default - * Revert "deb: forge -g flags for pjsip" - * * #5884: Disable debug code in pjsip - * echo suppressor : more assertions - * Don't let the daemon think crypto is enabled when it's not - * Simplify ToneList - * Some progress on contact support - * Remove unused getRegistrationCount() - * remove annoying debug - * revert SIP bit of e27e5c39bad27bae28f574eb2cba7717e8956229 - * Simplify CallManager::placeCallFirstAccount - * Fix crash on hold - * * #6905 : SIP refactor - * gnome client: be sure key exchange is set correctly - * Move code into createSipTransport - * Fix account registration on start - * ManagerImpl::registerAccounts(): simplify - * * #5884: don't mess with pjsip threads in echo suppressor - * * #6905 : simplify udp/stun/tls pjsip transport creation - * Restore and improve support for Call history - * fix launchpad build - * SIPVoIPLink: simplify / refactor - * Fix libwidget linking - * SIP: simplify - * IM : simplify - * gnome: remove some debug - * AudioRtpFactory::stop() cannot fail - * * #6905: simplify SIP code - * pjlib: fix build without SSLv2, fix warnings - * Port history to the new syntax - * Test a dock widget based implementation for contact and history - * Disable SSLv2 support from pjsip and sflphone - * deb: forge -g flags for pjsip - * Fix deb packaging to get debug symbols - * remove debug - * pjproject: update to last stable release (1.10) - * Require gtk >= 2.20 and glib >= 2.24 - * tlsadvanceddialog: simplify - * * #6902 : fix errors spotted by -DGSEAL_ENABLE - * Update daemon dbus XML and port KDE config backend from dbus to - local - * Remove unused but set variables - * * #6929 : fix IM widget, cleanup - * Unconditionally enable debug symbols - * Should fix many KDE issues - * * #6886 : hitting backspace on empty number have no side effects - * * #6905 : fix AudioCodecFactory access in optimized builds (-O > 0) - * Remove unsupported and broken jaunty/karmic packages - * * #6902 : avoid using some gtk deprecated functions - * Update dbus introspection files - * * #6904: removed unused contactmanager - * * #6903 : use correct dbus-cxx package name - * * #6902: don't use individual gtk headers - * Fix a segfault when config is not present - * Merge latest (0.9.13) KDE code. This version is not yet ready for - git master, but better than the previous one - * addressbook : simplify - * * #5659 : sflphone-plugins doesn't depend on libedataserverui - * * #5659 : addressbook doesn't use libedataserverui - * gnome client doesn't depend on evolution - * * #5695: addressbook: simplify - * * #5695: addressbook : remove AddrBookHandle from plugin - * * #5695 : addressbook : remove unused stuff in the client - * * #5695 : addressbook : remove unused stuff, use static mutex - * gnome client doesn't use evolution - * gnome: use proper API to set GTK_CAN_FOCUS - * * #6897: removed unused focus state vars/callbacks - * gnome: fix calls to sflphone_fill_codec_list_per_account - * * #6623: gnome: don't leak in mainwindow - * gnome: mainwindow whitespace cleanup - * gnome: actions.c parameter doesn't have to be a double pointer - * * #6895: fix memleaks, cleanup in accountconfigdialog - * * #6893: fixes segfault in client on clean history - * * #6894: fix leaks, cleanup in sflnotify - * daemon: fixed prints in main - * * #6892: simplify, fix leaks in dialpad - * * #6887: audiopreference creates audio layer - * * #6660: use const char * const, not std::string for globally - visible constants - * * #6852: Preferences now solely responsible for audiolayer creation. - * * #6860: refactor uimanager, also fixes #6865 - * * #6853: hangup as soon as all digits have been deleted - * * #6852: alsa: retry if device is busy - * * #6852: audiolayer creation depends only on preference.audioApi - * * #6850: gnome: fix build for gtk < 2.22.0 - * cleanup in iax - * alsa: typo - * pulse: if we can't peek in audio input, we can't drop samples - * * #6849: show error window if codecs are missing, instead of dying - * EchoCancel: unused, remove - * * #6629 : use number of samples as arguments for audio filters - * * #6629 : remove unused Algorithm interface - * * #6629 : use helper to call alsa functions and display error msgs - * Remove unused type - * * #6841: fix some error handling - * * #6629: simplify AlsaLayer::alsa_set_params() - * Get gdk key definition from header - * * #6828: Replace raw key codes by gdk defines - * remove some debug, enhance some other - * mainbuffer: simplify - * * #6561 : fix phantom call after transfer - * Conference Participant set : simplify - * SIPCall: remove unused functions, make invite session public - * * #6229 : remove malloc/free from pulse audio loop - * * #6629 : simplify pulse callbacks - * * #6629 - * Simplify widgets - * * #6629 : keep the correct audio module when frequency changes - * * #6751: fixed erroneous debug msgs - * callable_obj.h: removed unneeded pthread header - * alsalayer: cleanup - * * #6629: Always restart audio driver when changing parameters (ALSA - only) - * gnome GUI: don't block in DBus signal errorAlert() - * * #6629 : simplify AudioLayer creation - * * #6629 : remove unused and unconfigurable frameSize from audiolayer - * * #6629 : remove unused error message from audio layer - * Fix logic error when switching audio API - * Remove unused AudioProcessing class - * AudioRtpRecordHandler::initNoiseSuppress() : use noiseSuppress - directly - * * #6629 : use DC blocker directly in audio layers - * * #6629 : clean AudioLayer - * * #6629 : don't store mainbuffer inside audiolayer - * * #6629 : correct AudioLayer::notifyincomingCall() - * * #6554: cleanup, refactoring in sipvoiplink - * * #6554: cleanup in iaxvoiplink - * * #6554: throw exception in getSIPCall if pointer is NULL - * * #6554: make some methods of sipvoiplink static - * * #6655: cleanup in managerimpl - * * #6554: refactoring, fix memleaks in sipvoiplink - * * #6478: remove throw specs, cleanup in voiplink - * * #6629 : remove unused AudioDevice - * * #6655: removed more dependencies from managerimpl - * * #6744: simplified numbercleaner - * conference : remove one prototype - * * #6743: fix ip2ip - * Don't give glib warnings if icons are not found - * gnome: fixed includes - * Codec.h: removed unused function - * * #6742 : clean dbus & icons - * * #6699: refactor/cleanup accounts - * icons: cleanup - * timer : use second precision, not millisecond - * calltree_update_clock : use correct type, returns something - * * #6737: fixed typo in dbus call - * * #6737: removed tests for removed API - * * #6737: dbus: fixed bug from merge - * * #6737: cleanup in accountlist - * * #6737: cleanup in dbus - * * #6740 : fix history double free - * * #6740 : remove time updating thread from calls - * * #6737 : use c99 for client - * * #6738 : make history loading faster - * sipvoiplink : don't crash on transfers - * fixed typo - * Remove unused file - * Don't build networkmanager.cpp at all if NM is disabled - * _debug* -> _debug - * * #6554 : simplify sipvoiplink - * hudson: added -x to git clean command - * added git clean to hudson script - * audiocodecfactory: cleanup - * * #6718: refactored setTlsSettings into SIPAccount - * * #6718: removed more unused methods - * * #6718: refactored confmanager code into sipaccount - * remove unused functions - * * #6718: confmanager: removed more unused methods - * AudioCodecFactory : cleanup - * #6697 : Turn callableElement struct into union - * * #6718: confmanager: removed more unused methods - * * #6718: confmanager: removed more unused methods - * * #6718: removed unused dbus methods, refactoring - * * #6699: accounts: cleanup/refactoring - * * #6699: refactoring, cleanup in accounts - * * #6699: more account cleanup - * remove unused autoconf variable - * * #6714: fixed hudson script - * make distclean in hudson - * added || exit 1 to run_tests.sh call - * * #6714: fixed make distcheck for sflphone-plugins - * * #6714: fixed make distcheck for gnome client - * * #6714: fixed make distcheck for daemon - * git: #6698 split the main .gitignore file - * gnome: gpointer is already a pointer - * gnome: calltab_init: use calloc instead of malloc - * * #6699: more account cleanup - * * #6699: cleanup account - * * #6554 : more *voiplink cleanup - * * #6558 : more sipvoiplink simplification - * * #6558: saner loadSIPLocalIP prototype - * gnome: #6623 clean calllists - * * #6692: more audiolayer cleanup - * * #6692: cleanup/refactoring in audiolayers - * * #6692: more forward declarations, AudioThread->AlsaThread - * * #6692: audiolayer cleanup - * * #6692: alsalayer cleanup - * * #6558 : remove account creator - * * #6558 : clean sipvoiplink - * * #6554 : cleanup sipvoiplink - * audiortp: cleanup - * * #6657 : fix launchpad builds for good - * * #6675 : send RTP dtmf events only once - * * #6655: more cleanup - * AudioRtpSession::updateSessionMedia() : simplify - * * #6655: more cleanup in managerimpl - * * #6655: removed more code, cleanup - * * #6655: more cleanup, fixed infinite loop - * * #6655: removed more unused files - * * #6655: removed unused mutex - * * #6655 removed more unused code - * * #6655: removed unused methods - * * #6655: cleanup in main - * * #6663: fixed segfault when off hold from transfer - * * #6658: user's active codec selection is respected - * * #6660: static global string should be static const char* const - class member - * * #6659: use g_strcmp0, not strcmp for vals that may be null - * callable_obj: fix double free - * calltree_display_call_info() : simplify - * * #6657: Fix launchpad builds - * Logger::log() : simplify - * AudioRtpSession : privatize members - * * #6655: more constness, cleaned up/simplified methods - * * #6654: call DBus::_init_threading so that dbus-c++ to make it - threadaware - * set default credentials on account creation - * AudioCodecFactory::scanCodecDirectory() : simplify and correct - * * #6623: fixed typos - * * #6623: fixed more leaks - * * #6623: fixed more leaks - * * #6623: fixed more leaks, don't print codec name if null - * * #6623: more leaks fixed in client - * * #6623: fix more leaks, fixed some warnings - * * #6623: fixed leak in history - * updated gitignore - * initialize dbus dispatcher correctly - * Fix tests, hudson doesn't have a dbus daemon running - * remove unused code - * removeCall() : simplify , fix leak - * stopRtpThread() : simplify - * *CurrentCall : simplify - * Fix memleak - * fix serialization of audio api (pulse / alsa) - * account map : simplify - * remove call from callmap before terminating it, avoid use after free - * * #6630 : don't make DBusManager a singleton - * call: return confID by value - * add back history code deleted by error - * history : reverse logic - * simplify history serialization and remove some debug - * remove annoying debug - * * #6464 : replace cerr with _error - * * #6464: replace cout with logger macros - * replace printf() with logger macros - * update .gitignore - * remove unused function - * update eclipse projects - * uimanager_new() : simplify - * rename directories - * celt: simplify a bit - * Fix CELT configure.ac test - * * #6612 : template speex codecs - * * #6623: refactored conference obj - * * #6623: refactored callable object, removed leaks - * * #6623: more cleanup, fix leaks, make global vars static and rename - them - * * #6623: calltree: fixed memleaks, simplified code. - * audiolayer: init pointer members - * manager: catch exception on invalid hangup - * * #6623: don't leak on calls to create_new_call - * * #6611 : clarify codecs prototypes - * ringtones : .au and .ul files are both ulaw - * * #6611 : make sure samplerate converters are called correctly - * ManagerImpl::switchAudioManager() : simplify - * * #6623: fixed more leaks - * * #6623: fixed more leaks - * * #6623: fixed more leaks - * * #6623: fixed leak, line-endings in imwidget - * * #6627: zero-initialize pointers if they're going to be deleted - * * #6628: don't leak calls on exceptions - * Revert "audiortp: call join after calling stop on RtpThread" - * sflphone-client: more constness - * audiortp: call join after calling stop on RtpThread - * * #6625: return 0 on successful completion - * * #6624: fix segfault on servercallfailure - * * #6621: Fixed double free, unlock mutex in ManagerImpl::terminate - * * #6220: remove audio stream when peer hangs up - * * #6596: AudioSymmetricSession shouldn't self-delete - * resampler: grow internal buffers dynamically - * merge up and down sampling => resampling - * Leave test directory unchanged when running make check - * audio algorithms : remove unused prototype - * ringtone: detect codec from file extension - * *AudioFile : simplify - * * #6596: create local SDP on the stack, not the heap - * * #6596: don't call Ost::Thread::terminate from dtor - * audiofile: cleanup (samplerate -> unsigned) - * remove unused func - * samplerateconverter: cleanup - * RingBuffer::Put() : remove unused return value - * MainBuffer::putData() : remove unused return argument - * audiolayer::putMain() : remove unused func - * AudioLayer::putUrgent() : remove unused return value - * * #6618: delete any remaining ringbuffers in destructor - * RingBuffer::availForPut() : remove - * * #6617: return from main rather than calling exit - * MainBuffer::availForPut(): remove - * RingBuffer: simplify - * alsa : remove write only variable - * fix memcpy declaration - * bcopy(src, dst) -> memcpy(dst, src) - * RingBuffer::Get() : remove constant volume argument - * return a copy of the call ID, not just a reference. - * MainBuffer::getDataById() : remove volume argument (always 100) - * MainBuffer::getData() : remove constant volume argument - * RingBuffer::Put() : remove constant volume argument - * MainBuffer::putData() : remove constant (=100) volume argument - * audiolayer: remove constant _defaultvolume - * AudioRtpRecordHandler / AudioRtpSession : simplify - * mainbuffer: fix test - * iaxvoiplink : simplify - * sip registration callback: fix a dbus crash - * MainBuffer: simplify - * AudioRtpFactory: return cached type of rtp session. The rtp session - can have disappeared if the call was put on hold - * AudioRtpFactory: remove unused setters - * Fix launchpad builds - * * #6611 : remove unused bandwidth codec information - * * #6611: AudioCodec: remove useless/unused setters - * make sure buffer string is initialized correctly - * * #6596: declare certain destructors virtual - * audiolayer : cleanup - * Simplify doc build rules - * * #6270: don't build dbus-api doc with make, should require make all - * configure.ac: cleanup - * Remove copy of dbus-c++ from libs/ - * * #6596: stop clock thread when peer hangs up - * removed unused Fmtp.h - * * #6595: more logical initialization order - * * #6600 : fix account creation - * * #6601 : fix configure.ac tests - * remove unused variable - * Don't mix stack and heap based allocations - * Fix copyright (2009, 2008, 2009 -> 2008, 2009) - * Fix warnings found by clang - * * #6595: fix initialization order for AudioRTP - * * #6592: removed typedef std::string CallID - * * #6586: implement local g_slist_free_full for older glib versions - * * #6579: fix memory leaks in client (there's a lot left) - * ShortcutPreferences::setShortcuts() : simplify - * Fix merge - * * #6548: remove call to non thread-safe strerror() - * AudioRtpFactory: each instance is associated to exactly one SipCall - * create_audiocodecs_configuration() : make static - * * #6269 : refactor AudioRtpSession - * Fix AudioSymmetricRtpSession.h inclusion guard (cherry picked from - commit c3081dce1cc1370d6d3558a4c4ef5cfac0d21caf) - * * #6269: Rename AudioRtpSession to AudioSymmetricRtpSession - * * #6574: Don't exit when connection to pulseaudio server fails - * accountconfigdialog.h : remove some stuff from header - * * #6560: fix configuration test - * Fix warning in test - * * #6560: don't hide password entry in security tab - * * #6560: set initial password for SIP accounts - * * #6506: remove useless pointer indirection - * * 6560: password is now specific to IAX accounts - * * #6560 : actually use, store, restore, transmit SIP credentials - * * #6560: YamlEmitter: serialize sequences - * YamlEmitterException: typo - * ManagerImpl::computeMd5HashFromCredential() : simplify, fix memleak - * * #6561: invite_session_state_changed_cb() : simplify - * * #6561: More useful debug in VoIPLink::removeCall - * * #6561 : fix ghost call reappearing in GUI after transfer - * while -> for (make the code smaller) - * * #6558 : Account::loadConfig() : move IAX code to IAXAccount - * IAXVoIPLink::getAccountPtr : simplify - * * #6554 : access the SIPVoIPLink directly, not per account - * SIPVoIPLink is instanciated only once and is not associated to a - single account - * yamlnode: use const references when possible (still some left to do) - * Account::_accountID: constify - * VoIPLink: simplify, remove unused method - * hudson test : no need to call run_tests.sh anymore - * Remove AccountID type and AccountNULL define - * Make check runs the test (no need to call run_tests.sh manually - anymore) - * gnome GUI: Fix tests - * Revert "Move registration information from SIPAccount to - SIPVoIPLink" - * * #6392: pluginmanagertest: fix warnings reported by valgrind - * * #6547 : remove unused exceptions - * * #6547: CallManagerException: use runtime exceptions - * * #6547: InstantMessageException: use runtime exceptions - * * #6547: do not throw exceptions if some settings are not present in - config file - * * #6547: YamlParserException: use runtime exceptions - * * #6547: VoipLinkException: use runtime exceptions - * * #6547: YamlEmitterException: use runtime exceptions - * * #6547: DTMFException: use runtime exceptions - * * #6547: AudioFile: use runtime exceptions - * * 6547: AudioZRtpSession: remove impossible error case - * * #6547 : AudioRtpSession: remove impossible error case - * * #6547: AudioZrtp: use runtime exceptions - * * #6408 : send authenticationUsername to GUI - * * #6408 : store/restore authenticationUsername from config file - * SIPAccount: simplify - * Move registration information from SIPAccount to SIPVoIPLink - * SIPAccount::getAccountDetails : simplify - * * #6540: yaml parser: simplify - * sdp.cpp : fix a warning - * * #6540: yaml parser : remove std::string typedefs - * * #6540: Simplify yaml unserialization - * * #6540 : add a Conf::ScalarNode constructor for booleans - * setAccountDetails(): simplify - * * #6408: store authentication username in daemon - * * #6408: Be able to set the authentication username in the GUI - * * #6507 : do not crash if the program is not sflphoned - * Fix tests - * macroify SIPAccount::unserialize() - * Move all .cpp files from sflphoned target to libsflphone.la, except - main.c - * main() : simplify, return positive error codes - * * #6507 : find codecs dir in build directory - * * #6392: Sdp: move clean functions to destructor - * AlsaLayer::adjustVolume() : simplify - * alsalayer : reduce indentation - * malloc/free -> new/delete - * malloc/free -> new[]/delete[] - * malloc/free -> new/delete - * AudioSrtpSession: simplify base64 encoding - * * #6392: Initialize std::string from pj_str_t correctly - * * #6392: AudioRtpSession: Initialize remote port - * Audio settings : Initialize _echoCancelTailLength and - _echoCancelDelay(0) - * Initialize variable - * YamlParserException : fix use of stack variable after it has been - deallocated - * * #6392: fix memory leak in history - * * #6392 AudioCodec : fix memory leak - * * #6392 : fix memory leak in sip account - * * #6408: clean up sipaccount (cosmetics mostly) - * sipaccount.cpp serialize() : reduce number of lines - * * #6392: invalid memory access - * * #6392 : fix invalid memory access - * * #6479: merged useful code from MimeParameters into Codec interface - * * #6462: fixed hangup on IP2IP call - * added run_daemon.sh script - * test: remove unused variable - * Remove functions only used by a failing test (cherry picked from - commit fcf718cb75de7f1882dc61c07bb8d300dfa10f85) - * * #6360 : make client tests build (cherry picked from commit - 028b2835f040e51ab8ab979b32732b07b8798fce) - * * #6360 : fix warnings in check_global test (cherry picked from - commit 9e2bd6a7496dd64f6f48595e385760019aab1193) - * * 6360: updated API calls in tests, but they're not building yet - (cherry picked from commit 548f6f0f919b43772a3e9c667e5e292791281795) - * Fixed include in tests (cherry picked from commit - aeadc7525c1e31f936670ac8b02f0bcf387c38a8) - * Remove unused variables and functions - * IAX: fix warnings (cherry picked from commit - fd7a113a11cac2cd9a7c36929e88ad28195c4c35) - * Remove unused DEBUG define which interferes with logger.h (cherry - picked from commit b2f72b91d0f43cb1dd94d138882a8caa9c841c24) - * * #6392: no need to check for account NULLity since it is - dereferenced above - * * #6392: fix a memory leak, replace by stack allocation - * * #6392: remove a variable assignement which confuses cppcheck - * process_conference_participant_from_serialized() : remove unused - function - * * #6392: s/free/g_free/ - * * #6392: fix a memory leak in abookfactory_load_module() - * * #6392: remove generate_call_id() used only once - * * #6392: fix memory leak (opendir() without closedir()) - * * #6392: AudioRecorder(): ensures mbuffer is set - * Remove SFLPHONED_VERSION from global.h, use autoconf PACKAGE_VERSION - * #6298: Cleanup - * #6331: Fix deleting ringtone file after call have been answered - * * #6330: merged user_cfg into headers - * #6298: Fix conference recording file update at conference end - * #6298: Fix record file name serialization for conference - * * #6295: cleanup of codec hierarchy - * #6298: Fix gtk warnings - * * #6300: added script to run tests - * #6109: Add recording playback for conference - * * #6300: tests do not require an installed sflphone - * * #6295: re-removed clone methods - * #6109: Fix gtk_critical warnings for incoming calls - * #6109: Fix GTK_CRITICAL warning - * #6109: Fix icons when history is not activated - * #6109: Fix warnings - * #6109: Implement stop recorded file playback signal - * Revert "* #6295: removed unused clone method" - * * #6295: removed unused clone method - * * #6296: removed non existant file from Makefile.am - * #6109: Stop fileplayback for outgoing call - * #6109: Implement stop recording playback button - * Fix binding names errors in dbus introspection file - * #6109: Implement playback recorded file callback in client - * #6109: Store recorded file path on client side - * #6109: Add dbus methods for call recording playback - * * #6290: remove unused classes from utilspp - * * #6288: cleanup sdp - * * #6288: fix exception usage - * * #6288: simplify SdpException - * * #6288: cleanup in sdp.cpp/h - * #6109: Only display playback button if record file is set and valid - * * 6290: updated configure.ac to remove functor Makefile - * * #6290, #6289: removed unused classes from utilspp, fixed make - check - * #6109: Add button for history playback of recorded file - * * #6289: removed unused observer class - * * #6282: forward declare sdpMedia in sdp.h - * * #6281: renamed setCallAudioLocal->setCallMediaLocal - * #6183: Handle conference with more tahn two calls - * #6183: Fix history icons when calling back a conference from history - * #6183: Fix icons inconsistencies in history for conference hang up - * #6183: Fix toolbar actions when selecting a conference in history - * #6183: Fix conference serialization - * #6268: Serialize only calls - * * #6269: removed useless type testing - * ignore some files in test/ - * * #6268: Remove dead class AudioSymmetricRtpSession - * #6251: Do not had history calls in calllist when loading history - file - * #6251: Fix insertion in history map in before saving history file in - daemon - * #6251: Fix history unit tests - * #6251: Order the list before serailization, get rid of the hashtable - in history - * #6251: Implement history serialization using a list wether than a - map - * * #6253: remove external audioport from header, make all members - private - * * #6253: don't store external local audio port (used for NAT) in - Call - * #6251: Add start_time timestamp in history serialization - * #6251: Fix call insertion in conference items - * #6233: Fix serialized account list terminated with a ";" character - * #6238: Fix draggable history calls into current calls - * #6233: Fix toolbar updates - * #6233: Fix history - * * #6235: remove pyc files from git tree - * #6233: Handle cases when one or manuy calls are unreachable in - createConfFomrParticipantList - * #6233: Handle wrong numbers in createConferenceFromParticipantList - * #6231: Fix drag-n-drop issue - * * #6173 : move sippxml in tools - * #6231: Fix merging issue - * #6183: Implement conference unserialize - * * #6212: remove extraneous flags from globals.mak - * #6183: Unserialize conference data in conference - * #6183: Add account information in request for conference call from - history - * #5755: Add -ldl to liker in sflphone-client-gnome - * #5755: Fix fedora 15 compilation issue - * #6183: Serialize conference participant phone number and account - * #6183: Add conference timestamp in serialization - * * #6186: don't include global.h, just logger.h - * #6183: Fix saving history to file - * #6183: Fix removing call from calllist - * * #6184: remove pointers to Manager from AudioRtpSessions - * #6183: Calling calltree_add_call explicitely for history - * #6183: Ability to store conference inside history tab queue - * * 6181: remove unused API from sipcall - * #6171: Implment nreCallCreated callback - * #6167: Fix participant list NULL ending - * #6149: First draft of conference creation from history - * #6149: Fix multiple call/conf selection callbacks ... - * #6129: Fix place_call function called twice for pressing enter - action - * #6129: Fix double click action for history - * #6149: Add dbus call for creating conference from history - * #6129: Fix placing call from history and addressbook (still need to - fix icon) - * * #6148: removed unused AudioRtpFactory constructor - * * #6145: remove unused isAudioStarted - * * #6145: remove unused isAudioStarted - * #6129: Add conference into history, fix call/conference selection - * * #6143: don't use getType outside of serialization methods - * * #6132: forward declarations instead of includes - * * #6132: add constness, remove redundant "inline" keywords - * #6129: Add timestamp to conference object to order history entries - * * #6128: remove unused forward declarations from header - * * #6127: make noncopyable class actually noncopyable - * * #6125: don't include AudioRtpFactory in sipcall.h - * #6123: Fix alsa ringback audio file - * #6123: Fix raw audio file loading problem - * #6109: Fix daemon plugin manager unit test - * #6109: Fix history manager unit tests - * #6109: Recording filename in daemon and client for history items + - serialization - * #6109: Refactor AudioFile to play recorded call - * * #6104: AudioCodec moved to sfl namespace - * * #6099: remove active flags from codec classes - * #6095: Add notification-daemon as a runtime dependencies for rpm - packages - * #6095: Fix fedora 15 compilation in MineParameters.h - * #6095: Declare static variable explicitely for client - * #6095: Add logs to build OSC build machine - * * #6098: global variables should have file-scope to avoid name - conflicts - * #6095: Fix compilation error for Fedora 15 - * #6095: Update SFLphone version to 0.9.14 - * #6095: Add specification file in opensusse build service for - sflphone-plugins - * #6073: Fix sflphone-plugins build on launchpad - * #6093: Rename CodecDescriptor for AudioCodecFactory - * * #6089: fix warnings in make check - * * #6086: renamed codecs methods to audio_codecs - * * #6085: renamed codec related dbus calls to audio_codec - * #6065: Remove g_print from client, use DEBUG instead - * #6065: Add actions name for addressbook - * * #6085: renamed codecs* widgets/functions audiocodecs* - * #6065: Fix Addressbook runtime warnings - * #6065: Replace Codecs tab for Audio in account preference dialog - * #6065: Fix "transfert" typo - * #6065: Fix addressbook action runtime warning in uimanager - * * #6082: fixes make check by adding libcrypto libs to test - dependencies - * #6073: Rename plugin/addressbook folders for addressbook/evolution - in sflphone-plugins - * #6074: Removed AC_SUBST from configure.ac when using - PKG_CHECK_MODULE - * #6073: Fix sflphone-plugins package build - * #6073: Fix sflphone-common build - * #6065: Fix runtime gtk warning when initializing searchbar without - addressbook - * #6063: Fix mozilla-tellify gitignore - * #6063: Remove stream copy file using ifdef macro - * * #6012: fix make dist for sflphone-common - * #6063: Update .gitignore file - * #6058: Fix base64 encoding related warnings - * #6056: Fix SdpException handling - * #6055: Fix unknown pargma warning for gcc <= 4.5 - * * #5949: test gcc version before disabling unused-but-set warning - * #6054: Fix addressbook plugin compilation warning - * #6048: Fix uimanager static initialization - * #6046: Fix addressbook factory static initialization of member - addrbook - * #5979: Fix implicit function declaration warning - * #6042: Fixed discarding qualifier warnings in client - * #6041: Fix instant messaging unhandled case warning - * #5994: Implement set current addressbook name and search type in - addressbook plugin - * #5994: add rules for launchpad packaging of addressbook plugin - * #5994: Fix addressbook plugin configuration loading - * #6027: Fix addressbook enabled test from configuration - * #6027: No need of gnomedoc related macros in addressbook plugin - * #6027: Add NEWS file required for build - * #6027: Add addressbook plugin autogen.sh script - * #6027: Remove plugins from client - * #6027: Add sflphone-plugins folder at project's root level - * #5994: Move addressbook folder from contacts to plugin folder - * * #6011: removed unused Makefiles - * * #6010: remove unused headers - * * #5952: fix "string constant to char*" warnings - * * #6009 fixed warnings - * * #6003: finished cleanup of account classes - * * #6003, #6004: cleanup of account classes, defaultAccount no longer - global - * * #6000: fix memory leak of args object - * * #5998: removed using namespace std from networkmanager - * * #5998: removed "using namespace std" from ZrtpSessionCallback - * * #5998: removed using namespacestd from AudioZrtpSession.h - * * #5998: remove "using namespace std" from auriorecord.h and - MimeParameters.h - * * #5998: remove using namespace std in main - * * #5998: removed "using namespace std" from logger - * * #5949: test gcc version before disabling unused-but-set warning - * #5994: Installation of addressbook plugin - * #5979: Implement codec full addressbook search from plugin - * #5979: Implement addressbook factory and plugin - * * #5981: unused webwidget removed - * #5966: Account config synchronization fix (for stun) - * #5954: Handle media name exception - * #5954: Fix audio codec name display in client - * #5954: Clean up getSessionMedia methods - * * #5957: getRecordingSmplRate returns a value - * #5954: Clean up getCurrentCodec methods - * * #5950: remove "converting to non-pointer type 'int' from NULL" - warnings - * #5915: Full gain control version - * * #5949: remove more unused variable warnings - * * #5949: remove unused/unused-but-set variable warnings - * * #5949: show_preferences_dialog returns a success value - * * #5946: cleanup of include directives, undefined function - * * #5515: comment out SSLv2 calls in pjsip - * #5915: Implement different slope for attack tme and release time for - gain control - * #5915: use only one input signal for gain control (removed output - buffer) - * #5921: Fix no audio after holding a conference - * #5916: Add gaincontrol files - * #5916: Implement FFMPEG/CCRTP video streaming prototype - * #5903: Fix call transfer during a conference - * #5915: implement rms detector, first order averager, limiter for - gain control - * #5914: Fix call transfer when no notification request is required - * #5899: Fix conference right-click segfault - * #5884: temporary fix segfault in pjsip memory pool - * #5883: Fix compilation issues on maverick and lucid - * #5755: Fix fedora 15 compilation without patching ccrtp - * [#5855] Make echo canceller optional - * #5855: Fix echo suppression activation/deactivation - * #5855: Implement pjsip echo canceller - * #5814: Speex initialization function uses samples, not bytes - * #5814: Test using more unbalanced signals - * #5814: Fix buffer size for long echo length or long echo delay - * #5814: Adjust level for echo cancellation at runtime - * #5814: Process noise reduction before echo cancelling - * #5814: Implement speex post echo canceller processing - * #5814: Dump echo cancel file to disk - * #5814: Add parameters for echo cancel - * #5809: Add configuration parameters - * #5809: Implement speex echo canceller in audio rtp session - * #5814: Code cleanup - * #5814: Fix conf creation with several incomming ringing calls - * #5814: Fix conf creation segfault when dragging a call on hold on a - ringing call - * #5809: Added unit test for echo cancellation and implemented - "process" virtual method - * #5709: Add always recording option in configuration - * #5709: Add always recording option in audio conference panel - * #5709: Add core functionnality for always recording (missing config - options) - * #5769: Fix conference participant handling (detach/attach) and hold - actions - * #5747: Fix recording icons and state for conference when adding new - participant - * #5769: Code cleanup - * #5769: Fix hangup unsent calls - * #5769: Fix remove/add additional participant to conference - * 5769: Several fixes concerning confererence handling - * #5769: Fix compilation error - * [#5769] Fix audio streams binding in main buffer - * #5769: Removed access to audio mixer from audio layer - * #5765: Fix audio crash for illformated wavefiles - * #5765: Add maximum iteration for finding fmt and data "chunck" - * #5589: Fix compilation of libnotify under - * #5757: Fix abort signal when receiving INFO - * #5747: Add usersDetached.svg - * #5747: Handle offhold action for recording conference - * #5747: Fix off hold action for conferences - * #5747: Implement update conference in record action in calltree - * #5747: Add new icons for recording conferences - * #5747: Add recording state for conferences - * [#5738] Remove getAudioDriver call from manager (replace by - _audiodriver var) - * [#5738] Refactor mutex protecting audiolayer - * [#5737] Fix HD conference recording - * [#5730] Fix start audio session after changing sampling rate - * [#5714] Fix enter keyboard event for addressbbok and history - * [5695] Fix addressbook combo box update when no addressbook selected - * [#5695] Fix addressbook initialization and search bar update - * [#5695] Add mutex for books_data in addressbook to protect async - calls - * [#5695] Get back addressbook open from uri - * [#5695] Fix absolute addressbook URI for local addressbooks - * [#5695] Implement libebook 3.0 interface - * [#5571] Better logic for hangup (for case where call have not been - sent yet) - * [#5571] Update error handling in voip links - * [#5571] Fix compile time warnings - * [#5696] Fix installation dependencies for Natty - * [#5669] Add mention that sflphone.org is for testing only - * [#5693] Add natty in teh dput.conf file - * [#5690] Remove not useful logs - * [#5670] Use dynamic payload type for rtp dtmf - * [#5668] Clean up sflphone configuration logging - * [#5668] Fix hook checkbox configuration update - * [#5666] Fix unit tests - * [#5666] Manage event subscription - * [#5666] Emit bye request when subscription is terminated - * [#5666] Bye request should be sent after event subscription - notification is done on transfer - * [#5666] Make reinvite method static (to be called in pjsip - callbacks) - * [#5666] Hangup Call in manager for AccountNULL and IP2IP - * [#5589] Use PKG_CHECK_MODULE for every client's dependencies - * [#5623] Enlarge initial size of pjsip memory pool for calls (16k) - * [#5564] Fix audio recording resampling for g722 - * [#5571] Move attribute handling for onhold/offhold actions in SDP - session - * [#5571] Codec negotiation refactored and unittested - * [#5571] Implement tests - * [#5571] Implement pjsip negociator - * [#5571] Fix unit tests - * [#5571] Add Fmtp.h to repository - * [#5571] Integrate mime types and codec factory - * [#5571] Handle exception when SDP negotiation fails - * [#5570] Add sflphoned-sample.yml in repository - * [#5564]: Implement stereo to mono mixing for rigntone - * [#5342] Update audio stream initialization - * [#5514] Restore test ni historytest suite - * [#5514] Fix - * [#5514] Disable test_create_history_path - * [#5514] use pulseaudio in sample config file - * [#5514] Fix test: load history from file - * [#5514] Do not use X - * [#5513] Make unit tests compile successfully - * [#3947] Enable unit tests in Jenkins - * [#5454] Fix build system to handle new version number - * [#5454] Update languages from launchpad - * [#5454] Add --without-celt in OpenSuse build service - * [#5454] Change version number - * [#5331] Added first SDP session tests - * [#5273] Update nightly build version tags to conform dpkg rules - * [#5211] Refactor send register method for iaxvoiplink and - sipvoiplink - * [#3950] Remove call being transfered from calltree - * [#5211] Use appropriate memory pool for transport selector - * [#5211] Fix strict aliasing rules warning in pjsip - * [#5211] Bring back pjsip shutting down sleep to 1000 ms - * [#5211] Fix registration callback segfault when closing the - application - * [#5211] Use the dialog memory pool for Route header in INVITE - request - * [#5211] Add temporary memory pool for findLocalAddressFromUri and - findLocalPortFromUri - * [#5211] Use individual memory pool for dtmfs - * [#5211] SipVoipLink refactoring - * [#3950] Attended transfer for conference calls - * [#5284] Fix DNS resolution for Route with specified port number - * [#5284] Some code cleanup - * [#3947] Fix typo in hudson script - * [#5284] Added sip route to REGISTER, INVITE, BYE request, plus DNS - resolution - * [#5266] Use RTP dtmf as default - * [#5284] Added pjsip_process_route_set after setting routes in regc - structure - * [#5286] Fix parsing error due to long configuration file (removed - max event) - * [#5286] Fix false test in configuration emmiter - * [#5286] Code cleanup - * [#5286] Updated exception handling in configuration system - * [#4969] Fix put SRTP call on hold - * [#3950] Add debug messages - * [#3950] Ability to perform an attended transfer - * [#5276] Fix initialization problem in g722 - * [#3950] Add replace header in SIPVoIPLink::transferWithReplaces - method - * [#3950] Implemented attended method in SIPVoIPLink - * [#3950] Cleanup transaction request received callback - * [#3950] Implement dummy attended transfer in gnome-client - * [#5249] Fix audio samplerate update algorithm for g722 - * [#5249] Fix uninitialized variable used in conditional jumps - * [#5249] Fix conditional jump error in audiolayer (uninitialized - value) - * [#5267] Use autoconf 2.65 as a requirement (instead of 2.67) - * [#5267] Restore manual pjsip configuration and compilation - * [#5267] Autodetect celt version (0.9.1, 0.7.1) - * [#5267] Fix deprecated macros in gnome client configure.ac - * [#5267] Update configuration for libcelt-dev - * [#5267] Fix build autoconf and automake - * [#5227] Deactivate automatic call to astyle after compilation - * [#5242] Hangup every calls before leaving - * [#5237] Will now nightly-build for natty, Karmic deprecated - * [#5229] Use inner class for rtp thread instead of inheritance - * [#5211] Move mainbuffer unbind call in rtp final method - * [#5211] Initialize sip call memory pool using 16 kb - * [#5211] Use call memory pool in session reinvite - * [#5211] Add debug messages - * [#5211] Use and internal pool for calls - * [#5211] Reduce pjsip memory pool usage for stateless error messages - * [#5211] Refactor call deletion - * [#5212] - * [#5208] Refactor codec management for accounts - * [#5168] Remove printf from codec's encode & decode method - * [#5168] Fix celt compilation on launchpad - * [#5168] Fix sflphoned compilation warnings in audiocodec.h - * [#[#5168] Must keep the g722 specific RTP rate to avoid incoming - packet timeout - * [#5168] Fix static/dynamic payload rtp session update - * [#5168] Throw SIPVoipLink Error if codec not instantiated in new - outgoing call - * [#5168] Fix dynamic/static codec payload type ambiguity - * [#5169] Fix doubled IP2IP profile when no config file - * [#4867] Add gtkinfobar in configuration panel - * [#4867] Disable input/output/ringtone selection when using default - alsa plugin - * [#4952] Patches for possible buffer overflows - * [$4885] Fix schemas problem - * [#4885] sflphone-client-gnome.schemas not present during build - * [#4885] Add gconf shemas directories in opensuse build system - * [#4885] Add file/folder ownership for opensuse-factory build system - * [#4906] Fix opensuse-factory build - * [#4885] Update name dependency for libedataserver - * [#4885] Fix non-void function without return in dbus-c++ - * [#4895] Update language translation - * [#4896] Update session timestamp when updating media - * [#4896] Reapply RTP hack for G722 payload type - * [#4896] Update recording sampling rate when updating codec - * [#4897] Save codecs in config for each configuration changes - * [#4895] Do not save config when sflphone quit - * [#4885] Update date for copyright - * [#4885] Deactivate siptest that require more than one sipp instance - * [#4879] Remove inmcoming call notification from IAX - * [#4885] Some cleanup - * [#4874] Add setCancel immediate/deffered for ost::Thread - * [#4879] Fix incoming call notification - * [#4878] Set keyboard focus on searchbar when selecting addressbook - * [#4874] Fixed compilation warning - * [#4874] Fixed compilation warning in sipvoiplink - * [#4874] Fix compile time warning in RTP record handler - * [#4874] Fix conditional jump in SDP - * [#4874] Fix conditional jump based on uninitialized value - * [#4874] Store call id within rtp thread context - * [#4874] Fixed conditional jump based on uninitialised value in - conference - * [#4871] Fix default account fetching - * [#4870] Delete RTP session when Refusing an incoming call - * Restore IP to IP call - * [#4857] Fix audio codec negotiation problem - * [#3947] Adjust ressources allocated to compilation - * [#3947] Disable unit tests in Hudson - * [#4305] Free mutex only when really quiting SFLphone - * [#4859] Update copyright to 2011 in every source file - * [#3218] Character '.' stripped by the caller engine - * [#4854] Fix typos, desktop entry - * [#4847] Apply RTP modification to ZRTP session - * [#4852] Update Karmic and Lucid dependencies - * [#4852] Add Libedataserver and libedataserverui as gnome client - dependencies - * [#4852] Add authentication mechanism for EDS - * [#4851] Fix segfault when closing pulseaudio layer too rapidly - * [#4808] Some otehr cleanup - * [#4808] Made some cleanup - * [#4808] Added mutex in rtp session for codecs and noise process - * [#4847] Update audio processing when updating RTP media - * [#4842] Add support for linking with gold/ld --no-add-needed - * [#4808] Make update g722 related static/dynamic payload logic - * [#4827] Upper limit on the number of contacts to import from EDS is - hard-coded to 500 - * [#4808] Fix put call on/off hold - * [#4808] Implement early RTP start for incoming calls - * [#4808] Audio stream is no longer start within RTP session. - * [#4808] Removed coupling between audio layer and and RTP session - * [#4702] Start audio rtp session as soon as it is created - * [#4702] Init timestamp to 0 - * #4702: Send RTP packets immediately, no need of outgoing queue - * [#4784] Update dbus-c++ version from gitorious - * [#4702] Update RTP timeouts - * [#4702] Lengthen RTP timeouts - * [PATCH] Fixed compatibility with old libtool versions. - * [PATCH] Accept older libebook (Maemo 5 has 1.4.2) - * [PATCH] Fixed double-free error in preferences dialog - * [PATCH] Fixed building of sflphone-common on Maemo5 - * [PATCH] Improved Gnome client initialization error handling. 1. It - no longer segfaults when sflphoned isn't available. 2. User is - provided with GUI error dialog. - * [PATCH] Improved autogen.sh scripts 1. They do not require bash - anymore 2. Added workaround for Debian bug #565663 3. Replaced - manual autotools invocations with single autoreconf call 4. Non-zero - return status on failure - * Revert "[#4468] libtool <= 2.2 doesn't have LT_INIT macro so - AC_PROG_LIBTOOL should be used instead." - * Revert "[#4468] Libebook 1.4 is sufficient" - * Revert "[#4468] Apply big path on dbus communication system" - * [#4468] Apply big path on dbus communication system - * [#4468] Libebook 1.4 is sufficient - * [#4468] libtool <= 2.2 doesn't have LT_INIT macro so AC_PROG_LIBTOOL - should be used instead. - * [#4639] Fix determining default addressbook if this property is not - set in gconf - * [#4639] Fix memory leaks in Addressbook - * [#4637] Fix opening default addressbook at sflphone init - * [#4622] Free yaml events while parsing configuration file - * [#4623] Fix conditional jumps based on uninitialized variable - * [#4622] Fix leaks in yaml serialization engine - * [#4616] Fix addressbook warnings - * [#4514] Adjust RTP timestamp - * #4527: Rename Karmic libyaml and Celt package in debian control file - * #4495: Rework addressbook opening loop - * [#4524] Increment RTP count when sending data - * [#4524] DO NOT start RTP session twice - * [#4367] Use PKG_CHECK_MODULE for celt - * [#4367] Fedora package celt as celt (not libcelt) - * [#4367] Astyling - * [#4367] Update .po files - * [#4367] Fix segfault in gensin - * [#4354] Make celt a direct dependency on launchpad opensuse build - service - * [#4367] Make celt a required package, option --without-celt valid - * [#4367] Fix zrtp timestamping error - * [#4367] Fix audio zrtp timing - * [#4367] Dispatch ZRTP packets - * [#4367] Fix segfault when unloading account map - * [#4367] Fix zrtp session - * [#4367] Implement on packet receive - * [#4367] use symetric audio rtp session, not dual - * [#4367] Reduce packet receive/sent timeout - * [#4367] Reduce RTP timeouts - * [#4367] Move speaker data receive - * [#4367] Move speaker data receive - * [#4367] Move receive speaker data method - * [#4367] Remove debug in rtp session - * [#4367] Fix g722 codec clock rate - * [#4367] Fix noise suppression initialization - * [#4367] Fix segfault in RTP mic fadein method - * [#4367] Refactor mic data encoding in rtp session - * [#4367] Implement RTP main loop - * [#4367] Fix compilation problem - * [#4367] Fix AudioRtpclass using TRTPSessionBase - * [#4367] Fix AudioRtpSession putDtmfEvent shadowing - * [#4367] Fix AudioRtpSession putDtmfEvent shadowing - * [#4367] Refactor RTP session (phase 2) - * [#4367] Refactor RTP session (phase 1) - * [#4367] Remove Redeclaration of SymetricAudioRtpSession in - rtpfactory - * [#4265] Add continue statement in for loop for invalid addressbook - * [#4261] Makes addressbook initialization more robust - * [#4257] Add maverick in build system - * [#4233] Add sdp related unit tests - * [#4233] Add condition and signal in two incoming call test - * [#4243] Fix segfault in AudioSrtpSession - * [#4243] Fix memory leak in AudioSrtpSession - * [#4243] Make audio srtp optional in for incoming call - * [#4243] Add boolean variable to make sure remote crypto context - initialized only once - * [#4243] Add documentation to AudioSrtpSession - * [#4243] Use 80 bits authentication tags by default - * [#4243] Init audio srtp remote crypto context in - call_on_media_update - * [#4243] Move SDP negotiastion in mod_on_rx_request - * [#4243] Implement initLocalCryptoInfo to be called at different - momment - * [#4243] Init init local crypto context in when initializing audiortp - * [#4243] Change key length according to sdes negociation - * [#4243] Associate callid to accountid for incoming calls - * [#4242] Fix no SDES keys in IP2IP calls - * [#4242] Fix no SDES keys in IP2IP calls - * [#4233] Test for call on/off hold - * [#4233] Add two incoming call test - * [#4233] - * [#4233] Add 2 outgoing simultaneous call unit tests - - -- Julien Bonjean <julien.bonjean@savoirfairelinux.com> Fri, 30 Sep 2011 13:51:04 -0400 - -sflphone-client-kde (0.9.7~rc1~ppa1~SYSTEM) SYSTEM; urgency=low - - ** 0.9.7~rc1~ppa1~SYSTEM ** - - * [#2462] Set explicitly the transport on incoming call too - * [#2462] fix typo - * [#2462] Use different address for SDP and call IP - * [#2462] Use published address in SIP-SDP - * [#2181] Fixed changelog files - * [#2181] Updated spec file - * [#2402] Fix pointer to int conversion warning (atoi) - * [#2402] Remove daemon warnings, make indent - * [#2459] Make sure the stream is opened when the call is answered - * [#2402] Add conference related picture in documentation - * [#2443] Not much ... - * [#2399] Fix dialing display problem - * [#2450] Fix incoming call already in conference crash - * [#2399] Display peer name on the first line and peer number on the - second - * [#2450] Handle 403 FORBIDDEN when refused - * [#2447] Bind offHold/onHold actions to button in gtk client - * [#2447] Bind hangup action to button for conference - * [#2447] Add conference action in gtk client's ToolBar - * [#2381] Disable the password hashing in config file - * [#2402] Cleanup - * [#2366] Set callback to null when deleting Pulseaudio streams - * [#1313] Fix main buffer unit test - * [#1313] Fix audio layer unit test - * [#2315] Hide pw in security tab, display when editing, sync with - basic tab - * [#1313] UnitTest change AudioRtpSession for AudioSymetricRtpSession - instance - * [#2402] Code cleanup - * [#2444] Add debug to catch occasional crash when loading client's - config - * [#2444] Add debug info to catch occasional crash when loading config - dialog - * [#2402] Restore Call menu translations - * [#2403] Use the published address if checked in GUI - * [#2442] Add protection test in sdp - * [#1841] Reapply pjsip patch concerning DNS SRV resolution - * [#2384] Tags incoming call as direct SIP call, if applicable - * [#2402] Change the monkey face - * [#2315] Enable user to display password in clear text - * [#2434] Force optimization level at 2 - * [#2284] Fix dbus_get_all_ip_interface compilation warnings - * [#2431] Popup main window on incoming if applicable - * [$2402] Fix simple warnings - * [#2402] Fix implicit variable init order in LibraryManagerException - * [#2402] Fixing implicit variable initialization warnings in - AudioRtpSession - * [#2402] Revert atoi change, fixing codec list doubled entries - * [#2402] Fix gpointer to gint conversion - * [#2402] Fix pointer casting to integer different size warning in - codec list - * [#2402] Fix warning discarting qualifiers from pointer target - * [#2402] Fix gtk tree view assignement from incompatible type warning - * [#1669] Fix audio recording folder utf-8 non compatibility issue - * [#2414] Clean up debugs - * [#2414] Use transport set in iptoip Account and update it frm - preference - * [#2348] Use macro N_() to mark ui.xml strings as translatable - * [#2414] Rename getSipAddress/setSipAddress functions - * [#2407] Fix volume controls display - * [#2407] Fixes dialpad - * [#2383] Set ip to ip config when clicking apply button - * [#2404] Update call-to script - Maxime Chambreuil - * [#2405] Client handles unknown call in current state as well - * [#2383] Add DBUS signal to send IPtoIP local address and port as - string - * [#2383] Add Ip to IP config change apply call back - * Clonflict - * [#2402] Code cleanup - * [#2383] Do the same for IPtoIP (init localn ip with first in the - list) - * [#2383] Use first interface in the list if local addresss is not - defined - * [#2403] Clean up unuseful addresses/ports - * [#2403] Use the IP profile SIP port as global SIP port - * [#2383] Fix dbus_get_all_ip_interface warnings - * [#2383] Take into account sameAsLocal when loading published address - * [#2383] Tsake into account sameAsLocal option when saving published - address - * [#2383] Update local ip address in ip to ip config - * [#2383] Save ip 2 ip local port in config - * [#2406] Update toolbar at startup - * [#2284] Remove redefinition warnings + speex warnings - * [#2383] Fix security table in account config - * [#2383] Save ip 2 ip network interface parameters in config - * [#2403] Restore sip transport selector - * [#2383] Fix filling the Localt IP Address on account creation - * [#2383] Fix Gtk-Critical when checking STUN - * [#2383] Fix reopening account configuration display issue - * [#2383] Load IPtoIP local address and port in preference iptoiptab - * [#2383] Add LocalAddress and Localport in Preference IpToIp tab - * [#2403] Use the address and port associated to the account as often - as possible - * [#1753] Removed pjsip generated files - * [#1753] Removed remaining milenage lib references - * [#2383] Add _publishedSameasLocal variable in sipaccount - * [#2383] Add PUBLISHED_SAMEAS_LOCAL variable in config - * [#2383] Fix stun set active or not when opening config - * [#2181] Added RPM 64bits dbus patch - * [#2402] Code indentation - * [#2313] Force $(HOME).cache directory creation at startup - * [#2383] Separate network interface and published address in account - config - * [#2400] Change dbus service installation path to libdir - * [#2382] Move TLS related published address options in security tab - * [#2382] Indent accountconfigdialog.c - * [#2181] Install libdbus-c++ in $pkglib instead of $lib - * [#1753] Remove ILBC code and disable it by default in the configure - * [#1753] Remove milenage directory - * [#2382] Fix switching interaface instabilities - * [#2396] Save local ip in account creation wizard - * [#2284] Remove warning on hold - * [#2387] Fixes history searching and filtering - * [#1215] Add samplerate display in the GUI - * [#1663] Voicemail icon reflects voice messages - * [#2395] Fix account registration ( specifically with callcentric) - * [#2386] Strip "sip:" on incoming call, fixing history call back - * [#2181] Updated spec files - * [#1215] Display codec name in calltree instead of status bar - * [#2390] Move back nbCalls and stopStream higher in refuseCall - * [#2392] Fix ringtone during call in IAX - * [#2391] Stop audio streams when there is 0 calls only - * [#2391] Add debug when call state is not valid - * [#2390] Clear returns in IAXvoipLink::sendAudioFromMic() method - * [#2380] Fixing IncomingCallNotification not regular - * [#2339] Query conference at client startup - * [#2339] Working conference querying at startup - * [#2339] Add conference in call tree - * [#2339] Primitives to query conferences at client startup - * [#2320] Add account selection in history - * [#2355] Temporary solution: do not delete pointer when removing - account - * [#2380] Change algorithm in AudioRtp to trigger an - IncomingCallNotification - * [#2274] Comment sdebug in MainBuffer flush method - * [#2274] Add flushMain() in ManagerImpl::addStream - * [#2274] Add getBufferID() method in ring buffer - * [#2274] Fix warning, comment debug in ringbuffer's flush method - * [#2274] Use AudioLayer flushMain() and flushUrgent() in ALSA - * [#2274] Clean up unused variable warning - * [#2274] Protect minbudffer pointer on flushing - * [#2274] Fix playATone method which writing empty buffer in urgent - ringbuffer - * [#2274] Use audio layer flushUrgent and flushMain in createStreams - * [#2274] Use flush audio calls from audiolayer - * [#2274] Flush when peer answered call - * [#2375] Flush main buffer in iax when answering a call - * [#2274] Parse displayname using c++ string method - * [#2375] Flush main buffer when off holding calls - * [#2375] Flush main buffer mon RTP startup - * [#2376] Use now Pulseaudio module-cork-music-on-phone - * Updated OSC packaging - - -- Julien Bonjean <julien.bonjean@savoirfairelinux.com> Fri, 20 Nov 2009 14:00:02 -0500 - -sflphone-client-kde (0.9.7~beta~ppa1~SYSTEM) SYSTEM; urgency=low - - ** 0.9.7~beta~ppa1~SYSTEM ** - - * [#1933] Cleanup debug - * [#1933] Clean up debug - * Fix mic - * [#1933] Set the IAx format earlier - * [#1933] Move IAX sendAudioFromMic outside if (call) statement - * [#1933] Fix startstream when offhold in iax and add debug concerning - codec neg. - * [#2371] sflphone_notify_voice_mail: minor gettext message formatting - cleanup - * [#2371] select_account_cb: properly gettextize status message - * [#2371] show_account_list_config_dialog: properly gettextize status - message - * INSTALL: Minor tidyup of core install guide - * Add /sflphone-client-gnome/src/icons/Makefile to .gitignore - * [#2181] Updated OpenSUSE files (tmp) - * [#1933] Add debug for codec negociation for iax - * [#1933] Get rid of getMicAvail and getMicData in audiolayer (not - used anymore) - * [#1933] Add "audio codec not determined" error in IAX - * [#1933] Test flush data - * [#1933] Do not need to start audio stream in iax anymore - * [#1933] Protecting pointer - * [#2284] Remove more compilation/execution warnings - * [#2284] Cleanup debug in client, use DEBUG instead of g_print - * [#2284] Clean up uimanager - * [#2370] Remove warnings - * [#2366] Clean up other debug - * [#2366] Clean up debug - * [#2366] Call pa_xfree explicitely in writeToSpeaker - * [#2284] Remove address book warnings - * [#2365] Fixes bad cast - * [#2352] Fix continuous ringing when peer hangup and call not yet - answered - * [#2181] Added version support - * [#2181] Fixed some minor issues - * [#2360] Moved MainBuffer from AudioLayer to ManagerImpl - * [#2352] Makes getMainBuffer() everywhere - * [#2352] Use 50 sec latency on pulseaudio stream creation - * [#2352] Add alsa debug - * [#2359] Update repository documentation - * [#2354] Move pulseaudio disconnectAudioStream after stopping main - loop - * [#2352] Adjust nb byte copied in pulseaudio according to - writeableSize - * [#2352] Specify pulseaudio tlength parameters using pa_usec_to_bytes - * [#2322] Convert italian translation to UTF-8 - * [#2357] Fixes window size - * [#2357] Display only actionnable tool item - * [#2333] Update streams parameters - * [#2347] Use GNOME user settings for Menu and Toolbar appareance - * [#2349] Load/Save properly audio params - * [#2322] Update translations from Launchpad - * [#2181] Added Francois Marier script - * [#2350] Remove non-valid test - * [#2181] Updated launchpad packaging - * [#2333] Fix Pulseaudio Capture - * [#2333] Use pulseaudio ADJUST_LATENCY flag and ALSA RT-SCHEDULING - * [#2333] Pulseaudio Interpolate timing - * [#2333] Change (again) Pulseaudio settings to fit logiteck usb hdw - requirement - * [#2333] Adjust pulseaudio fragment size to 4096 (max sflphone's - frames per buffer) - * [#2284] Remove recurrent compilation warning (g++ linker problem) - * [#2333] Safer Audiostream parameters - * [#2333] Fix alsa playback to reduce underrun - * [#2333] Better audiostream parameters - * [#2181] Updated version management - * [#2333] Exclusive test in playback loop - * [#2181] Updated build system - * [#2333] Less underrun with these value - * [#2333] Update playback audiostream parameters - * [#2333] Lengthen the audio buffer reduce number of underrun in - pulseaudio - * [#2333] Add ALSA recovery functions for underrun (begin) - * [#2333] Add pa_stream_trigger in pulse audio underrun callabck - * [#2048] Reduce prebuffering in pulseaudio (which affect incomming - calls' plbck) - * [#2316] Do not display any icons to the right on the history tab - * [#2333] Comment pa_stream_trigger in pulseaudio underrun - * [#2333] Modify pulseaudio streams parameters - * [#2318] Fix transfer tool button double signal - * [#2181] Updated - * [#2333] Fix ALSA ringtone - * [#2333] Flush all main buffer before starting audio - * [#2333] Open/Close Alsa thread between calls while there is no audio - * [#2333] Add debug message and test condition on starting playback - and capture - * [#2181] Fixed gnome client makefile - * [#2181] Updated - * [#2308] Remove getTelephoneTone debug - * [#2308] Change plughw for default in ALSA - * [#2308] Oups, forgot to change function name in audiolayertest.cpp - * [#2308] Cleanup in pulseaudio code (debug, function name) - * [#2308] Fix pulseaudio stream closing assertion failure - * [#2308] Moved pulseaudio mainloop locking from AudioStream - disconnect stream - * [2308] Fix latency at the beginning of a call, when playing DTMF and - wehn starting tone - * [#2181] Updated karmic - * [#2317] [#2319] Fix address book toggle button contextual behaviour - * [#2308] Stop stream when refusing a call - * [#2308] Stop pulseaudio stream when peer hungup - * [#2308] Fix tone and ringtone - * [#2312] Display the STUN entry widget when opening the tab - * [#2308] Implement two different callbacks for capture/playback in - pulseaudio - * [#2309] Open/close pulseaudio connections in startStream/stopStream - * [2308] Leave pulseaudio stream running, do not cork/uncork them - anymore - * [#2295] Set gtk file chooser to None if nothing is set in - configuration - * [#1976] Add codec and conference documentation - * [#2209] Fix recording in regard of resamling - * [#2297] Update .gitignore - * [#2297] Update translation files - * [#2297] Add reference to our coding standards - * [#2297] Remove old docbook code - * [#2296] Reinit tls account settings after modification - * [#2253] Add DcBlocker class to remove capture's dc offset - * [#2034] Fixes for TLS transport to initialize - * [#2284] Add silent build rule + client clean warnings - * [#2274] Fix unserialize history items in cilent at startup - * [#2274] Complete display name parsing and displaying - * [#2274] Parse the Display Name in sip INVITE message - * [#2050] Fix capture volume control in ALSA - * [#1970] Volume controls disable when using pulseaudio - * [#1970] Disable volume controls when using pulseaudio - * [#2277] Fix direct ip2ip ZRTP enabling/disabling in ip2ip - preferences - * [#2181] Added launchpad debian files - * [#2181] Added spec files for OSC - * [#2274] Set display name for "Contact" sip header as the hostname - * [#2181] Fixed daemon issues - * [#2181] Fixed gnome client issues - * [#1976] Remove warnings - need to fix the transfer - * [#2006] Add init is_rec variable in ManagerImpl - * [#2006] Update codec display on call selection - * [#2006] Restore double click actions in history and contact calltree - (GTK) - * [#2176] use XDG_CACHE_HOME when initializing sfl.zid file - * [#1976] Fix calltree switching from history - * [#2209] (Re)Fix cache for zid - * [#2209] Clean up debug messages - * [#2209] Clean debug messages - * [#2209] Fix trasnfering a call during a conference - * [#2209] Speex decode must return the number of bytes - * [#2209] Change frameSize speex 32kHz - * [#2209] Fix speex codec framesize - * [#2209] Reinit converterSamplingRate in RTP sessions - * [#2209] Change speex ultra wide band framesize - * [#1747] Add pixmap data - * [#2252] Fix Receiving a server error 488 crashes the callee - * [#2209] Fix iax low rate packate sending - * [#2209] Clean up debug messages - * [#2209] Add resampling changes for IAX - * [#2209] Clean up resampling code - * [#2209] Fix latency introduced by pulseaudio - * [#2209] Fix initialization of mainbuffer's internal sampling rate - * [#2176] Fix upsampling buffer size in audiolayer - * [#2209] Add dynamic converter sampling rate in audiortp sessions - * [#1747] Fixes runtime warnings - * [#1747] Remove from repo - * [#1747] register our icons to be used as stock icons - * [#2209] Fix number of byte in alsa's write to speaker - * [#2209] Fix putting non-resampled data in RTP's mainbuffer - * [#2209] Add alsa resampler - * [#2209] Add a samplerate converter in PulseLayer - * [#2209] Add mainbuffer's internal sampling rate and flushall method - * [#2176] Add mainbuffer stateInfo debug method - * [#2209] Resampling is optimal using SRC_LINEAR not SRC_FASTEST - * [#2176] Remove debug recordings - * [#2176] Fix Holding a conference participant on new calls - * [#2224] Add confID in callable object - * [#2176] Fix putting onhold a call participating to a conference when - pressing new call - * [#2176] Reset auidio buffers when adding streams (rtp, audiolayer) - * [#1976] Use xml to describe toolbars - Add a naviguation toolbar - * [#2176] Remove conference default_id in joinParticipant - * [#2176] Display error message in alsa's snd_pcm_avail_update call - * [#2176] Alsa mic avail data debug - * [#2176] Add some debug message for mic loss problem - * [#2176] Flush mic ring buffer when offholding a call - * [#2176] Reset ringbuffers' readpointer when adding main participant - * [#2176] Fix getAvailData algorithm - * [#2176] Reset ringbuffer's readpointer when adding a new participant - to a conference - * [#1744] Regex object renamed to Pattern. Previous attempt at - providing - * [#2176] Fix detach main participant problem when adding new one - * [#1976] Use right domain to translate - * [#1976] Add xml menu description - * [#2176] Store a list of confernece participant in client - * [#2176] Fix add participant, joinparticipant methods - * [#2181] Do not install dbus-c++ headers + add return value - * [#2176] Fix minor call handling instabilities - * [#2174] Fix incoming IP call contact address - * [#2211] Add test to protect NULL pointer - * [#1163] Add Advanced account configuration section - * [#2176] Add some usefull comments and debugging info - * [#2176] Add conditions to display security icons in conference - * [#2176] Fix detaching one participant while keeping communication to - others - * [#2176] Reenable userActive.svg in call tree - * [#2176] Make user active blue (not red) - * [#2176] Fix user active picture - * [#2176] Fix "hidden" merge conflict in sipvoiplink - * [#2176] Remove iax audio stream on peer hungup - * [#2174] Multiple UDP transports functional (TESTED with 2 accounts - and 3 calls) - * [#2176] Fix fix audio stream binding in iax - * [#2174] Create a default UDP transport + use tp selector for dialogs - also - * [#2176] Register iax audio stream in mainbuffer - * [#2176] Fix getAudioCodecName in IAXvoipLink - * [#2176] Fix iax account init - * [#2176] Handle multiple account using the same sip transport - * [#2165] Add .png files - * [#2176] Small fixes concerning dtmf - * [#2176] Fix make uninstall in codecs - * [#2174] remove stund makefile generation - * [#2176] Add conference lock - * [#2174] Add transport selector for multiple accounts - * [#2176] Change userActive picture from red to blue - * [#2176] Fix security pixbuff in calltree - * [#2176] Replace sfl.zid in .cache/sflphone instead of .sflphone - * [#2176] Fix add call description - * [#2176] Remove detach button from toolbar - * [#2176] Fix calltree call description state and state code in - conferences - * [#2176] Fix pulse audio double free - * [#2176] Fix conference selection - * [#2174] Clean up - remove stun settings in client network - configuration panel - * [#2174] Remove voviva stun code - * [#2174] Rsolve STUN with pjsip - DO NOT WORK - * [#2165] Add user svg - * [#2165] Debugging sip call failed - * [#929] Link against uuid if installed - * Oops - * Fixed bugs related to libsexy (with GTK < 2.16) - * [#929] Remove uuid-dev dependency in the core - * [#2165] Debugging no negociated codecs at communicatio start - * [#2165] Fix calltree bug (gtktreestore instead of gtkliststore) - * [#2165] Fix several merge problems - * Updated opensuse packaging script - * [#1163] Add missing figures - * [#1163] Update INSTALL file - * [#2165] Fix IAX - * [#2165] Add recordabe interface - * [#2165] Finish recording refactoring for call (not for conference) - * [#2165] Enable speaker recording for two different calls - simultanously - * [#2165] Implement call recording using the Recordable interface - * [#2165] Add get and set to AudioLayer's audio recorder - * [#2165] Add class recordable from which inherit call and conference - * [#2006] Fix G722 and Speex 8khz codec conferencing - * [#2006] add recording of audio buffers - * [#1163] Add general settings section - * [#1163] Fixes makefile error - * [#2006] Fix some minor issues - * [#2006] Drag a conference call on another conference call - (difference conferences) - * [#2006] Fix dragging a conference on itself - * [#1744] Integrating some of the needed regular expression patterns - in order - * COmplete call features - * [#1744] Added support for named subgroup in the Regex object. Also, - new - * [#1744] Adds thread safety features, compile() and setPattern() - methods to the Regex class. - * [#1744] Fix inconsistency in the finditer method from the last - commit. - * [#1744] Added regex pattern object built on top of libpcre. To be - used - * [#1744] Initial commit towards implementing RFC4568. Unimplemented - in the - * [#2157] Hide "security" and "advanced" tabs for IAX under account - * [#1163] Add call features section - * [#2006] Add joinConference capabilities - * [#2006] Add dbus joinConference signal - * [#2006] Drag a conference call onto a conference to add it - * [#1163] Add addressbook section - * [#2006] Drag a conference call onto a single call to create a - conference - * [#2006] Expand rows automatically - * [#2006] Add minimal multiple conference handling - * [#2006] Add atached/detached conference icons - * [#2006] Add function processRemainingParticipant - * [#2006] Deep refactoring, fix hangup bug - * [#1163] Update documentation - Accounts part - * [#1976] Integrate user doc to gnome client build system - * [#2122] Remove double inclusion in dbus-c++/src/Makefile.am - * Remove pjproject version number - * [#2006] Fix peerHungup - * [#1976] Make Yelp accessible from the GNOME client (need to install - the sflphone.xml first) - * [#2006] Fix multiconferencing hangup - * [#2006] Fix hangup calls in a conference - * [#2150] Make IAx2 reappear - * [#2006] Fix detach participant on multiple call - * [#2006] Can remove rining call from a conference - * [#2006] Reinit confID when removing a participant - * [#2006] Remove get isCurrentCAll in hangup/peerhungup (SipVoipLink) - * [#2006] Fix refuse call - * [#2006] Fix answerring incoming call - * [#2006] Refactor conference's participant list - * [#2101] Re-integrate test compilation in main build system - * [#2101] Make the test directory compile - * [#2136] Restore history functionality - * [#2006] Fix binding main participant to himself - * [#2006] Fix add current/incoming/onHold participant to an existing - conference - * [#2006] Fix add incoming calls to an already created conference - * [#2006] Fix remove stream - * [#2006] Fix detachParticipant/removeParticipant switchCall ids - * [#2006] Fix adding a call in conference having state "CURRENT" - * [#2006] Remove/add main participant from conferences - * [#2006] Hold/unHold conference - * [#2006] Detach a partcipant from drag n drop - * [#2006] Hangup a conference - * [#2006] Add hold/unhold conference dbus messages - * [#2034] gtk-ui fix under the "basic" tab. - * [#2006] Fix dragging calls on conference calls - * [#2006] Fix detach participant from a conference - * [#2034] Added default message is status bar under the account config - dialog - * [#2112] Fix a crashed caused when a non-md5 password was sent to - pjsip. - * [#2006] Detach participant by ID - * [#2006] Fix addParticipant method in managerImpl to handle - incoming/answered calls - * [#2006] Add addParticipant method in managerimpl and related dbus - messages - * [#2111] Added the ability to configure zrtp on sip.sflphone.org from - * [#2106] Fixed problem in the account assistant under gtk-ui. Also, - assistant.c - * [#2006] Fix dragging a conference call on another conference call - (same conference) - * [#1904] Small UI fix. Assistant was moved from "Call" to "Edit" - menu. - * [#1904] Fix a wrong label under gtk-ui. - * [#2034] Renaming and source code splitting. - * [#2034] Status bar added to account window to better reflect the - registration - * [#2006] Make calltree_remove_call recursive (for GtkTreeStore) - * [#1110] Small gtk-UI fix in the account window (alignment). - * [#2006] Fix remove conference, display children which are still - active - * [#2006] Recursive function call in calltree_update_call - * [#2006] Add multilayered capabilities to calltree (GtkTreeStore) - * [#2006] Implement remove conference in calltree - * [#2034] Now useless as Direct Ip calls settings moved under - Preferences. - * [#2034] Edit/add buttons were set insensitive all the time under - gtk-ui. - * [#1887] Information about the state of the current SIP call is - displayed - * [#2006] Add call tree remove callback - * [#2006] Fix create_conference function - * [#2006] Update conference_added_cb to add new conference to the list - * [#812] Added new tab under GTK-ui Preferences. Moving Direct Ip - Calls from - * [#2121] Disable temporarily test compilation - * [#2006] Fix conferencelist to handle conference_obj_t instead of - gchar - * [#2006] Add conference_obj structure - * [#2121] Update version - * [#2006] Fix conference selection - * [#2101] Use the new source tree to fetch the right object files - * [#2006] Add conference in calltree - * [#2006] Add Dbus signal conference added/removed/changed - * [#2006] Add getConferenceDetails call on dbus - * [#1904] Registration expire now appears as a spin box under gtk-ui. - * [#812] Fixing a segmentation fault caused by a non-existing account - ID - * [#2006] Add getConfList method over dbus - * [#2006] Add a conferencelist data structure in client-gnome - * [#812] Defaults value are now sent if a non-existing account is - requested - * [#2006] Add sflphone action sflphone_join_participant - * [#2006] Fix buffer read pointer problem deletion - * [pjsip] Attempt at fixing via header incompatibility with - Freeswitch. - * [#1797] forget something - * [#2006] Add call new state conferencing in deamon - * [#2006] Remove addParticipant method for conference, use - joinParticipant only - * [#1163] Update INSTALL documentation - * [#812] Msec/sec values were not taken into account. - * [#1797] Make pjproject-1.4 compile - * [#2006] Add Detach participant method - * [#2006] Dragndrop fully functional with INCOMING and HOLD call - * [#1797] Add pjproject-1.4 - * [#1797] Remove pjproject-1.0.3 - * [#2006] Get call state in conference related function - * [#2006] Add joinParticipant (conference) method in ManagerImpl - * [#2006] Add joinConference DBUS message - * [#2006] Store the previously selected call_id on dragndrop - * [#2006] Fix GValue pointer unref in selection callback - * [#2006] Store dragged call_id - * [#2006] Update drag_data_received_cb callback to manipulate CallIDs - * [#2006] Add dragndrop signals - * [#2006] Set calltree reordable - * [#812] Adds the ability to create a TLS listener in case the user - requests - * [#812] Adds the ability to configure local/published address from - * [#1883] Move switchCall in onHoldCall function - * [#812] Deals with the published address/port problem when - integrating TLS. - * [#1883] Switch call id in managerimpl when peerHungUp - * [#1883] Switch call id before hangup - * [#1883] Add usefull and permanent debug info for conference - cretion/deletion - * [#812] Fix various segmentation faults related to Direct IP kind of - calls. - * [#1883] Fix deletion of std::map elements using iterators - * [#2014] Add libzrtpcpp build dependency - * [#1883] Still some for loop test ambiguity (while loop instead) - * [#1883] Fix for loop initial test ambiguity (use while loop instead) - * [#1883] We must discard data in urgent ring buffer if data is get in - mainbuf - * [#1883] Fix availForGet same id for ringbuffer and readpointer - * [#812] Match "sips" as a Direct IP Call when the user enter a sip - uri - * [#812] Fix segmentation fault related to SIP URI creation. - * [#812] Towards integrating multiple tls listeners at the same time. - This - * [#1883] Add debug messages in conference and fix mainbufferTest - * [#812] gkt-ui fix. Private key must be fed as a filename and not as- - is. - * [#812] TLS integration within sipvoiplink and pjsip. Also, - configure.ac - * [#1883] Fix Alsa/Pulse mallocation - * [#1883] Fix data corruption in AudioRtp's micData buffer - * [#812] Full dbus integration for all the tls related options under - gtk-ui. - * [#1883] Fix memory leaks in audiortp session - * [#1883] Fix mem leaks in audio rtp - * [#812] Fix setAccountDetails where TLS_ENABLE was set to the value - * [#812] Small gtk-ui fix. - * [#811][#812] Small gtk-ui fix. - * [#812] Introduced a mechanism for configuration files that makes - possible - * [#812] New dbus bindings added. Also, configuration compliance was - enforced - * [#1881] Remove default buffer from MainBuffer (update unit-tests) - * [#1881] Add ring buffer read pointer tests - * [#1883] Fix issues in ringbuffer reader pointers - * [#2034] Implementing a new configuration dialogue for TLS transport - settings - * [#1883] Add some usefull debug and safety checks - * [#2028] Notify the client with libnotify when the zrtp negotiation - failed. - * [#811] Harmless no to throw an exception, an makes the application - less - * [#2028] A minidialog is showed to the user under sflphone-client- - gnome - * Removed useless file. - * Ignoring Makefile in src/widget - * [#2027] Fix segmentation fault when showMessage callback is called - after - * [#2026] keyExchange was set to ZRTP instead of "1" - * [#2024] Fix the wrong summary at the end of the assistant. - * [#1883] Fix mnagerimpl conference map insertion - * [#1883] Add Mutexes in MainBuffer - * [#811] Gtk ui was not presenting the right information about zrtp - for - * [#2023] security icons were not installed in sflphone-client-gnome. - * [#2021] Fix a mistake in the readme from sflphone-common that gives - wrong - * [#811] The current SRTP mode was not properly displayed for the - IP2IP - * [#1743] Re-implementation of the "automatically remove error dialogs - [...]" - * [#2017] [#2019] Fix the inability to dial a number and place a - registered - * [#811] Final re-integration of ZRTP support in the main branch from - 0.9.6 - * [#1883] Fix map insertion methods - * [#811] Combo box now is now set to the active key exchange method - * [#811] ZRTP options now configurable back again from the Gtk UI. - IP2IP - * Updated hostname for git clone - * [#1883] Add minimal functionalities to create a conference - * [#811] re-integration of all the methods and signals on dbus. - ManagerImpl - * [#811] Got out of a precarious position were nothing would compile. - * [#1976] Build documentation squeleton with docbook - * [#1883] Add sflphone-client "addParticipant" button for conference - * [#1994] Better organize the source directory structure. New - subdirectories - * [#1883] Add a simple Conference class - * [#1882] Use static audio buffer in Pulse and ALSA layer (instead of - malloc) - * [#811] First commit toward re-integration and refactoring of ZRTP - * [#1882] Flush RTP ring buffer before entering mainloop - * [#1882] Fixed MainBuffer::UnBinCallID() in case there is no - ringbuffer - * [#1882] Test (and fixe) high level conference and mixing - functionalities - * [#1772] Apply patch to compile on fedora (sent by Marcin - Zajączkowski <mszpak@wp.pl>) - * [#1882] Update Bind, unBind call_id in MainBuffer - * [#1959] This adds the ability to store password as an MD5 Hash in - the - * [#1538] Fixes rules compilation - * [#1930][#1931] Fixed a mistake (again) related to index and - credential count - * [#1753] Remove ILBC from pjproject - Hacks in pjsip - * [#1930][#1931] Credential was not selected properly using realm - * [#1882] Finilize multiple reading pointer in RingBuffer - * [#1538] Remove configure from autogen.sh to respect debian upstream - authors policy - * [#1773] Remove generated files from repo - * [#1791] Use XDG_CACHE_HOME to save pid file - * [#1791] Fixes path to save history - * [#1791] Fix debian installation scripts - * [#1930][#1931] Settings are now taken into account in the server. - * [#1882] Add ringbuffer default ring buffer pointer in methods - involving mStart - * [#1882] Add default ringbuffer pointer - * [#1882] Add RingBuffer multiple read pointer basic functionnalities - * [#1882] Fix MainBuffer flushData unit test - * [#1930][#1931] Ability to save and retreive the configuration from - * [#1882] Added Multiple CallID mapping to MainBuffer - * [#1791] Not much - * [#1791] If XDG env variables are not null but empty, use default - ones - * [#1791] Make XDG_CONFIG_HOME writable - * [#1930][#1931] Partial commit. Not working yet. Cannot delete - account - * [#1881] Fixed alsa capture latency problem - * [#1881] Fixed Alsa capture temporarily - * [#1930] [#1931] Partial unbroken commit providing the ability to - * [#1881] MainBuffer implemented in AudioLayer/AudioRTP - * [#1881] Add discard and flush unit-tests - * [#1881] Add discard and flush functionnalites to MainRingBuffer - * [#1881] Add availForGet in MainBuffer - * [#1881] Add availForPut function to MainBuffer - * [#1880] Remove AudioRTP* pointer from SipVoIP (reapered while - merging master) - * [#1881] Add a map between call id and coresponding ring buffer - * [#1855] Refresh pot file and upload on Launchpad - * [#1881] MainBuffe now robust to false ids on getData and putData - * [#1881] Fix big big big memory leak - * [#1881] Add getData and putData to mainBuffer - * [#1881] Unit-test basic ring buffer functionnaities - * [#1881] Add class MainBuffer and basic buffer creation unit-tests - * [#1880] Fix call transfer (step2) issues - * [#1880] Moved AudioRtp* pointer from SIPVoIPLink to SIPCall class - * [#1791] Add postinst script to keep user data when migrating - config/history file - * [#1797] Make pjsip compile - * [#1777] Code indentation - * [#1791] Use XDG_DATA_HOME and XDG_CONFIG_HOME for sflphonedrc and - history + unit tests - * [#1746] Useless space does not appear anymore when volume sliders - and - * [#1643] GtkCheckMenuItem is used instead of icons for elements in - the - * [#1110] [#1668] STUN parameters are now located in the preferences, - under - - -- Julien Bonjean <julien.bonjean@savoirfairelinux.com> Fri, 06 Nov 2009 11:23:15 -0500 - -sflphone-client-kde (0.9.6-SYSTEM) SYSTEM; urgency=low - - ** 0.9.6 ** - - * Documentation on echo test - * [redmine_down] codec names not displayed in total - * [redmine_down] crash when hanging up a dialing call because tries to - add it to history whereas no starttime - * [#1927] alternate every time screen changed to call history - * [#1886] clean code - * [#1886] debug messages when loading history removed - * [redmine_down] sflphone-kde icons - * [#1855] Update language files - * [#1502] Update version number - * [redmine_down] setHistory at close - * [#redmine_down] Handle PJ_DECLINE_SC as failure - * [#1923] Fix segmentation fault when adding a new account - * [#1923] Check on iterator before setting the config - * [#1904] Added mnemonic to tabs in sflphone-client-gnome. - * [#1905] The daemon was not sending the currentSelectedCodec signal - on dbus when answering a call. - * [#1922] Default values set to all account details - * [#1886] Spinbox reg expire enables apply, and address book is not - visible when disabled - * [#1905] Bug fix for segmentation fault caused by an empty string, - * [#1910] Warnings in test directory - * [#1919] Error fixed - * [#1855] Update russian translation - Hussein Abdallah - * [#1910] Remove files - * [#1919] fixed - * [#1777] Code indentation - * [#1918] fixed - * [#1917] fixed - * [#1910] Remove warnings compilation in src - * [#1886] removed AccountListModel in configskeleton - * [#1914] - * [#1911] check previous and new port - * [#1910] Remove compilation warnings in src/dbus and src/history - * [#1910] Remove compilation warnings in src/audio - * [1855] Update german translation - Sven Werlen - * [#1909] removed - * [#1906] Done - * [#1904] The registration expire value is now configurable from the - * Cleaned up debug messages. - * [#1886] separated initCallItem in two functions - * [#1886] reversed error in commit - * [#1886] clean debug - * [#1886] changed Name of classes and files - * [#1886] clean - * [#1870] In call_state_cb (dbus.c:126), _time_stop was overridden by - the actual time. - * [#1884] Added some new gpg flags to prevent tty warnings - * [#1886] Clean audio config dialog - * [#1886] No more compile warnings. + 1 comm - * [#1872] Check if the user input is smaller than PJ_MAX_HOSTNAME. - * [#1886] - * [#1785] Fixed build when no new commit - * [#1852] If chosen by the user, the hostname can now be solved and - used - * [#1871] * and # inverted back - * [#1869] Conditional compilation that checks if - * [#1309] removed test in main - * [#1425] Put actions in SFLPhone window class instead of ui view, - made a separate toolbar for screens. - - -- SFLphone Automatic Build System <team@sflphone.org> Mon, 27 Jul 2009 09:53:00 -0400 - -sflphone-client-kde (0.9.6~rc2-SYSTEM) SYSTEM; urgency=low - - ** 0.9.6~rc2 ** - - * [#1755] Remove generated file - * [#1753] restore ilbc ... - * [#1866] Methods getSipPort and setSipPort now have an effect on the - * [#1753] make pjsip compile without ilbc. Use ./autogen.sh --disable- - ilbc-codec - * [#1855] Fix error in russian translation - * [#1805] Remove the old flawed signal mechanism which was failing in - * [#1855] Refresh translation - * Spanish translation finished + po README files updated + echo's in - copy-in-clients - * [#1850] Yun made the chinese HK-CN translation - * [#1848] Fix transfer interface bug - * [#1862] At install, kde client installs only french translation file - * [#1841] A new fallback mechanism was added to the internal resolver - in PJSIP. - * Started AccountList model/view - * [#1855] Remove po subdir in Makefile.am - * [#1855] Fix typo error in sflphone-client-gnome - * [#1855] Do not generate Makefile in sflphone-common/po - * [#1855] Copy translation files into both clients dirs - * [#1855] Remove po dir from sflphone-common - * Comments added - * [#1860] mailbox->voicemail... - * make scripts executable - * [#1855] French translation - * [#1855] Chinese zh_HK partially filled... - * [#1859] An unnamed pipe monitored by poll() was added. When we want - to - * [#1855] Sven completed the first part of the german translation - * [#1855] Cantonese manually filled for already translated, almost - equal strings - * [#1855] Merge russian translation - * [#1855] Spanish manually filled for already translated, almost equal - strings - * [#1855] Update german translation in ./lang/de - * [#1858] This problem was fixed by removing a useless line in - * [#1855] merged existing translations in lang/ sflphone.po's - * [#1842] [#1843] An attempt at improving the expected behaviour that - can't - * [#1855] added po folder in gnome client and scripts for copying from - common lang folder to clients - * [#1853] Edit before call does nothing on call history - * Put most language entries possible in common. From 300 to 250 - entries. Stays underscores problem. Scripts for copy in clients. - * commit to merge master - * [#1825] Changed "Bad authentification" to "Authentication Failed". - * common po files - * [#1753] Remove ILBC from pjproject - - -- SFLphone Automatic Build System <team@sflphone.org> Fri, 17 Jul 2009 19:12:44 -0400 - -sflphone-client-kde (0.9.6~rc1-SYSTEM) SYSTEM; urgency=low - - ** 0.9.6~rc1 ** - - * Update some version number - * [#1792] Creates .sflphone directory with permission 600. Also, - "chmod 600" after - * [#1810] GUI is now notified that the call failed. Also, a segfault - was - * [#1816] Address book search disabled when disabled address book and - enabled it back plus button stays triggered - * codeclistmodel + asynchronous loading of address book + - enable/disable address book - * [#1810] Now checking SDP answer after 200 OK. Still need to - implement full - * [#1794] Can't use the interface during a call - * Updated translation files - * Russian translation integrated - * Codec list model/view started. - * [#1807] Add configure.ac in pjproject-1.0.3 - * [#1787] closeRtpSession added in some places where it should have - been - * Use Item class for contacts and accounts - * Comments + clean code - * [#1794] Improved debug messages - * [#1805] Replaced the old and unreliable mecanism that was was - waiting for - * [#1794] Can't use the interface during a call - * [#1787] For those cases where no registered SIP account is - configured - * [#1797] Make pjsip compile - * [#1787] Minor changes. Removed useless commented line. Changed order - of - * [#1777] Code indentation - * [#1797] Update package generation with new pjsip version - * [#1798] Does not hang up when the call is building up - * [#1797] Update .gitignore with new pjsip version - * [#1797] Remove generated files from repo - * [#1797] Main build system now uses pjproject-1.0.3 - * [#1797] Add pjproject-1.0.3 - * [#1797] Remove pjproject-1.0.2 - * [#1796] Computing time optimization (samplerate conversion) - * [#1787] _audiortp->start() moved away from offhold(), - SIPCallAnswered() - * [#1312] Added new states for calls initialized by other clients - * [#1795] Crashes when adding a new account, checking it and applying - * [#1782] Missing icons - * [#1793] KDE client compilation problem - * Fake ringtone files can no longer be set. - * indentation - * [#1312] Able to fetch to differentiate incoming/ringing call state - * [#1784] Use DESTDIR variable in po Makefile - fix language file - installation - * [#1785] Fixed typo - * [#1785] Fixed changelog update - * [#1759] ./autogen.sh --prefix=/usr --with-debug to use optimization - level 0 - * [#1773] Changed snapshot naming convention - * [#1773] Removed gpg agent use, added repository cache cleaning - * [#1759] Use optimization level 0 for repository, 2 for packages - * [#1777] Code indentation/formatting - * Translated new features in french - * [#1785] Added missing changelog entry - * [#1781] Window title is SFLPhone - * [#1777] Add code indentation/formatting in the buil system - * [#1774] Can't set voicemail number in KDE account creation wizard - * [#1775] Can't modify account information for account created with - the wizard - * [#1771] Add a "Default" button in context menu to disable chosen - prior account - * [#1705] - * [#1224] Remove generated file from the repo - * [#1224] Remove generated file from the repo - * [#1762] distclean target should remove kconfig generated files - (settings.h, settings.cpp). Rename them? - * [#1761] clear history button should really clear history - * Dialpad works. - * Implemented Dialpad widget instead of building it in main view. - * Removed last occurence of the old config dialog, that made the build - crash. - * [#1755] Do not consider G722 as a dynamic payload elsewhere than in - RTP layer - * [#1753] Remove ilbc Makefile generation - * [#1756] Implement a kde configuration dialog with kconfig xt and - kconfigdialog class - * [#1755] fix audiocodec folder parsing problem - * [#1450] Reinit timestamp comparison in RTP, create session in - newOutgoingCall - * [#1753] Remove milenage third party code from pjsip - * New Config Dialog integrated in GUI.(without codecs) - * [#1753] Remove ILBC codec - * kconfig started, tr2i18n -> i18n, icons folder, accountList changed - * [#1705] Fixed Audio RTP thread creation/start - * [#1714] Fix codec negociation result handling - * [#1678] Fix audiortp payload setting - * [#1678] Put bac putData method in rtp - * [#1669] gtk_file_chooser_get_filename() support UTF-8 by default - * [#1735] Add conditions to sdp update call if call declined - * [#1737] substr of recordings destination folder to remove "file://" - should be done in client rather than in daemon - * [#1731] Enlarge audio stream buffer size - * [#1714] Missing true - * [#1317] Fixed Mandriva timeout - * [#1317] Changed tag convention - * [#1317] Cleaned git-dch - - -- SFLphone Automatic Build System <team@sflphone.org> Fri, 10 Jul 2009 15:49:56 -0400 - -sflphone-client-kde (0.9.6~beta-SYSTEM) SYSTEM; urgency=low - - ** 0.9.6~beta ** - - * spec files for mandriva and opensuse updated with buildrequires - libqt4-dev >=4.3 - * [#1700] Cannot build on ubuntu 8.10 and a few other distribs - * [#1502] Update version number where applicable - * [#1642] Update client icons - * [#1450] Clean up useless debug and comments in sipvoiplink and - audiortp - * [#1450] Remove Semaphore object in AudioRtp thread deletion - * [#1450] Audio RTP init now synchronized with Sip/SDP - * [#1693] kde client crashes when changing codecs order/activation - * [#1450] Deep refactoring of audiortp - * [#1450] setRtpSessionRemoteIp - * [#1689] getCallList at start - * [#1224] Change path in package files - * [#1450] Audio RTP initialized only once, payload and remote ip set - at runtime - * [#1450] Add setRtpSessionMedia and setRtpSessionRemoteIp address - * [#1642] Make GNOME GUI fresher and younger ;) - * [#1686] Status bar displaying used account - * added sflphone-kde icon so that it compiles - * [#1659] Ending a call causes the daemon to crash - * corrected introspection XMLs, po files... - * [#1211] g722 media descriptor in codecDescriptor - * [#1310] Install sflphoned in $(prefix)/lib/sflphone - * [#1502] Do not install test binaries and dbus utilitaries - * [#1224] hack for pjsip build system! - * [#1224] Remove pjsip binaries from repo - * [#1224] Upgrade to pjsip 1.0.2 - * [#1658] About SFLphone (bugs) - * [#1658] About SFLphone - * [#1660] Displaying all dialed numbers in a call - * Tested status bar. - * [#790] Optimize pulse audio streams parameters - * [#1678] Some usefull debug messages for mutex/semaphore deadlock - problem - * [#1669] Add/remove some usefull/unusefull debug - * [#1665] Fix latency related to pulse audio stream openning/closing - * [#1457] Make the menus and panels accessible in french - * [#1457] Improve broken keyboard accessibility in menus and conf - panels - * [#961] Instanciate only once the searchbar icons - * [#961] Restore transfer fonction - * [#961] Filter on the history type OK - * [#961] Fix compilation problems on hardy/intrepid - * [#1157] Commit missing files - * [#790] Reduce number of start/stop streams call on pulse audio - * [#1639] kde client crashes when no account registered - * [#1620] Fix the searchbar - * [#1620] Get back caltree as it was during gtkcritical area - * [#1620] Add history filter reinit function - * [#1335] Add a missing label in address book preferences - * [#1561] Update russian translation - Hussein Abdallah - * [#1605] Fix edit menu french translation - * [#961] Enable to search in the history according to the call type - * [#1449] Searchbar does not work anymore - * [#961] Add popup menu on the entry primary icon for history - * [#1317] Fixed KDE client package dependency - * [#936] speex 32 khz integration completed - * [#936] Use 320 frame size - * [#936] Test using a frame size at 320 smpls - * [#1214] Enable / Disable history - * [#1607] Fix compilation problem for ubuntu 8.10 (libsexy) - * [#1313] Implement processDataEncode processDataDecode in audiortp - * [#1613] codec list order can't be set - * Better handling of localisation + added languages + corrected - warnings + begginning of new config dialog with kconfig + 14px - account leds - * [#1214] Save and load history according to the limit timestamp + - unit tests - * [1609] Fix call number copy/paste feature - * [1607] Restore clear action icon in searchbar - * [#936] Try to decode using 1280 samples - * [#936] Add some debug - * [#936] Add .cpp file - * [#936] Oops Forgot speex 32 khz - * [#1214] Add configuration panel for history + D-Bus calls - * [#1313] Test rtp thread function, frame size, nbbytes, resampling - * [#790] Flush audio data before closing audio streams - * [#1214] History displays local time - * [#1214] Skip empty field on display - * [#1214] Associate an account to an history entry - * [#1342] Get addressbook options sensitive/non-sensitive - * [#1211] Clean up and comments - * [#1211] Get back to 20 ms framesize - * [#1211] Use sendImmediate instead of putData in RTP - * [#1211] Fix nb byte available in RTP - * [#1211] Clear condition on maxNbSamples in RTP - * [#1211] Fix max byte available in RTP session - * [#1211] G722: Use 160 samples per frame instead of 320 - * [#1211] Test using a dynamic payload - * [#1211] Test using a dynamic payload type - * [#1211] Rename size variable (nb_samples, nb_bytes) - * [#1211] Test g722 ip-to-ip sending twice the data lenth - * [#1211] Test g722 ip-to-ip - * [#1214] Do not select an history item by default at startup - * [#1214] Remove some compilation warnings - * [#1214] Handle empty field - remove g_print - * [#1214] Add each history item only once - * [#1214] Handle call timestamps properlier - * [#1214] Do not need timestamp files anymore - * [#1214] Use the saved date for history entry - * Clean up - * [#1214] Client doesn't crash if the D-Bus call fails - * [#1214] Client is able to save its history - still some glitches - * [#1211] Forgot 16000 for g722 - * [#1211] G722 initialization - * [#1214] Save name/number, successfully load the history if no fields - are empty - * [#1499] Fixed destination directory bug - * [#1214] Restore all the functionalities; peer name/number way more - easy to handle !! - * [#1214] Add callable_object instead of call_t, refactoring - * [#1211] Test with polycom soundstation 16000 - * [#1211] Remove C like inline function in g722 codec - * [#1342] Finalize gnome client preference window formating - * [#1214] Retrieve the history when the gnome client startsup - * [#1306] Implement localization for KDE client - * [#1593] enable accounts apply button when account checked/unchecked - * [#1214] Implement the dbus calls on server side - * [#1214] Add serialized/unserialized functions to pass data on DBUS - * [#1342] Formating gnome client configuration windows - * [#1214] Save sucessfully a map of history items - * [#1499] Removed multiple jobs compilation for KDE client (2) - * [#1214] Load history from file into memory, add unit tests - * [#1534] Throws a length_error exception in case URL exceeds - std::string max_size - * [#1499] Removed multiple jobs compilation for KDE client - * [#1565] make account leds smaller - * [1430] Fix dbus debug - * [#1562] crashes when trying to change item of a call of state "OVER" - * [#1116] Fix compilation bug - * [#1317] Added mandriva and opensuse-11 64 bits - * [#1108] Add messges in main window concerning transfer success - failure - * [#1116] Fix compilation problems - * [#1211] g722 Makefile - * [#1108] Client side transferFailed/trasferSucceded signals handling - * [#1211] G722 mostly completed, - * [#1555] make bigger toolbar (24x24) - * [#1551] remove default mailbox number in wizard and disable mailbox - button when first account doesn't have mailbox number - * [#1342] Re-add sflphone manpages - * [#1116] Fix compilation on non-jaunty distros - * [#1317] Fixed opensuse startup sleep - * [#1108] Add a signal in the client to notify successful or failed - transfer - * [#1108] Dbus signals concerning call transfer success/failure - * [#1317] Added opensuse to automatic build system - * [#1223] Fix manpages bug - * [#1060] german translation glitch - * Clean up some gnome client warnings - * [#1547] replace ugly account leds by beautiful icons - * [#1548] add close button that hides windowand just hide on clicking - the cross - * [#1549] put introspec XMLs in the client's source - * [#1312] Implement getCallList D-BUS method - * [#1116] Clear text in history and contacts - * [#1499] KDE integration - * [#1469] Modify header linkers in dbus-c++'s Makefile.am's - * [#1469] Remove examples folder from dbus-c++ - * [#1214] History integration in build system; unit test squeleton - * [#1317] Cleaning - * [#1469] Remove configure stuff in dbus-c++ - * [#1469] Add unofficial mainline dbus-c++ - * [#1469] Remove dbus-c++ from freedesktop - * [#1430] Bring account changed signal/callback back to normal - * [#1060] Update german translation - Sven Werlen - * [#1430] Add marshaller one string define - * [#1430] Send account change signal broadcast using account id - * [#1430] Remove condition on setRegistrationState, cause stun to - crash - * [#1317] Centralized version handling - * [#1317] Fixed version number on sfl-git-dch - * [#1317] Refactoring for new distributions - * [#1215] Fix account order at startup if latency - * [#1088] Restore sip dns srv - * [#1214] Add squeleton for history manager - * [#1430] Add accout id to accout changed method - * [#1430] No connectionStatusNotification (account changed) if no - changes - * [#1538] Add COPYING file - * [#1430] Add audio rtp thread tests - * [#1317] Changed version detection - * [#1538] Document license in libs/stund - * [#1317] Added version files - * [#1538] Apply François patches - debian packages - * [#1317] Updated spec files - * add files - * [#1538] Apply François patches - debian packages - * [#1535] Change program file structure (directory src...) - * [#1317] Updated build system scripts - * [#1317] Cleaning - * [#1317] Copied introspect files to gnome client - * [#1317] Added opensuse to build-system : first-shot - * [#1317] Remove spec files from configure - * [#1317] Added missing prefix - * removed debug for daemon account fix - * [#1430] Add a connection reference which most likely belong to - libdbus - * [#1430] Use shared connection instead of private - * make daemon find the account, added userMatch - * Clean code, add comments... - * [#1317] Fixed packaging rules - * [#1317] Updated autogen - * Updated autogen.sh for pjsip - * [#1526] Set accounts order - * [#1317] Fixed pjsip lib dirs - * [#1317] Updated debian packaging for new pjsip configuration script - * [#1317] Switch to autogenerated guess and sub files - * [#1317] Updated pjsip inclusion in build system - * [#1317] Replaced pjsip guess and sub files - * [#1317] Fixed compilation issues on opensuse 11 - * [#1505] account list seem to crash the application when clicking - Apply very fast... - * [#1456] Add a flag to be replaced in the control files - * [#1456] Added version dependancy handling - * put account alias in AccountWidgetItem rather than in the item with - " " before. - * [#1034] The KDE client should start sflphoned if it is not started - * [#1500] Handle options for notifications and display on incoming - call. - * [#1443] Client should not crash when receive an unexpected - stateChanged signal - * [#1403] Do not stop the notification anymore - * [#1456] Added version dependancy handling - * [#1426] Daemon crashes when get alsa plugin - * [#1422] Improved error messages - * commit for merge - * [#1424] Change logo in tray icon and put a different one when - incoming call - * [#1425] first part done, window title... - * [#1413] add manpages creating and installing in build system - * [#1417] The client should start the account creation wizard if - started for the first time (if config file doesn't exist) - * [#1421] Make volume bars horizontal when dialpad is hidden. - * Changed main window title and fixed a mistake in sflphone_const.h - * [#1412] make debian package building work - * changelog changed. - * Changed addAccount method in gnome client. - * Debian and man folders added. - * [#1388] Change project name from sflphone_kde to sflphone-client-kde - * Better handle of kabc check. - * [#1351] Automatic generation of dbus interfaces in makefile - generated by cmake - * [#1307] Implement "edit before call" in history and address book. - * [#1344] change action_call label in call history from "call" to - "call back". - * [#1308] Implement Hook feature in kde client - * Improved build system. - * #1219 : Add address book configuration page - * Better handling of registration to the daemon. - * #1039 : Add tray icon in kde. - * Issue no 1216 : Double click on item in history or address book - causes call. - * display peer name in call list and call history when called from - address book. - * Address book functionnal with photo displayed. - * Help menu kde available but actions disappeared. All fonctions in - view. - * Address book functionnal but ugly and making its own sort in the - complete address book. - * Account choice on right click, clean out includes, page address - book, fixed bugs... - * Wizard, double click, context menu... - * Removed sflphone_kde.kdevelop.filelist - * Added account creation wizard and translated interface in english. - * Transfer functionnal but ugly. - * transfer not functionnal - * Bug fixed : unholding (UNHOLD_CURRENT, UNHOLD_RECORD) - * Commit functional for push. With install.sh - * Before merge. - * Problem with enable accounts. Account display increased. - * Functional with codec order working , playDTMF. - * Commit functional. - * sflphone_kde/build added in .gitignore. - * complete commit for checkout previous. - * Commit before checkout previous version to check the display - bug(little font everywhere...) - * Functionnal client. Rest : history icons, config icons and - functionalities - * commit before merge asavard for isRecording. - * Call and Automate fusion done and seems to work. - * Commiting before putting Automate class in Call class. - * Functionnal main window without recording, history, voicemail, kio - widgets. - * client kde avec kdevelop. - * Config Dialog almost finished. - * Base of QT client - - -- SFLphone Automatic Build System <team@sflphone.org> Tue, 23 Jun 2009 11:12:06 -0400 - -sflphone-client-kde (0.9.5-SYSTEM) SYSTEM; urgency=low - - ** 0.9.5 release ** - - * [#1060] FIx bug in chinese translation - * [#1313] git add rtpTest.cpp rtpTest.h - * [#1313] Add init/close rtp tests - * [#1313] Basic instanciation of the rtp layer - * [#1449] Gtk-Critical concerning history filters and new calls - * [#1400] Make the match with the hostname instead of username - * [#1324] Change status bar label for "Using %s (%s)" - * [#1403] Icon size: 60x60 px - * [#1403] Do not remove notification, improve icon quality - * [#1403] Add smaller icon for gnome notifications - * [#1403] Prevent crash when hangup && no notification - * [#1403] Remove all actions on notifications; code refactoring - * [#1451] Use stun.sflphone.org as default STUN server - * [#1060] New po files - need to be translated - * [#1060] Update french translation - Rebuild template file - * [#1456] Add a flag to be replaced in the control files - * [#1454] Make cppunit optional; remove from build deps in control - files - * [#1401] Add libexpat1-dev dependency in control files - * [#1448] Take off these ugly debug messages - * [#1448] fixed getTelephoneTone and getTelephoneFile() called - repeatedly - * [#1406] add liblog4c-dev in build-depends - * [#1409] Restore .desktop icon - - -- SFLphone Automatic Build System <team@sflphone.org> Mon, 25 May 2009 11:34:40 -0400 - -sflphone-client-kde (0.9.5-SYSTEM~rc2) SYSTEM; urgency=low - - ** 0.9.5 rc2 ** - - * [#1422] Improved error message - * [#1402] Fix pjsip build - * [#1404] Clear GTK-Critical Bug at client startup - * [#1422] Added automatic VM shutdown when building on more than one - VM - * [#1422] Fixed some issues with new changelog generation script - * [#1422] Moved distribution update to specific file - * [#1422] Dropped git-dch, replace by home made implementation - * [#1402] Fix pjsip build - * [#1404] Clear GTK-Critical Bug at client startup - * Changes for name based dbus connection - * Clean changelogs - * [#1343] Gnome: Implement a callback system to handle focus on - different widgets - * Debus Session - * Refactoring Python code, PEP8 - * [#1430] Get back dbus_g_proxy_new_for_name - * [#1430] Get back DBUS_BUS_SESSION type - * [#1430] Dbus fixed owner message binding - * Second test with DBUS owner - * [#1404] Gnome -> Preferences -> Hooks - * [#1404] Gnome -> Preferences -> Recordings - * [#1404] Call History - * [#1404] Gnome -> Preferences -> Address Book - * [#1404] IF the first notification option disable the second - notification - * Dbus with fixed owner does not automatically start the deamon - * Add codec debug tests in pysflphone - * [#1407] Some print info - * [#1407] Add a scenario to pick_up action - * Test client dbus connection to a fixed owner - * Add python dbus test suite - * [#1161] Modified version handling in build system - * [#1314] Test pulse audio and audio streams connect and disconnect - * [#1402] Add info message after configure - * [#1402] Build the daemon with the local pjsip library (vs the - installed one) - * [#1009] Fix Codec Sampling Rate set to zeros - * [#1314] Add mutex to pulse layer audio streams - * [#1314] Refactoring pulseaudio stream to test connect disconnect - * [#1314] Refactoring of pulselayer to test conect/disconnect - * Add debug messages in debus calls concerning account - * [#1314] Add some return values to audio init functions - * [#1406] add liblog4c-dev in build-depends - * [#1409] Restore .desktop icon - * Bug #1405: Fix strings as requested. - * Bug #1404: Fix strings in preferences panel. - - -- SFLphone Automatic Build System <team@sflphone.org> Tue, 19 May 2009 12:08:03 -0400 - -sflphone-client-kde (0.9.5-0ubuntu1~rc1) SYSTEM; urgency=low - - [ SFLphone Project ] - * [#1262] Updated changelogs for version 0.9.5-0ubuntu1 Snapshot 2009- - 05-05 - - [ Emmanuel Milou ] - * Add some python CLI client code; not really functional - * [#1108] Fix peerHungup method for IP to IP call - - [ Alexandre Savard ] - * [#1108] Correct setting of SIP contact for direct IP call - * [#1108] SIP user agent handles incoming REFER - - [ Emmanuel Milou ] - * Remove website from repository - * Update translation - - [ Alexandre Savard ] - * Sflphone icon's tooltip changed for "configured" instead of - "registered" - - [ Emmanuel Milou ] - * Update translation - - [ Sflphone Project ] - - -- Sflphone Project <sflphone@mtl.savoirfairelinux.net> Tue, 05 May 2009 19:16:09 -0400 - -sflphone-client-kde (0.9.5-0ubuntu1~beta) SYSTEM; urgency=low - - [ Julien Bonjean ] - * Updated Eclipse stuff - * Improved addressbook config window - * Added sflphone Eclipse stuff - * Implemented addressbook list server side - * Moved dbus stuff in dbus directory - * Updated addressbook configuration - - [ Emmanuel Milou ] - * Remove unuseful installation scripts. Use apt-get build-dep sflphone - instead - * fix bug #1090 - - [ Alexandre Savard ] - * defining speex 16khz - - [ Emmanuel Milou ] - * Remove unuseful file from build system - * Start dns srv resolver - - [ Alexandre Savard ] - * Basic ogg/vorbis initialization - - [ Emmanuel Milou ] - * Handle incoming IP-to-IP invite correctly - - [ Alexandre Savard ] - * speex wideband 16000 - - [ Emmanuel Milou ] - * Better handling of incoming IP to IP call - * DNS SRV resolution functional - * Implement IAX2 incoming URL - * Allow user to make IP call without any accounts configured - * Add a contextual menu to edit a number from the contacts tab - * Add comments, tooltip and new button to the contextual menu - * add delete event, migrate to GTK 2.16 for sexy icons - * Resolve ticket #1118 - * Update suse spec file - * Add phone number cleanup functions, unit tests and panel - configuration - * Add pertinent test that fails - * fix dependencies for suse package - * Add contextual edit menu in history - #1120 - - [ Alexandre Savard ] - * Temporary comit: make speex wideband (16 khz) - * Temporary: shared object for speex narrow band - * Temporary: speex narrowband and wideband coexist - - [ Julien Bonjean ] - * Fixed bug when no book selected - * Fixed addressbook related compilation warnings - * Fixed GTK client remaining compilation warnings - * Fixed segfault when book removed since last sflphone run - * Fixed bug when book is unreachable (ldap error) - - [ Alexandre Savard ] - * Fix codec list in audio config window - * Active/inactive speex codec by payload - - [ Julien Bonjean ] - * Updated gitignore - * Added some comments - - [ Emmanuel Milou ] - * Add callto: handler script for browsers and al. - * Integrate test compilation in the daemon build-system - - [ Julien Bonjean ] - * Fixed g_object_unref warning for pixbuf - * Cleaned too verbose output - * Fixed toolbar update warning - * Added support for asynchornous books open (first shot) - - [ Emmanuel Milou ] - * Add a DBus call to fetch the call details from a call ID - Ticket - #928 - - [ Julien Bonjean ] - * Improved async open books - * Fixed bug #1139 - - [ Emmanuel Milou ] - * Add a way to save account order - * commit missing files - - [ Julien Bonjean ] - * Introduced log4c (ticket #1162) - - [ Emmanuel Milou ] - * Load/save account order functionnal - ticket #813 - - [ Alexandre Savard ] - * Add CELT codec (#1143) - * Make celt frame size 256 (*1143) - - [ Julien Bonjean ] - * Switched everything to log4c (ticket #1162) - * Updated eclipse settings - - [ Emmanuel Milou ] - * Restore adding account - ticket #1172 - * Add liblog4c dependecy - ticket #1179 - - [ Alexandre Savard ] - * Double maxAvailByte for frame size in rtp (#1143) - - [ Emmanuel Milou ] - * Add User-Agent SIP header - Ticket #1173 - - [ Julien Bonjean ] - * Fixed autoresize issue (#708) - - [ Emmanuel Milou ] - * Remove libcppuint dependency for the debian packages - * Look for libsexy only if gtk version < 2.16 - Ticket #1116 - * Remove libsexy dependency for jaunty. ticket #1116 - - [ Julien Bonjean ] - * Introduced unit tests (#1146) - * Updated gitignore - * Fixed Makefile (#1146) - - [ Emmanuel Milou ] - * [TICKET #1112] Add a test on the voice buffer to send through iax - packets - * Remove doublon in dependencies - * Remove warnings from the client test framework - * Update version number to 0.9.5~beta - * Update build-package script - * Add check dependency in build-deps control file field - * Create debian files for the new sflphone-client-gnome - * [TICKET #1212] Add Replaces field in control files - * [TICKET #1212] Fix manpages installation path - * [TICKET #1212] Add maintainer scripts to create alternatives - * [#1212] Update the manpages generation - edit preinst maintainer - script - * [#1212] Fix reference error in manpage - * [#1212] Add missing files on the client side - * [#1212] Fix debian docs files - no TODO file - * [1212] Fix manpage creation problem - * [#1220] Generate client-side glue files and marshaller at - compilation time - * [#1220] Generate server-side glue files at compilation time - * [#1212] Change binary name to sflphone-client-gnome - * [#1212] Update .gitignore to fit the new working tree - * [#1220] Explicitly generate glue files before building the library - * [#1220] Compile dbus directory before audio - * [#1212] Create sflphone-common at the root of the repository - * [#1212] Re-add pjproject - * [#1212] Remove Makefile from repo - * [#1220] Fix Makefile.am - * [#1212] New working directory functional - * [#1212] Update .gitignore - * [#1212] Hack to make pjsip compile.. - * [#1220] Use non-installed binary for dbusxx-xml2cpp - * [#1212] Add descriptive files, remove unuseful scripts from tools/ - - [ Alexandre Savard ] - * Restore speex codecs - * add frame size for celt (#1143) - * add framesize to codec, independant from audiolayer (#1143) - * use codec frame size in rtp (#1143) - * compute fixed_codec_framesize (#1143) - * do not resample if not required (#1143) - * add condition on resampling for decoder (#1143) - * add a condition on bytesAvail == 0 from mic data - * no maximum in rtp decode (#1143) - * compute maximum for decoding (#1143) - - [ Emmanuel Milou ] - * [#1146] Implement unitary tests on the client-side - - [ Alexandre Savard ] - * use float instead of int to compute max nb of sample (#1143) - * add nbSampleMax for unresampled data (#1143) - * make thread sleep during 5 ms insead of 20 (#1143) - * use unix usleep (#1143) - * 50 usecond thread!!!!! (#1143) - * try with the smallest compression (#1143) - * use timer set at framesize (#1143) - - [ Emmanuel Milou ] - * [#1161] Restore changelog version - - [ Alexandre Savard ] - * Remove celt stuff - - [ Emmanuel Milou ] - * [#1161] Update changelog - * [#1220] Add Conflicts: sflphone in debian control files - * [#1179] Add liblog4c3 runtime dependency - * [#1212] FIx typo error in dependency list for itnrepid - * [#1212] FIx .desktop file to point on the right exec - * [#1212] Modify changelog replacing tag - - [ Sflphone Project ] - * "[#1262] Updated changelogs for version 0.9.5-0ubuntu1~beta" - - [ Emmanuel Milou ] - * [#1212] restore changelogs - - [ Sflphone Project ] - * [#1262] Updated changelogs for version 0.9.5-0ubuntu1 Snapshot 2009- - 04-27 - - [ Emmanuel Milou ] - * [#1212] restore changelogs - - [ Sflphone Project ] - * [#1262] Updated changelogs for version 0.9.5-0ubuntu1~beta - - [ Emmanuel Milou ] - * [#1212] restore changelogs - - [ Sflphone Project ] - - -- Sflphone Project <sflphone@mtl.savoirfairelinux.net> Mon, 27 Apr 2009 16:57:00 -0400 - -sflphone-client-kde (0.9.4-0ubuntu2) SYSTEM; urgency=low - - [ Alexandre Savard ] - * Restore speex and GSM detection - - [ Emmanuel Milou ] - * Fix bug #1090 - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Wed, 8 Apr 2009 11:29:15 -0500 - -sflphone (0.9.4-0ubuntu1) SYSTEM; urgency=low - - [ Emmanuel Milou ] - * Integrate DBus-c++ and libiax2 in the main build system - * Clean up in the working repository - * Reorder hooks configuration panel - * Protect case when no codecs are active - * Fix some return values - * Add unitary tests for the hook manager (premisces) - - [Yun Liu] - * Update chinese translation - - [Sven Werlen] - * Update german translation - - [Hussein Abdallah] - * Update russian translation - - [Maxime Chambreuil] - * Update spanish translation - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Fri, 3 Apr 2009 18:29:15 -0500 - - -sflphone (0.9.4-rc1) SYSTEM; urgency=low - - [ Emmanuel Milou ] - * Fix bug while trying to hold/unhold several simultaneous call - * Improve address book build system - * Implement SIP url popup on incoming call - * Improve GTK+ panel configuration - [ Julien Bonjean ] - * GTK+ client refactoring - * GTK+ clean up - * Address book improvment - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Fri, 27 Mar 2009 18:29:15 -0500 - -sflphone (0.9.4-0beta1) SYSTEM; urgency=low - - [ Alexandre Savard ] - * Display codec used during conversation on the GUI - * Enable/disable STUN parameters at runtime - * Refactor search bar use - [ Emmanuel Milou ] - * Build system fixes - * Implement SIP re-invite - * Implement IP to IP call - [ Julien Bonjean ] - * Integrate GNOME address book based on evolution data server - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Fri, 20 Mar 2009 18:29:15 -0500 - - -sflphone (0.9.3-0ubuntu3) SYSTEM; urgency=low - - [ Alexandre Savard ] - * Both playback and record streams in PA_STREAM_CORKED (pulseaudio) - * Use PLUGHW device for ALSA capture - * Functional IAX and SIP recording for voicemail - * Use the less CPU-consuming interpolator algorithm for resampling - * Display in GTK GUI the codec used in conversation - * GTK GUI use ASCII instread of utf-8 - * Add record menus in GTK GUI - * Put on hold when dialing a new number - * AccountID's are saved in the history - - [ Emmanuel Milou ] - * Integrate DBUS C++, libiax2 in the git repository - * Update website - * Use libspeexdsp only if available on the system - * Updated .gitignore file - - [Cyrille Béraud] - * Account assistant manager improvment - * Add an email request when creating a new account to receive voicemails - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Sat, 14 Feb 2009 13:29:15 -0500 - -sflphone (0.9.3-0ubuntu2) SYSTEM; urgency=low - - [ Emmanuel Milou ] - * Add compilation note in README - * Use default ALSA plugin for capture - * Fix the ALSA capture problem one more time - * Clean up debug messages in dbus.c - * Add libspeexdsp dependency - * Remove implicit declaration compilation warnings - * Fix links in the website, add release note - * Change capture for the website front page - * Add alsa devel dependency in build-depends control file field - * Clean up, indentation, try to handle latency problems in iax/pulseaudio - * Remove pjsip generated files from the repo - * Use the previous declared curAlias function in accountwindow - * Fix bug in history call duration when the call fails - * Remove runtime warning in the GTK+ client - * Add librsvg2-common dependency to load SVG under KDE - * Refresh .gitignore - * Update locales files + french translation - * Add configuration panel for future noise reduction - * Add configuration panel for audio record module - * Daemon less verbose; accounts don't try to access STUn options anymore - * Fix typo in configwindow - * Add content in the official website - * use a GTK_STOCK icon for the record button - * Complete description text in the assistant manager - * Add libtool flags in client configure.ac - * Remove unuseful dependency (snd) - * Fix SIP transfer problems - * Remove previous version of PJSIP from the repo - * Upgrade PJSIP to version 1.0.1 - * Add the new website source in the repository - * Use libspeexdsp for silence detection only if available - - [ Loïc Faure-Lacroix ] - * Ajout du logo gpl3 - * Ajout des images - * Ajout de la section screenshot pour le site - * Ajout du favicon dans le header - * Modification des cartes - - [ Alexandre Savard ] - * Clean up <speex/libspeexdsp> - * Small cleanup - * Save Wave fixed - * Fix new call button when recording - * libspeexdsp added - * Recording: default home folder at startup - * Minor changes to config window - * IAX recording fixed - * Set / get recording path, still need some GTK for client - * AudioRecord file name format - * Now recording in HOME folder - - [ Cyrille Béraud ] - * Fix bug in reqaccount.c - - [ Maxime Chambreuil ] - * Update spanish translation - - [Yun Liu ] - * Update chinese translation - - [ Hussein Abdallah ] - * Update russian translation - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Sat, 14 Feb 2009 13:29:15 -0500 - -sflphone (0.9.3-0ubuntu1) SYSTEM; urgency=low - - * Remove debug - * Join thread before leaving - * Fix implicit declaration in reqaccount - * Add REST code to build the request to server - * Fix GValue initialization warnings - * Update version number, fix implicit declaration, fix GTK markup - warnings - * Apply patch to create custom SIP account from our own server - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Fri, 06 Feb 2009 19:17:32 -0500 - -sflphone (0.9.2-2ubuntu9) SYSTEM; urgency=low - - [ Alexandre Savard ] - * Speex audio codec preprocessing initialization - * peer hung up segmentation fault solved - * Stop recording when transfering - * Terminate only one call - * Add isRecording() function - * Fix call_icon GTK client - * Fix SIPCallClose() function, recorded file now close properly - * Function terminateSIPCall added in sipvoiplink and managerimpl - * Fix thread destructor - * setRecordingOption function implement in audiorecord - * Record now implemented in Call class - * Record interface complete (on hold erase previous recording) - * Added recButton in client - * Added: record button related icons - * Record button added - * Overload AudioRecord::recData to get mic and speaker data mixed - * Recording now in audiortp::run() method - * Audio recording working in AudioRTP: receiveSessionForSpeaker - * Open/close a wave file when pulse audio stream start/stop - - [ Emmanuel Milou ] - * Fix path for GTK+ icons; clean up - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Thu, 05 Feb 2009 18:27:53 -0500 - -sflphone (0.9.2-2ubuntu8) SYSTEM; urgency=low - - [ Emmanuel Milou ] - * Update changelogs - * Fix bug in merge and in Makefile.am - * Terminate only one call - * Disable PJsip shutdown when changing STUN parameters - * Function terminateSIPCall added in sipvoiplink and managerimpl - * Add a timer to the alsa thread to not jam the CPU load - * Fix bug in sipvoiplink.cpp - * Clean shutdown of pulseaudio on quiting - * Fix DTMF at first start with Pulseaudio - * Remove zeroconf from the build system - * Add a library manager + exception handling - * Clean up in the working directory - * Better handling of capture XRUNs - * Restore mic adjust volume on ALSA layer - * Protect device ALSA operation if not opened - * Fix the switching layer bug - * Use dynamic_cast<> to use audiolayer-specific methods - * Open the audio devices only once at startup - * Refactoring of the ALSA part - * Functional plug-in manager - * Use a C++ thread to handle tones and DTMF in ALSA - * Restore IAXVoIPLink, restore Mutex - * Make the plugins registering against the plugin manager - * Migrate to 1->N relationship between voiplink and accounts - * API plugin for registration - * Use C++ thread in SIP, move everything in sipvoiplink - * Complete singleton pattern for the plugin manager - * Add -Wno-return-type compilation flag to remove warnings; Update - version number in configure.ac - * Add the dynamic loading for the plugin framework; integate unittest - - [ Yun Liu ] - * Update rpm spec file - * modify build package script and spec file for suse - - [ Alexandre Savard ] - * Add audiorecorder plugin and testaudiorecorder - * Add audio Recording class, edit global.h - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Wed, 04 Feb 2009 14:00:30 -0500 - -sflphone (0.9.2-2ubuntu7) SYSTEM; urgency=low - - [ Emmanuel Milou ] - * Update changelog to 0.9.2-6 - * Fix some dbus-glib implementation details on the client side - * Init history after dbus initialization - * Add error checking in useragent; Clean sipvoiplink - * Prevent crash when trying to call an empty number - * Set the volume of the playback stream to PA_VOLUME_NORM at startup - * Fix GTK+ generic value double initialization - * Fix jaunty control file dependency problems - * Fix jaunty control file dependency problems - - [ Yun Liu ] - * Fix bug ticket # 137 - * Tolerant to gsm library of OpenSuse 11 - - [ Sven Werlen ] - * Update german translation - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Fri, 23 Jan 2009 17:48:13 -0500 - -sflphone (0.9.2-2ubuntu6) SYSTEM; urgency=low - - [ Emmanuel Milou ] - * Migrate STUN configuration to the main config window - * Update french translation - * Other tiny memory leaks - * Fix memory leak in sampleconverter.cpp - * Generate packages from the release branch - * update the build package script - * modify the control files with architecture=any - * Remove valgring uninitialized value - * IAX and SIP use the same global variables to set account - configuration ; fix broken code - - [ Maxime Chambreuil ] - * Update spanish translation - - [ Hussein Abdallah ] - * Update russian translation - - [ Yun Liu ] - * Update translation files - * Fix the bug when user uncheck the account which fails in the - previous registration - * Add stun error status - * Fix bug ticket #143 - * Script for auto-install dependencies - * Fix bug ticket #140 - * Fix bug ticket 141 - * Fix the reregister process when user change the details of an - account - - -- Emmanuel Milou <manu@sulfur.inside.savoirfairelinux.net> Fri, 16 Jan 2009 18:19:05 -0500 - -sflphone (0.9.2-2ubuntu5) SYSTEM; urgency=low - - * Fix memory leak in the pulseaudio callback - * Update debian package generation script - * Warnings removal in GTK+ client - * Clean adjust volume method in alsalayer - * Plug the sflphone playback volume control to the pulseaudio volume - manager - * Display the date in history according to the current locale - * Generate the changelog according to the git commit messages - * Complete header in chinese translation file - * Use the right gpg key to sign the packages - * add debian jaunty jackalope support - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Wed, 14 Jan 2009 21:17:20 -0500 - -sflphone (0.9.2-2ubuntu4) SYSTEM; urgency=low - - [ Emmanuel Milou ] - * add german translation - - [ Yun Liu ] - * Fix GUI crash in Ubuntu8.10 64bit system - - -- Yun Liu <yun.liu@savoirfairelinux.com> Thu, 08 Jan 2009 13:08:51 -0500 - -sflphone (0.9.2-2ubuntu3) SYSTEM; urgency=low - - [ Emmanuel Milou ] - * The main thread synchronizes the ringtone thread - * disable custom ringtone for the ALSA layer - * Fix the Makefile.am in man directory, add a SEE ALSO section - - [ Yun Liu ] - * Fix daemon crash caused by the previous patch ( for bug ticket #129) - - -- Yun Liu <yun.liu@savoirfairelinux.com> Tue, 06 Jan 2009 16:18:38 -0500 - -sflphone (0.9.2-2ubuntu2) SYSTEM; urgency=low - - * Fix bug ticket #129 - - -- Yun Liu <yun.liu@savoirfairelinux.com> Wed, 5 Jan 2009 15:54:53 -0500 - -sflphone (0.9.2-2ubuntu1) SYSTEM; urgency=low - - * Migrate from eXosip library to pjsip - * Add multiple SIP accounts support - * Fix ringtones problems - * Add a pulseaudio support - * Improve audio quality with ALSA - * Add chinese translation - * Improve spanish translation - * Migrate to a maintained C++ DBus bindings - * Clean and improve the build system - * Add build-dependency on Perl because we need pod2man to generate manpages - - -- Yun Liu <yun.liu@savoirfairelinux.com> Wed, 26 Nov 2008 09:47:53 -0500 - -sflphone (0.9.1) unstable; urgency=low - * Add a search tool in the history - * Migrate some gtk_entry_new to sexy_icon_entry_new - * Bug fix (Ticket #78): The voicemail password isn't displayed anymore in - the history tab - * Add the SIP registration expire value in the user file. - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Thu, 22 May 2008 11:14:25 -0500 - -sflphone (0.9.0) unstable; urgency=low - * Add history features - * Call date - * Call duration - * Mouse events in the history tab - * Smooth switch from the history tab to the calls tab - * Remove most of GTK-Critical warnings - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Wed, 13 May 2008 16:58:25 -0500 - -sflphone (0.9-2008-06-06) unstable; urgency=low - * Audio bug correction: capture stopped after a few minutes of conversation - with USB Plantronics sound card - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Tue, 06 May 2008 16:58:25 -0500 - -sflphone (0.9-2008-05-06) unstable; urgency=low - * Bug correction: account creation with the assistant - * GTK+ warnings removal - * libnotify warnings removal - * Remove aliasing on the SFLphone logo - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Mon, 05 May 2008 16:58:25 -0500 - -sflphone (0.9) unstable; urgency=low - * Clean dependencies ( removal of libboost ) - * Several GTK improvement and updates - -account window - -configuration window - * Migrate from GtkCheckMenuItem to GtkImageMenuItem - * ALSA standard I/O transfers: MMAP instead of R/W - * Fix speex audio quality - * IAX2 protocol - -Fix hold/unhold situation - -Add on hold music - * SIP protocol - -Ringtone on incoming call - -Fix transfer situation - * Add desktop notification ( libnotify ) - * Improve the system tray icon behaviour - * Improve registration error handling - * Register/unregister from the account window takes effect without starting back SFLphone - * Compilation warnings removal - * Call history - * Add an account configuration wizard - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Wed, 30 Apr 2008 16:58:25 -0500 - -sflphone (0.8.2) unstable; urgency=low - * Internationalization of the GTK GUI - * English / French - * STUN support - * Slight modifications of the graphical interface ( tooltips, dialpad, ...) - - -- Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Fri, 21 Mar 2008 11:37:53 -0500 + -- Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> Thu May 17 15:14:46 EDT 2012 \ No newline at end of file diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/control b/tools/build-system/launchpad/sflphone-client-kde/debian/control index a4e6a266195dad90c9132c41a8373ea5bf84ae16..6b38e74ec03704affed35f1eccf3e4662fb08e08 100644 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/control +++ b/tools/build-system/launchpad/sflphone-client-kde/debian/control @@ -1,20 +1,13 @@ Source: sflphone-client-kde -Maintainer: SavoirFaireLinux Inc <julien.bonjean@savoirfairelinux.com> Section: kde Priority: optional -Build-Depends: debhelper, cmake, kdepimlibs5-dev, libcommoncpp2-dev, libqt4-dev -Standards-Version: 3.7.3 +Maintainer: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> +Uploaders: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> +Standards-Version: 1.1 +Build-Depends: debhelper (>= 5.0), cdbs, kdelibs5-dev, cmake, libphonon-dev, kdepimlibs5-dev +Homepage: http://www.sfphone.org/ Package: sflphone-client-kde -Priority: optional -Architecture: i386 -Depends: sflphone-common (>=${source:Version}), libcommoncpp2-1.6-0, kdepimlibs5, libqt4-dbus, libqt4-svg, libqtgui4 -Replaces: sflphone -Conflicts: sflphone -Homepage: http://www.sflphone.org -Description: KDE client for SFLphone - Provide a KDE client for SFLphone. - SFLphone is meant to be a robust enterprise-class desktop phone. - SFLphone is released under the GNU General Public License. - SFLphone is being developed by the global community, and maintained by - Savoir-faire Linux, a Montreal, Quebec, Canada-based Linux consulting company. +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description:KDE client for the sflphone-daemon SIP/AiX softphone \ No newline at end of file diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/control.lucid b/tools/build-system/launchpad/sflphone-client-kde/debian/control.lucid deleted file mode 100644 index 183ca4e831341b6778830669d3cfc0a5c017f4b3..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/control.lucid +++ /dev/null @@ -1,20 +0,0 @@ -Source: sflphone-client-kde -Maintainer: SavoirFaireLinux Inc <julien.bonjean@savoirfairelinux.com> -Section: kde -Priority: optional -Build-Depends: debhelper, cmake, kdepimlibs5-dev, libcommoncpp2-dev, libqt4-dev -Standards-Version: 3.7.3 - -Package: sflphone-client-kde -Priority: optional -Architecture: i386 -Depends: sflphone-common (>=${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Replaces: sflphone -Conflicts: sflphone -Homepage: http://www.sflphone.org -Description: KDE client for SFLphone - Provide a KDE client for SFLphone. - SFLphone is meant to be a robust enterprise-class desktop phone. - SFLphone is released under the GNU General Public License. - SFLphone is being developed by the global community, and maintained by - Savoir-faire Linux, a Montreal, Quebec, Canada-based Linux consulting company. diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/control.natty b/tools/build-system/launchpad/sflphone-client-kde/debian/control.natty deleted file mode 100644 index 183ca4e831341b6778830669d3cfc0a5c017f4b3..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/control.natty +++ /dev/null @@ -1,20 +0,0 @@ -Source: sflphone-client-kde -Maintainer: SavoirFaireLinux Inc <julien.bonjean@savoirfairelinux.com> -Section: kde -Priority: optional -Build-Depends: debhelper, cmake, kdepimlibs5-dev, libcommoncpp2-dev, libqt4-dev -Standards-Version: 3.7.3 - -Package: sflphone-client-kde -Priority: optional -Architecture: i386 -Depends: sflphone-common (>=${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Replaces: sflphone -Conflicts: sflphone -Homepage: http://www.sflphone.org -Description: KDE client for SFLphone - Provide a KDE client for SFLphone. - SFLphone is meant to be a robust enterprise-class desktop phone. - SFLphone is released under the GNU General Public License. - SFLphone is being developed by the global community, and maintained by - Savoir-faire Linux, a Montreal, Quebec, Canada-based Linux consulting company. diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/control.oneiric b/tools/build-system/launchpad/sflphone-client-kde/debian/control.oneiric deleted file mode 100644 index 183ca4e831341b6778830669d3cfc0a5c017f4b3..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/control.oneiric +++ /dev/null @@ -1,20 +0,0 @@ -Source: sflphone-client-kde -Maintainer: SavoirFaireLinux Inc <julien.bonjean@savoirfairelinux.com> -Section: kde -Priority: optional -Build-Depends: debhelper, cmake, kdepimlibs5-dev, libcommoncpp2-dev, libqt4-dev -Standards-Version: 3.7.3 - -Package: sflphone-client-kde -Priority: optional -Architecture: i386 -Depends: sflphone-common (>=${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Replaces: sflphone -Conflicts: sflphone -Homepage: http://www.sflphone.org -Description: KDE client for SFLphone - Provide a KDE client for SFLphone. - SFLphone is meant to be a robust enterprise-class desktop phone. - SFLphone is released under the GNU General Public License. - SFLphone is being developed by the global community, and maintained by - Savoir-faire Linux, a Montreal, Quebec, Canada-based Linux consulting company. diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/copyright b/tools/build-system/launchpad/sflphone-client-kde/debian/copyright index fbde2314bef1fb7ee643083e6d27c397213c5ead..9a2517742fc84d943b27046e0f5538cd76fbd00c 100644 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/copyright +++ b/tools/build-system/launchpad/sflphone-client-kde/debian/copyright @@ -1,28 +1,8 @@ -This package was debianized by Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> on -Fri, 3 Apr 2009 09:47:53 -0500. +SFLPhone: -It was downloaded from the git repository of SFLphone: git://sflphone.org/git/sflphone.git + (C) 2004-2012 Savoir-Faire Linux <contact@savoirfairelinux.com> -Upstream Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> +SFLPhone KDE: -Copyright: - -Savoir-Faire Linux Inc. - -License: - -This software is copyright (c) 2004-2009 Savoir-Faire Linux inc. - -You are free to distribute this software under the terms of -the GNU General Public License version 3. -On Debian systems, the complete text of the GNU General Public -License can be found in the file `/usr/share/common-licenses/GPL'. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklyn St, Fifth Floor, Boston, MA 02110-1301, USA. + Copyright (C) 2008-2009 Savoir-Faire Linux <jeremy.quentin@savoirfairelinux.com> + Copyright (C) 2009-2012 Savoir-Faire Linux <emmanuel.lepage@savoirfairelinux.com> diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/cron.d b/tools/build-system/launchpad/sflphone-client-kde/debian/cron.d deleted file mode 100644 index d11e61177739b56bce3aac6de6483b48e797a258..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/cron.d +++ /dev/null @@ -1,4 +0,0 @@ -# -# Regular cron jobs for the sflphone package -# -0 4 * * * root sflphone_maintenance diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/dirs b/tools/build-system/launchpad/sflphone-client-kde/debian/dirs deleted file mode 100644 index e2dc98dcb24907fb5a7ceb0f0651276b702d6030..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/dirs +++ /dev/null @@ -1,7 +0,0 @@ -usr/bin -usr/share/applications -usr/share/pixmaps -usr/share/sflphone -usr/share/locale -usr/share/doc -usr/share/man diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/docs b/tools/build-system/launchpad/sflphone-client-kde/debian/docs deleted file mode 100644 index 9830da213fdb4baf4d68538e8c8e490248e209e1..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/docs +++ /dev/null @@ -1,5 +0,0 @@ -NEWS -README -ChangeLog -AUTHORS - diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/manpages b/tools/build-system/launchpad/sflphone-client-kde/debian/manpages deleted file mode 100644 index 919cf59a8e71fbc2fda9ea40c7cd1162970babd2..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/manpages +++ /dev/null @@ -1,2 +0,0 @@ -debian/sflphone-client-kde/usr/share/man/man1/sflphone.1 -debian/sflphone-client-kde/usr/share/man/man1/sflphone-client-kde.1 diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/menu b/tools/build-system/launchpad/sflphone-client-kde/debian/menu new file mode 100644 index 0000000000000000000000000000000000000000..272ceffd65e30b12cd2d27a28cfd3aa8bdecb78a --- /dev/null +++ b/tools/build-system/launchpad/sflphone-client-kde/debian/menu @@ -0,0 +1,6 @@ +?package(filelight):needs="X11" \ + section="Applications/Multimedia" \ + hints="KDE, Phone, Sip,Call" \ + command="/usr/bin/sflphone-client-kde" \ + title="SFLPhone Client KDE" \ + longtitle="SFLPhone Client KDE: Enterprise class softphone for KDE" diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/postinst b/tools/build-system/launchpad/sflphone-client-kde/debian/postinst deleted file mode 100644 index 03f87b04e8143e344563fca7b6760ec43986592a..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/postinst +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -e - -update-alternatives --install /usr/bin/sflphone sflphone /usr/bin/sflphone-client-kde 200 \ - --slave /usr/share/man/man1/sflphone.1.gz sflphone.1.gz \ - /usr/share/man/man1/sflphone-client-kde.1 - -update-alternatives --set sflphone /usr/bin/sflphone-client-kde - -exit 0 diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/preinst b/tools/build-system/launchpad/sflphone-client-kde/debian/preinst deleted file mode 100644 index fdaa8ab8ec9a4ebe1c93136c5c15dedcb599febc..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/preinst +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# postrm script for sflphone -# -# see: dh_installdeb(1) - -set -e - -package=sflphone-client-kde - -case "$1" in - install|upgrade) - ;; -esac - -exit 0 diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/prerm b/tools/build-system/launchpad/sflphone-client-kde/debian/prerm deleted file mode 100644 index 5e9021706875bb08a56c8c54f35cef96a7ca6055..0000000000000000000000000000000000000000 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/prerm +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -e - - -if [ "$1" = "remove" ]; then - # Remove alternatives symlink set in postinst - update-alternatives --remove sflphone /usr/bin/sflphone -fi diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/rules b/tools/build-system/launchpad/sflphone-client-kde/debian/rules index b6368f42f485c9e57d82f6fc153969cbe9b90d62..084d00f39e1d4bde43e8b8302c00a59de977b8d7 100755 --- a/tools/build-system/launchpad/sflphone-client-kde/debian/rules +++ b/tools/build-system/launchpad/sflphone-client-kde/debian/rules @@ -1,118 +1,10 @@ #!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. +# debian/rules file - for filelight (1.0) +# Copyright 2007 Raúl Sánchez Siles +# 2009 Michael Meskes +# This packaging is licensed under GPLv2 +# see /usr/share/common-licenses/GPL-2 for details. -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 -export DH_OPTIONS +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/cmake.mk -package=sflphone-client-kde - -CXX = g++-4.0 -# CFLAGS = -Wall -g -# DEB_INSTALL_PAGES_sflphone_client_kde = sflphone.1 sflphone-client-kde.1 - -configure: configure-stamp -configure-stamp: - dh_testdir - # Add here commands to configure the package. - cmake . -DCMAKE_INSTALL_PREFIX=/usr - touch configure-stamp - - -#Architecture -build: build-arch build-indep - -build-arch: build-arch-stamp -build-arch-stamp: configure-stamp - - # Add here commands to compile the arch part of the package. - $(MAKE) - touch $@ - -build-indep: build-indep-stamp -build-indep-stamp: configure-stamp - - # Add here commands to compile the indep part of the package. - #$(MAKE) doc - touch $@ - -clean: - dh_testdir - dh_testroot - rm -f build-arch-stamp build-indep-stamp configure-stamp - # Add here commands to clean up after the build process. - [ ! -f Makefile ] || $(MAKE) distclean - -ifneq "$(wildcard /usr/share/misc/config.sub)" "" - cp -f /usr/share/misc/config.sub config.sub -endif -ifneq "$(wildcard /usr/share/misc/config.guess)" "" - cp -f /usr/share/misc/config.guess config.guess -endif - dh_clean - -install: install-indep install-arch -install-indep: - dh_testdir - dh_testroot - dh_clean -k -i - dh_installdirs -i - # Add here commands to install the package into debian/sflphone. - -install-arch: - dh_testdir - dh_testroot - dh_clean -k -s - dh_installdirs -s - # Add here commands to install the arch part of the package into - # debian/tmp. - $(MAKE) DESTDIR=$(CURDIR)/debian/$(package) install - dh_install -s -# Must not depend on anything. This is to be called by -# binary-arch/binary-indep -# in another 'make' thread. - -binary-common: - pwd - dh_testdir - dh_testroot - dh_installchangelogs ChangeLog - dh_installdocs - dh_installexamples -# dh_installmenu -# dh_installdebconf -# dh_installlogrotate -# dh_installemacsen -# dh_installpam -# dh_installmime -# dh_python -# dh_installinit -# dh_installcron -# dh_installinfo -# dh_installman - dh_link - dh_strip - dh_compress - dh_fixperms -# dh_perl - dh_makeshlibs - dh_installdeb -# dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb -# Build architecture independant packages using the common target. -binary-indep: build-indep install-indep - $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common - -# Build architecture dependant packages using the common target. -binary-arch: build-arch install-arch - $(MAKE) -f debian/rules DH_OPTIONS=-s binary-common - -binary: binary-arch binary-indep -.PHONY: build clean binary-indep binary-arch binary install install-indep install-arch configure diff --git a/tools/build-system/launchpad/sflphone-client-kde/debian/source/format b/tools/build-system/launchpad/sflphone-client-kde/debian/source/format new file mode 100644 index 0000000000000000000000000000000000000000..163aaf8d82b6c54f23c45f32895dbdfdcc27b047 --- /dev/null +++ b/tools/build-system/launchpad/sflphone-client-kde/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/tools/pysflphone/sflphonectrlsimple.py b/tools/pysflphone/sflphonectrl.py similarity index 73% rename from tools/pysflphone/sflphonectrlsimple.py rename to tools/pysflphone/sflphonectrl.py index 12709ed900ddb56310ed0d4487af2693faa5db98..b6a17226a21ec1a38df9699caf08fb740ec6408b 100755 --- a/tools/pysflphone/sflphonectrlsimple.py +++ b/tools/pysflphone/sflphonectrl.py @@ -47,38 +47,49 @@ except ImportError, e: raise SflPhoneError("No python-dbus module found") -class SflPhoneCtrlSimple(Thread): - """ Simple class for controlling SflPhoned through DBUS - - If option testSuite (ts) is put to true, - simple actions are implemented on incoming call. +class SflPhoneCtrl(Thread): + """ class for controlling SflPhoned through DBUS + + Classes deriving this class should reimplement signal handlers, + more especially: + onIncomingCall_cb + onCallHangup_cb + onCallRinging_cb + onCallHold_cb + onCallCurrent_cb + onCallBusy_cb + onCallFailure_cb + onConferenceCreated_cb """ # list of active calls (known by the client) activeCalls = {} - def __init__(self, test=False, name=sys.argv[0]): - print "Create SFLphone instance" - Thread.__init__(self) - # current active account + # list of active conferences + activeConferences = {} + + def __init__(self, name=sys.argv[0]): + Thread.__init__(self) + + # current active account self.account = None + # client name self.name = name + + self.currentCallId = "" + self.currentConfId = "" + + self.isStop = False + # client registered to sflphoned ? self.registered = False self.register() - self.currentCallId = "" + # Glib MainLoop for processing callbacks self.loop = MainLoop() - self.isStop = False - - self.test = test - self.onIncomingCall_cb = None - self.event = Event() - gobject.threads_init() - def __del__(self): @@ -88,9 +99,7 @@ class SflPhoneCtrlSimple(Thread): def stopThread(self): - print "Stop PySFLphone" self.isStop = True - def register(self): @@ -141,18 +150,15 @@ class SflPhoneCtrlSimple(Thread): print "Adding Incoming call method" proxy_callmgr.connect_to_signal('incomingCall', self.onIncomingCall) proxy_callmgr.connect_to_signal('callStateChanged', self.onCallStateChanged) + proxy_callmgr.connect_to_signal('conferenceCreated', self.onConferenceCreated) except dbus.DBusException, e: print e - def unregister(self): - print "Unregister" - if not self.registered: return - #raise SflPhoneError("Not registered !") try: self.instance.Unregister(os.getpid()) self.registered = False @@ -164,66 +170,122 @@ class SflPhoneCtrlSimple(Thread): return self.registered - def getEvent(self): - return self.event + # + # Signal handling + # - def wait(self): - self.event.wait() + def onIncomingCall_cb(self): + pass - def isSet(self): - self.event.isSet() + def onCallHangup_cb(self, callId): + pass - def set(self): - self.event.set() + def onCallRinging_cb(self): + pass - def clear(self): - self.event.clear() + def onCallHold_cb(self): + pass - # - # Signal handling - # + def onCallCurrent_cb(self): + pass + + def onCallBusy_cb(self): + pass + + def onCallFailure_cb(self): + pass - # On incoming call event, add the call to the list of active calls def onIncomingCall(self, account, callid, to): - print "Incoming call: " + account + ", " + callid + ", " + to - self.activeCalls[callid] = {'Account': account, 'To': to, 'State': '' } + """ On incoming call event, add the call to the list of active calls """ + + self.activeCalls[callid] = {'Account': account, + 'To': to, + 'State': ''} self.currentCallId = callid + self.onIncomingCall_cb() - if(self.test): - # TODO fix this bug in daemon, cannot answer too fast - time.sleep(0.5) - if self.onIncomingCall_cb(self) is not None: - self.onIncomingCall_cb(self) - + + def onCallHangUp(self, callid): + """ Remove callid from call list """ + + self.onCallHangup_cb(callid) + self.currentCallId = "" + del self.activeCalls[callid] + + + def onCallRinging(self, callid, state): + """ Update state for this call to Ringing """ + + self.activeCalls[callid]['State'] = state + self.onCallRinging_cb() + + + def onCallHold(self, callid, state): + """ Update state for this call to Hold """ + + self.activeCalls[callid]['State'] = state + self.onCallHold_cb() + + + def onCallCurrent(self, callid, state): + """ Update state for this call to current """ + + self.activeCalls[callid]['State'] = state + self.onCallCurrent_cb() + + + def onCallBusy(self, callid, state): + """ Update state for this call to busy """ + + self.activeCalls[callid]['State'] = state + self.onCallBusy_cb() + + + def onCallFailure(self, callid, state): + """ Handle call failure """ + + self.onCallFailure_cb(self) + del self.activeCalls[callid] - # On call state changed event, set the values for new calls, - # or delete the call from the list of active calls def onCallStateChanged(self, callid, state): - print "Call state changed: " + callid + ", " + state + """ On call state changed event, set the values for new calls, + or delete the call from the list of active calls + """ + + print "On call state changed " + callid + " " + state + + if callid not in self.activeCalls: + print "This call didn't exist!: " + callid + ". Adding it to the list." + callDetails = self.getCallDetails(callid) + self.activeCalls[callid] = {'Account': callDetails['ACCOUNTID'], + 'To': callDetails['PEER_NUMBER'], + 'State': state } + + + self.currentCallId = callid + if state == "HUNGUP": - try: - del self.activeCalls[callid] - except KeyError: - print "Call " + callid + " didn't exist. Cannot delete." - - elif state in [ "RINGING", "CURRENT", "INCOMING", "HOLD" ]: - try: - self.activeCalls[callid]['State'] = state - except KeyError, e: - print "This call didn't exist!: " + callid + ". Adding it to the list." - callDetails = self.getCallDetails(callid) - self.activeCalls[callid] = {'Account': callDetails['ACCOUNTID'], - 'To': callDetails['PEER_NUMBER'], 'State': state } - elif state in [ "BUSY", "FAILURE" ]: - try: - del self.activeCalls[callid] - except KeyError, e: - print "This call didn't exist!: " + callid - -# elif state == "UNHOLD_CURRENT": -# self.activeCalls[callid]['State'] = "UNHOLD_CURRENT" + self.onCallHangUp(callid) + elif state == "RINGING": + self.onCallRinging(callid, state) + elif state == "CURRENT": + self.onCallCurrent(callid, state) + elif state == "HOLD": + self.onCallHold(callid, state) + elif state == "BUSY": + self.onCallBusy(callid, state) + elif state == "FAILURE": + self.onCallFailure(self, callid, state) + else: + print "unknown state" + + def onConferenceCreated_cb(self): + pass + def onConferenceCreated(self, confId): + self.currentConfId = confId + self.onConferenceCreated_cb() # # Account management @@ -237,7 +299,7 @@ class SflPhoneCtrlSimple(Thread): Required parameters are type, alias, hostname, username and password input details - + """ if details is None: @@ -247,6 +309,7 @@ class SflPhoneCtrlSimple(Thread): return self.configurationmanager.addAccount(details) + def removeAccount(self, accountID=None): """Remove an account from internal list""" @@ -255,13 +318,16 @@ class SflPhoneCtrlSimple(Thread): self.configurationmanager.removeAccount(accountID) + def getAllAccounts(self): """Return a list with all accounts""" + return self.configurationmanager.getAccountList() def getAllEnabledAccounts(self): """Return a list with all enabled accounts""" + accounts = self.getAllAccounts() activeaccounts = [] for testedaccount in accounts: @@ -306,6 +372,7 @@ class SflPhoneCtrlSimple(Thread): raise SPaccountError("No account matched with alias") + def setAccount(self, account): """Define the active account @@ -318,6 +385,7 @@ class SflPhoneCtrlSimple(Thread): print account raise SflPhoneError("Not a valid account") + def setFirstRegisteredAccount(self): """Find the first enabled account and define it as active""" @@ -326,6 +394,7 @@ class SflPhoneCtrlSimple(Thread): raise SflPhoneError("No registered account !") self.account = rAccounts[0] + def setFirstActiveAccount(self): """Find the first enabled account and define it as active""" @@ -348,40 +417,44 @@ class SflPhoneCtrlSimple(Thread): if self.account is None: raise SflPhoneError("No provided or current account !") account = self.account - return self.getAccountDetails(account)['Status'] == "REGISTERED" + return self.getAccountDetails(account)['Registration.Status'] == "REGISTERED" def isAccountEnable(self, account=None): """Return True if the account is enabled. If no account is provided, active account is used""" if account is None: - if self.account is None: - raise SflPhoneError("No provided or current account !") + if self.account is None: + raise SflPhoneError("No provided or current account !") account = self.account return self.getAccountDetails(account)['Account.enable'] == "TRUE" + def setAccountEnable(self, account=None, enable=False): - """Set account enabled""" + """Set account enabled""" if account is None: - if self.account is None: - raise SflPhoneError("No provided or current account !") + if self.account is None: + raise SflPhoneError("No provided or current account !") account = self.account - if enable == True: - details = self.getAccountDetails(account) - details['Account.enable'] = "TRUE" - self.configurationmanager.setAccountDetails(account, details) + if enable == True: + details = self.getAccountDetails(account) + details['Account.enable'] = "true" + self.configurationmanager.setAccountDetails(account, details) else: - details = self.getAccountDetails(account) - details['Account.enable'] = "FALSE" - self.configurationmanager.setAccountDetails(account, details) + details = self.getAccountDetails(account) + details['Account.enable'] = "false" + self.configurationmanager.setAccountDetails(account, details) + def checkAccountExists(self, account=None): """ Checks if the account exists """ + if account is None: raise SflPhoneError("No provided or current account !") return account in self.getAllAccounts() - + + def getAllRegisteredAccounts(self): """Return a list of registered accounts""" @@ -392,6 +465,7 @@ class SflPhoneCtrlSimple(Thread): return registeredAccountsList + def getAllEnabledAccounts(self): """Return a list of enabled accounts""" @@ -402,8 +476,10 @@ class SflPhoneCtrlSimple(Thread): return enabledAccountsList + def getAllSipAccounts(self): """Return a list of SIP accounts""" + sipAccountsList = [] for accountName in self.getAllAccounts(): if self.getAccountDetails(accountName)['Account.type'] == "SIP": @@ -411,6 +487,7 @@ class SflPhoneCtrlSimple(Thread): return sipAccountsList + def getAllIaxAccounts(self): """Return a list of IAX accounts""" @@ -421,23 +498,22 @@ class SflPhoneCtrlSimple(Thread): return iaxAccountsList + def setAccountRegistered(self, account=None, register=False): - """ Tries to register the account """ - - if account is None: - if self.account is None: - raise SflPhoneError("No provided or current account !") - account = self.account - - try: - if register: - self.configurationmanager.sendRegister(account, int(1)) - #self.setAccount(account) - else: - self.configurationmanager.sendRegister(account, int(0)) - #self.setFirstRegisteredAccount() + """ Tries to register the account """ + + if account is None: + if self.account is None: + raise SflPhoneError("No provided or current account !") + account = self.account + + try: + if register: + self.configurationmanager.sendRegister(account, int(1)) + else: + self.configurationmanager.sendRegister(account, int(0)) except SflPhoneError, e: - print e + print e # # Codec manager @@ -445,12 +521,14 @@ class SflPhoneCtrlSimple(Thread): def getCodecList(self): """ Return the codec list """ + return self.configurationmanager.getCodecList() + def getActiveCodecList(self): """ Return the active codec list """ - return self.configurationmanager.getActiveCodecList() + return self.configurationmanager.getActiveCodecList() # @@ -479,9 +557,6 @@ class SflPhoneCtrlSimple(Thread): for call in self.activeCalls: print "\t" + call - # - # Action - # def Call(self, dest): """Start a call and return a CallID @@ -496,7 +571,7 @@ class SflPhoneCtrlSimple(Thread): if dest is None or dest == "": raise SflPhoneError("Invalid call destination") - + # Set the account to be used for this call if dest.find('sip:') is 0 or dest.find('sips:') is 0: print "Ip 2 IP call" @@ -508,7 +583,7 @@ class SflPhoneCtrlSimple(Thread): raise SflPhoneError("Can't place a call without a registered account") # Generate a call ID for this call - callid = self.GenerateCallID() + callid = self.GenerateCallID() # Add the call to the list of active calls and set status to SENT self.activeCalls[callid] = {'Account': self.account, 'To': dest, 'State': 'SENT' } @@ -521,26 +596,18 @@ class SflPhoneCtrlSimple(Thread): def HangUp(self, callid): """End a call identified by a CallID""" + if not self.account: self.setFirstRegisteredAccount() - # if not self.isAccountRegistered() and self.accout is not "IP2IP": - # raise SflPhoneError("Can't hangup a call without a registered account") - if callid is None or callid == "": pass # just to see - #raise SflPhoneError("Invalid callID") self.callmanager.hangUp(callid) def Transfer(self, callid, to): """Transfert a call identified by a CallID""" - # if not self.account: - # self.setFirstRegisteredAccount() - - # if not self.isAccountRegistered(): - # raise SflPhoneError("Can't transfert a call without a registered account") if callid is None or callid == "": raise SflPhoneError("Invalid callID") @@ -553,12 +620,6 @@ class SflPhoneCtrlSimple(Thread): print "Refuse call " + callid - # if not self.account: - # self.setFirstRegisteredAccount() - - # if not self.isAccountRegistered(): - # raise SflPhoneError("Can't refuse a call without a registered account") - if callid is None or callid == "": raise SflPhoneError("Invalid callID") @@ -567,26 +628,22 @@ class SflPhoneCtrlSimple(Thread): def Accept(self, callid): """Accept an incoming call identified by a CallID""" + print "Accept call " + callid if not self.account: self.setFirstRegisteredAccount() - if not self.isAccountRegistered(): + if not self.isAccountRegistered(): raise SflPhoneError("Can't accept a call without a registered account") if callid is None or callid == "": raise SflPhoneError("Invalid callID") - + self.callmanager.accept(callid) def Hold(self, callid): """Hold a call identified by a CallID""" - # if not self.account: - # self.setFirstRegisteredAccount() - - # if not self.isAccountRegistered(): - # raise SflPhoneError("Can't hold a call without a registered account") if callid is None or callid == "": raise SflPhoneError("Invalid callID") @@ -596,11 +653,6 @@ class SflPhoneCtrlSimple(Thread): def UnHold(self, callid): """Unhold an incoming call identified by a CallID""" - # if not self.account: - # self.setFirstRegisteredAccount() - - # if not self.isAccountRegistered(): - # raise SflPhoneError("Can't unhold a call without a registered account") if callid is None or callid == "": raise SflPhoneError("Invalid callID") @@ -610,11 +662,13 @@ class SflPhoneCtrlSimple(Thread): def Dtmf(self, key): """Send a DTMF""" + self.callmanager.playDTMF(key) def GenerateCallID(self): """Generate Call ID""" + m = hashlib.md5() t = long( time.time() * 1000 ) r = long( random.random()*100000000000000000L ) @@ -622,13 +676,30 @@ class SflPhoneCtrlSimple(Thread): callid = m.hexdigest() return callid + + def createConference(self, call1Id, call2Id): + """ Create a conference given the two call ids """ + + self.callmanager.joinParticipant(call1Id, call2Id) + + + def hangupConference(self, confId): + """ Hang up each call for this conference """ + + self.callmanager.hangUpConference(confId) + + def run(self): """Processing method for this thread""" - context = self.loop.get_context() + context = self.loop.get_context() while True: context.iteration(True) if self.isStop: - return + print "++++++++++++++++++++++++++++++++++++++++" + print "++++++++++++++++++++++++++++++++++++++++" + print "++++++++++++++++++++++++++++++++++++++++" + print "++++++++++++++++++++++++++++++++++++++++" + return diff --git a/tools/pysflphone/sflphoned.functest.yml b/tools/pysflphone/sflphoned.functest.yml new file mode 100644 index 0000000000000000000000000000000000000000..926a0506b642f640a7dbf57396e85f8757051a3b --- /dev/null +++ b/tools/pysflphone/sflphoned.functest.yml @@ -0,0 +1,208 @@ +--- +accounts: +- alias: 100 + codecs: 0/3/8/9/110/111/112/ + credential: + - Account.password: password + Account.realm: '*' + Account.username: 100 + displayName: + dtmfType: overrtp + enable: true + hostname: 127.0.0.1:5062 + id: Account:1334024061 + interface: default + mailbox: + port: 5060 + publishAddr: 0.0.0.0 + publishPort: 5060 + registrationexpire: 600 + ringtoneEnabled: true + ringtonePath: /home/alexandresavard/Development/sflphone/gnome + sameasLocal: true + serviceRoute: + srtp: + enable: false + keyExchange: + rtpFallback: false + stunEnabled: false + stunServer: stun.sflphone.org + tls: + calist: + certificate: + ciphers: + enable: false + method: TLSv1 + password: + privateKey: + requireCertif: true + server: + timeout: 2 + tlsPort: 5061 + verifyClient: true + verifyServer: true + type: SIP + updateContact: false + username: 100 + zrtp: + displaySas: true + displaySasOnce: false + helloHashEnabled: true + notSuppWarning: true +- alias: 200 + codecs: 0/3/8/9/110/111/112/ + credential: + - Account.password: password + Account.realm: '*' + Account.username: 200 + displayName: + dtmfType: overrtp + enable: true + hostname: 127.0.0.1:5062 + id: Account:1334024356 + interface: default + mailbox: + port: 5060 + publishAddr: 0.0.0.0 + publishPort: 5060 + registrationexpire: 600 + ringtoneEnabled: true + ringtonePath: /home/alexandresavard/Development/sflphone/gnome + sameasLocal: true + serviceRoute: + srtp: + enable: false + keyExchange: + rtpFallback: false + stunEnabled: false + stunServer: stun.sflphone.org + tls: + calist: + certificate: + ciphers: + enable: false + method: TLSv1 + password: + privateKey: + requireCertif: true + server: + timeout: 2 + tlsPort: 5061 + verifyClient: true + verifyServer: true + type: SIP + updateContact: false + username: 200 + zrtp: + displaySas: true + displaySasOnce: false + helloHashEnabled: true + notSuppWarning: true +- alias: + codecs: 0/3/8/9/110/111/112/ + credential: + - Account.password: + Account.realm: '*' + Account.username: + displayName: + dtmfType: overrtp + enable: true + hostname: + id: IP2IP + interface: default + mailbox: + port: 5060 + publishAddr: + publishPort: 5060 + registrationexpire: 600 + ringtoneEnabled: true + ringtonePath: /usr/share/sflphone/ringtones/konga.ul + sameasLocal: true + serviceRoute: + srtp: + enable: false + keyExchange: sdes + rtpFallback: false + stunEnabled: false + stunServer: stun.sflphone.org + tls: + calist: + certificate: + ciphers: + enable: false + method: TLSv1 + password: + privateKey: + requireCertif: true + server: + timeout: 2 + tlsPort: 5061 + verifyClient: true + verifyServer: true + type: SIP + updateContact: false + username: + zrtp: + displaySas: true + displaySasOnce: false + helloHashEnabled: true + notSuppWarning: true +preferences: + historyLimit: 30 + historyMaxCalls: 20 + md5Hash: false + notifyMails: false + order: Account:1334024356/Account:1334024061/ + portNum: 5060 + registrationexpire: 180 + searchBarDisplay: true + zeroConfenable: false + zoneToneChoice: North America +voipPreferences: + playDtmf: true + playTones: true + pulseLength: 250 + symmetric: true + zidFile: true +addressbook: + business: true + enabled: true + home: true + list: + maxResults: 25 + mobile: true + photo: true +hooks: + iax2Enabled: false + numberAddPrefix: + numberEnabled: false + sipEnabled: false + urlCommand: x-www-browser + urlSipField: X-sflphone-url +audio: + alsa: + cardIn: 0 + cardOut: 0 + cardRing: 0 + plugin: default + smplRate: 44100 + alwaysRecording: false + audioApi: pulseaudio + echoCancel: false + echoDelayLength: 0 + echoTailLength: 100 + noiseReduce: true + pulse: + devicePlayback: alsa_output.pci-0000_00_1b.0.analog-stereo + deviceRecord: alsa_input.pci-0000_00_1b.0.analog-stereo + deviceRingtone: alsa_output.pci-0000_00_1b.0.analog-stereo + recordPath: + volumeMic: 100 + volumeSpkr: 100 +shortcuts: + hangUp: + pickUp: + popupWindow: + toggleHold: + togglePickupHangup: +... diff --git a/tools/pysflphone/sippwrap.py b/tools/pysflphone/sippwrap.py new file mode 100644 index 0000000000000000000000000000000000000000..0bdc07355893fca4a475267d00707323b3e84f97 --- /dev/null +++ b/tools/pysflphone/sippwrap.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +# +# Copyright (C) 2012 by the Free Software Foundation, Inc. +# +# Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import os + +class SippWrapper: + """ Wrapper taht allow for managing sipp command line easily """ + + def __init__(self): + self.commandLine = "./sipp" + self.remoteServer = "" + self.remotePort = "" + self.localInterface = "" + self.localPort = "" + self.customScenarioFile = "" + self.isUserAgenClient = True + self.launchInBackground = False + self.numberOfCall = 0 + self.numberOfSimultaneousCall = 0 + self.enableTraceMsg = False + self.enableTraceShormsg = False + self.enableTraceScreen = False + self.enableTraceError = False + self.enableTraceStat = False + self.enableTraceCounts = False + self.enableTraceRtt = False + self.enableTraceLogs = False + + def buildCommandLine(self, port): + """ Fill the command line arguments based on specified parameters """ + + self.localPort = str(port) + + if not self.remotePort and not self.remoteServer: + self.isUserAgentClient = False + elif self.remotePort and not self.remoteServer: + print "Error cannot have remote port specified with no server" + return + + if self.remoteServer: + self.commandLine += " " + self.remoteServer + + if self.remotePort: + self.commandLine += ":" + self.remotePort + + if self.localInterface: + self.commandLine += " -i " + self.localInterface + + if self.localPort: + self.commandLine += " -p " + self.localPort + + if self.customScenarioFile: + self.commandLine += " -sf " + self.customScenarioFile + elif self.isUserAgentClient is True: + self.commandLine += " -sn uac" + elif self.isUserAgentClient is False: + self.commandLine += " -sn uas" + + if self.launchInBackground: + self.commandLine += " -bg" + + if self.numberOfCall: + self.commandLine += " -m " + str(self.numberOfCall) + + if self.numberOfSimultaneousCall: + self.commandLine += " -l " + str(self.numberOfSimultaneousCall) + + if self.enableTraceMsg: + self.commandLine += " -trace_msg" + + if self.enableTraceShormsg: + self.commandLine += " -trace_shortmsg" + + if self.enableTraceScreen: + self.commandLine += " -trace_screen" + + if self.enableTraceError: + self.commandLine += " -trace_err" + + if self.enableTraceStat: + self.commandLine += " -trace_stat" + + if self.enableTraceCounts: + self.commandLine += " -trace_counts" + + if self.enableTraceRtt: + self.commandLine += " -trace_rtt" + + if self.enableTraceLogs: + self.commandLine += " -trace_logs" + + + def launch(self): + """ Launch the sipp instance using the specified arguments """ + + print self.commandLine + return os.system(self.commandLine + " 2>&1 > /dev/null") + + +class SippScreenStatParser: + """ Class that parse statistic reported by a sipp instance + report some of the most important value """ + + def __init__(self, filename): + print "Opening " + filename + self.logfile = open(filename, "r").readlines() + print self.logfile[39] + print self.logfile[40] + + def isAnyFailedCall(self): + """ Look for any failed call + Return true if there are failed call, false elsewhere """ + + # TODO: Find a better way to determine which line to consider + if "Failed call" not in self.logfile[40]: + print "Error: Could not find 'Failed call' statistics" + # We consider this as a failure + return True + + return "1" in self.logfile[40] + + def isAnySuccessfulCall(self): + """ Look for any successful call + Return true if there are successful call, false elsewhere """ + + # TODO: Find a better way to determine which line to consider + if "Successful call" not in self.logfile[39]: + print "Error: Could not find 'Successful call' statistics" + return False + + return "1" in self.logfile[39] + + + +def test_result_parsing(): + dirlist = os.listdir("./") + + logfile = [x for x in dirlist if "screen.log" in x] + testResult = SippScreenStatParser(logfile[0]) + + assert(not testResult.isAnyFailedCall()) + + assert(testResult.isAnySuccessfulCall()) diff --git a/tools/pysflphone/test_sflphone_dbus_interface.py b/tools/pysflphone/test_sflphone_dbus_interface.py new file mode 100644 index 0000000000000000000000000000000000000000..34dfee8a274b084c99b72b520f0b27f6eb31902e --- /dev/null +++ b/tools/pysflphone/test_sflphone_dbus_interface.py @@ -0,0 +1,412 @@ +#!/usr/bin/env python +# +# Copyright (C) 2012 by the Free Software Foundation, Inc. +# +# Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import os +import time +import yaml +import logging +import multiprocessing +from sippwrap import SippWrapper +from sippwrap import SippScreenStatParser +from sflphonectrl import SflPhoneCtrl + +from nose.tools import nottest + +### +### function starting with 'test' are executed. +### + +SCENARIO_PATH = "../sippxml/" + +class SippCtrl: + + def __init__(self): + self.remoteServer = "127.0.0.1" + self.remotePort = str(5062) + self.localInterface = "127.0.0.1" + self.localPort = str(5060) + + def initialize_sipp_registration_instance(self, instance, xmlScenario): + instance.remoteServer = self.remoteServer + instance.remotePort = self.remotePort + instance.localInterface = self.localInterface + instance.localPort = self.localPort + instance.customScenarioFile = SCENARIO_PATH + xmlScenario + instance.numberOfCall = 1 + instance.numberOfSimultaneousCall = 1 + + def initialize_sipp_call_instance(self, instance): + instance.localInterface = self.localInterface + instance.localPort = self.localPort + instance.numberOfCall = 1 + instance.numberOfSimultaneousCall = 1 + instance.enableTraceScreen = True + + def launchSippProcess(self, sippInstance, localPort): + sippInstance.buildCommandLine(localPort) + sippInstance.launch() + + def find_sipp_pid(self): + # Retreive the PID of the last + # The /proc/PID/cmdline contain the command line from + pids = [int(x) for x in os.listdir("/proc") if x.isdigit()] + sippPid = [pid for pid in pids if "sipp" in open("/proc/" + str(pid) + "/cmdline").readline()] + + return sippPid[0] + + def clean_log_directory(self): + dirlist = os.listdir("./") + files = [x for x in dirlist if "screen.log" in x] + for f in files: + os.remove(f) + + def parse_results(self): + dirlist = os.listdir("./") + logfile = [x for x in dirlist if "screen.log" in x] + + fullpath = os.path.dirname(os.path.realpath(__file__)) + "/" + + # there should be only one screen.log file (see clean_log_directory) + resultParser = SippScreenStatParser(fullpath + logfile[0]) + + assert(not resultParser.isAnyFailedCall()) + assert(resultParser.isAnySuccessfulCall()) + +class TestSFLPhoneAccountConfig(SflPhoneCtrl): + """ The test suite for account configuration """ + + def __init__(self): + SflPhoneCtrl.__init__(self) + + self.logger = logging.getLogger("TestSFLPhoneAccountConfig") + filehdlr = logging.FileHandler("/tmp/sflphonedbustest.log") + formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s") + filehdlr.setFormatter(formatter) + self.logger.addHandler(filehdlr) + self.logger.setLevel(logging.INFO) + + + def get_config(self): + """ Parsse configuration file and return a dictionary """ + config = {} + with open("sflphoned.functest.yml","r") as stream: + config = yaml.load(stream) + + return config + + + def get_account_list_from_config(self): + """ Get the accout list from config and add IP2IP """ + + config = self.get_config() + + accounts = config["preferences"]["order"] + accountList = accounts.split('/') + del accountList[len(accountList)-1] + accountList.append("IP2IP") + + return accountList + + + def test_get_account_list(self): + self.logger.info("Test get account list") + + accountList = self.get_account_list_from_config() + + # make sure that the intersection between the list is of same size + accList = self.getAllAccounts() + listIntersection = set(accList) & set(accountList) + assert len(listIntersection) == len(accountList) + + + def test_account_registration(self): + self.logger.info("Test account registration") + accList = [x for x in self.getAllAccounts() if x != "IP2IP"] + for acc in accList: + self.logger.info("Registering account " + acc) + + if self.isAccountEnable(acc): + self.setAccountEnable(acc, False) + time.sleep(2) + + # Account should not be registered + assert self.isAccountRegistered(acc) + + self.setAccountEnable(acc, True) + time.sleep(2) + + assert self.isAccountRegistered(acc) + + + @nottest + def test_get_account_details(self): + self.logger.info("Test account details") + + accList = [x for x in self.getAllAccounts() if x != "IP2IP"] + + config = self.get_config() + + accountDetails = {} + for acc in accList: + accountDetails[acc] = self.getAccountDetails(acc) + + accountConfDetails = {} + for accConf in config["accounts"]: + accountConfDetails[accConf["id"]] = accConf + + + @nottest + def test_add_remove_account(self): + self.logger.info("Test add/remove account") + accountDetails = {} + newAccList = [] + + # consider only true accounts + accList = [x for x in self.getAllAccounts() if x != "IP2IP"] + + # Store the account details localy + for acc in accList: + accountDetails[acc] = self.getAccountDetails(acc) + + # Remove all accounts from sflphone + for acc in accountDetails: + self.removeAccount(acc) + + # Recreate all accounts + for acc in accountDetails: + newAccList.append(self.addAccount(accountDetails[acc])) + + # New accounts should be automatically registered + for acc in newAccList: + assert self.isAccountRegistered(acc) + + + +class TestSFLPhoneRegisteredCalls(SflPhoneCtrl, SippCtrl): + """ The test suite for call interaction """ + + def __init__(self): + SflPhoneCtrl.__init__(self) + SippCtrl.__init__(self) + + self.logger = logging.getLogger("TestSFLPhoneRegisteredCalls") + filehdlr = logging.FileHandler("/tmp/sfltestregisteredcall.log") + formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s") + filehdlr.setFormatter(formatter) + self.logger.addHandler(filehdlr) + self.logger.setLevel(logging.INFO) + self.sippRegistrationInstance = SippWrapper() + self.sippCallInstance = SippWrapper() + + # Make sure the test directory is populated with most recent log files + self.clean_log_directory() + + + def onCallCurrent_cb(self): + """ On incoming call, answer the callm, then hangup """ + + print "Hangup Call with id " + self.currentCallId + self.HangUp(self.currentCallId) + + print "Stopping Thread" + self.stopThread() + + + def onCallRinging_cb(self): + """ Display messages when call is ringing """ + + print "The call is ringing" + + + def onCallFailure_cb(self): + """ If a failure occurs duing the call, just leave the running thread """ + + print "Stopping Thread" + self.stopThread() + + + def test_registered_call(self): + self.logger.info("Test Registered Call") + + # Launch a sipp instance for account registration on asterisk + # this account will then be used to receive call from sflphone + self.initialize_sipp_registration_instance(self.sippRegistrationInstance, "uac_register_no_cvs_300.xml") + regd = multiprocessing.Process(name='sipp1register', target=self.launchSippProcess, + args=(self.sippRegistrationInstance, 5064,)) + regd.start() + + # wait for the registration to complete + regd.join() + + # Launch a sipp instance waiting for a call from previously registered account + self.initialize_sipp_call_instance(self.sippCallInstance) + calld = multiprocessing.Process(name='sipp1call', target=self.launchSippProcess, + args=(self.sippCallInstance, 5064,)) + calld.start() + + # Make sure every account are enabled + accList = [x for x in self.getAllAccounts() if x != "IP2IP"] + for acc in accList: + if not self.isAccountRegistered(acc): + self.setAccountEnable(acc, True) + + # Make a call to the SIPP instance + self.Call("300") + + # Start the threaded loop to handle GLIB cllbacks + self.start() + + # Wait for the sipp instance to dump log files + calld.join() + + self.stopThread() + self.parse_results() + + +class TestSFLPhoneConferenceCalls(SflPhoneCtrl, SippCtrl): + """ Test Conference calls """ + + def __init__(self): + SflPhoneCtrl.__init__(self) + SippCtrl.__init__(self) + + self.logger = logging.getLogger("TestSFLPhoneRegisteredCalls") + filehdlr = logging.FileHandler("/tmp/sfltestregisteredcall.log") + formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s") + filehdlr.setFormatter(formatter) + self.logger.addHandler(filehdlr) + self.logger.setLevel(logging.INFO) + self.sippRegistrationInstanceA = SippWrapper() + self.sippRegistrationInstanceB = SippWrapper() + self.sippCallInstanceA = SippWrapper() + self.sippCallInstanceB = SippWrapper() + self.localPortCallA = str(5064) + self.localPortCallB = str(5066) + self.callCount = 0 + self.accountCalls = [] + + # Make sure the test directory is populated with most recent log files + # self.clean_log_directory() + + + def onCallCurrent_cb(self): + """ On incoming call, answer the call, then hangup """ + + self.callCount += 1 + + self.accountCalls.append(self.currentCallId) + print "Account List: ", str(self.accountCalls) + + if self.callCount == 2: + self.createConference(self.accountCalls[0], self.accountCalls[1]) + + + def onCallRinging_cb(self): + """ Display messages when call is ringing """ + + print "The call is ringing" + + + def onCallHangup_cb(self, callId): + """ Exit thread when all call are finished """ + + if callId in self.accountCalls: + self.accountCalls.remove(callId) + + self.callCount -= 1 + if self.callCount == 0: + self.stopThread() + + + def onCallFailure_cb(self): + """ If a failure occurs duing the call, just leave the running thread """ + + print "Stopping Thread" + self.stopThread() + + + def onConferenceCreated_cb(self): + """ Called once the conference is created """ + + print "Conference Created ", self.currentConfId + print "Conference Hangup ", self.currentConfId + + self.hangupConference(self.currentConfId) + + + def test_conference_call(self): + self.logger.info("Test Registered Call") + + # launch the sipp instance to register the first participant to astersik + self.initialize_sipp_registration_instance(self.sippRegistrationInstanceA, "uac_register_no_cvs_300.xml") + regd = multiprocessing.Process(name='sipp1register', target=self.launchSippProcess, + args=(self.sippRegistrationInstanceA, 5064,)) + regd.start() + regd.join() + + # launch the sipp instance to register the second participant to asterisk + self.initialize_sipp_registration_instance(self.sippRegistrationInstanceB, "uac_register_no_cvs_400.xml") + regd = multiprocessing.Process(name='sipp2register', target=self.launchSippProcess, + args=(self.sippRegistrationInstanceB, 5066,)) + regd.start() + regd.join() + + # launch the sipp instance waining for call as the first participant + self.initialize_sipp_call_instance(self.sippCallInstanceA) + calldA = multiprocessing.Process(name='sipp1call', target=self.launchSippProcess, + args=(self.sippCallInstanceA, 5064,)) + calldA.start() + + + # launch the sipp instance waiting for call as the second particpant + self.initialize_sipp_call_instance(self.sippCallInstanceB) + calldB = multiprocessing.Process(name='sipp2call', target=self.launchSippProcess, + args=(self.sippCallInstanceB, 5066,)) + calldB.start() + + # make sure every account are enabled + accList = [x for x in self.getAllAccounts() if x != "IP2IP"] + for acc in accList: + if not self.isAccountRegistered(acc): + self.setAccountEnable(acc, True) + + # make a call to the SIPP instance + self.Call("300") + self.Call("400") + + # start the main loop for processing glib callbacks + self.start() + + print "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" + calldA.join() + print "+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+" + calldB.join() + + print "=====================================================" + + self.stopThread() + self.parse_results() + + +# callInstance = TestSFLPhoneRegisteredCalls() +# callInstance.test_registered_call() + +confInstance = TestSFLPhoneConferenceCalls() +confInstance.test_conference_call() diff --git a/tools/sippxml/uac_register_no_cvs_300.xml b/tools/sippxml/uac_register_no_cvs_300.xml new file mode 100644 index 0000000000000000000000000000000000000000..f22ae377a8df43ddbcd8800e4d1f57d49765d306 --- /dev/null +++ b/tools/sippxml/uac_register_no_cvs_300.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="ISO-8859-2" ?> + +<!-- Use with CSV file struct like: 3000;192.168.1.106;[authentication username=3000 password=3000]; + (user part of uri, server address, auth tag in each line) +--> + +<scenario name="register_client"> + <send retrans="500"> + <![CDATA[ + + REGISTER sip:127.0.0.1 SIP/2.0 + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] + From: <sip:300@127.0.0.1>;tag=[call_number] + To: <sip:300@127.0.0.1> + Call-ID: [call_id] + CSeq: [cseq] REGISTER + Contact: sip:300@[local_ip]:[local_port] + Max-Forwards: 10 + Expires: 120 + User-Agent: SIPp/Win32 + Content-Length: 0 + + ]]> + </send> + + <!-- asterisk --> + <recv response="200"> + <!-- + <action> + <ereg regexp=".*" search_in="hdr" header="Contact:" check_it="true" assign_to="1" /> + </action> + --> + </recv> + + <!-- + <recv request="INVITE" crlf="true"> + </recv> + + <send> + <![CDATA[ + + SIP/2.0 180 Ringing + [last_Via:] + [last_From:] + [last_To:];tag=[pid]SIPpTag01[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Length: 0 + + ]]> + </send> + + <send retrans="500"> + <![CDATA[ + + SIP/2.0 200 OK + [last_Via:] + [last_From:] + [last_To:];tag=[pid]SIPpTag01[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + </send> + + <recv request="ACK" + optional="true" + rtd="true" + crlf="true"> + </recv> + + <recv request="BYE"> + </recv> + + <send> + <![CDATA[ + + SIP/2.0 200 OK + [last_Via:] + [last_From:] + [last_To:] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Length: 0 + + ]]> + </send> + + <timewait milliseconds="4000"/> + + + <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> + + <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> + --> + +</scenario> diff --git a/tools/sippxml/uac_register_no_cvs_400.xml b/tools/sippxml/uac_register_no_cvs_400.xml new file mode 100644 index 0000000000000000000000000000000000000000..ccceacdf7748bbe490cfe306222724e4dfe93c99 --- /dev/null +++ b/tools/sippxml/uac_register_no_cvs_400.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="ISO-8859-2" ?> + +<!-- Use with CSV file struct like: 3000;192.168.1.106;[authentication username=3000 password=3000]; + (user part of uri, server address, auth tag in each line) +--> + +<scenario name="register_client"> + <send retrans="500"> + <![CDATA[ + + REGISTER sip:127.0.0.1 SIP/2.0 + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] + From: <sip:300@127.0.0.1>;tag=[call_number] + To: <sip:400@127.0.0.1> + Call-ID: [call_id] + CSeq: [cseq] REGISTER + Contact: sip:300@[local_ip]:[local_port] + Max-Forwards: 10 + Expires: 120 + User-Agent: SIPp/Win32 + Content-Length: 0 + + ]]> + </send> + + <!-- asterisk --> + <recv response="200"> + <!-- + <action> + <ereg regexp=".*" search_in="hdr" header="Contact:" check_it="true" assign_to="1" /> + </action> + --> + </recv> + + <!-- + <recv request="INVITE" crlf="true"> + </recv> + + <send> + <![CDATA[ + + SIP/2.0 180 Ringing + [last_Via:] + [last_From:] + [last_To:];tag=[pid]SIPpTag01[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Length: 0 + + ]]> + </send> + + <send retrans="500"> + <![CDATA[ + + SIP/2.0 200 OK + [last_Via:] + [last_From:] + [last_To:];tag=[pid]SIPpTag01[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + </send> + + <recv request="ACK" + optional="true" + rtd="true" + crlf="true"> + </recv> + + <recv request="BYE"> + </recv> + + <send> + <![CDATA[ + + SIP/2.0 200 OK + [last_Via:] + [last_From:] + [last_To:] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Length: 0 + + ]]> + </send> + + <timewait milliseconds="4000"/> + + + <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> + + <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> + --> + +</scenario>