diff --git a/.gitignore b/.gitignore index 6c16ccfeee2ba7a992f26776dcceec93e7900c60..a80993a56d6799c99f1445a3ec3e03d687ac4450 100644 --- a/.gitignore +++ b/.gitignore @@ -17,10 +17,9 @@ Makefile.in *.mo # Ignore rendered docs -doc/doxygen/html-everything -doc/doxygen/html-sflphoned +doc/doxygen/core-doc +doc/doxygen/gtk-gui-doc doc/*.html -sflphone-gtk/doc/html/* # Ignore buildsys stuff /autom4te.cache diff --git a/doc/doxygen/Makefile.am b/doc/doxygen/Makefile.am index a1a0473e7c157fc43814ef6c93b407e4954541e9..57c36f9880e53b6611515a0961a798e247d67389 100644 --- a/doc/doxygen/Makefile.am +++ b/doc/doxygen/Makefile.am @@ -5,8 +5,8 @@ html_parent_dir = . HTML_HEADER = HTML_FOOTER = -all: - +all: doxygen-trac + .PHONY: doxygen-trac doxygen-trac: clean core-doc-trac gtk-gui-doc-trac @@ -52,4 +52,4 @@ maintainer-clean-local: clean-local sed < $@.tmp3 > $@.tmp4 \ -e 's:@-html_footer-@:${HTML_FOOTER}:g' rm $@.tmp3 - mv $@.tmp4 $@ \ No newline at end of file + mv $@.tmp4 $@ diff --git a/doc/doxygen/core-doc.cfg.in b/doc/doxygen/core-doc.cfg.in index 13939c756dc7d89cb2b16618671b3523126c1cae..c526acc255ccdcdcaf4fc3c4315b7e8ae7c551a7 100644 --- a/doc/doxygen/core-doc.cfg.in +++ b/doc/doxygen/core-doc.cfg.in @@ -4,7 +4,7 @@ # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = SFLPhoneCore +PROJECT_NAME = SFLphone Core PROJECT_NUMBER = OUTPUT_DIRECTORY = CREATE_SUBDIRS = NO @@ -75,10 +75,10 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = @-top_srcdir-@/src +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 INPUT_ENCODING = UTF-8 FILE_PATTERNS = -RECURSIVE = YES +RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = diff --git a/doc/doxygen/gtk-gui-doc.cfg.in b/doc/doxygen/gtk-gui-doc.cfg.in index caa00e1bbbffa6752aa8f2e589fe0383df65146b..dff19c26003819dcbff825911ab09d5e3150378f 100644 --- a/doc/doxygen/gtk-gui-doc.cfg.in +++ b/doc/doxygen/gtk-gui-doc.cfg.in @@ -26,7 +26,7 @@ INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YESsrc +OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO @@ -75,10 +75,10 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = @-top_srcdir-@/sflphone-gtk/src +INPUT = @-top_srcdir-@/sflphone-gtk/src INPUT_ENCODING = UTF-8 FILE_PATTERNS = -RECURSIVE = YES +RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = diff --git a/doc/images/devel.png b/doc/images/devel.png new file mode 100644 index 0000000000000000000000000000000000000000..70a0d06667dffbd6acc6ad7276da96cebe85d21b Binary files /dev/null and b/doc/images/devel.png differ diff --git a/doc/images/fetch.png b/doc/images/fetch.png new file mode 100644 index 0000000000000000000000000000000000000000..778b9de1c54b0bf95ebb01c852cb829adb1808d7 Binary files /dev/null and b/doc/images/fetch.png differ diff --git a/doc/images/home.png b/doc/images/home.png new file mode 100644 index 0000000000000000000000000000000000000000..4e78a3112f1b765a334d454daa8979431dd13159 Binary files /dev/null and b/doc/images/home.png differ diff --git a/doc/images/info.png b/doc/images/info.png new file mode 100644 index 0000000000000000000000000000000000000000..3e0729c6757590db194ea291ae00058601e4a0bc Binary files /dev/null and b/doc/images/info.png differ diff --git a/doc/images/screenshots/accounts.png b/doc/images/screenshots/accounts.png new file mode 100644 index 0000000000000000000000000000000000000000..2a1d033892ad357faf1e79c20141ffb9b6bd1d80 Binary files /dev/null and b/doc/images/screenshots/accounts.png differ diff --git a/doc/images/screenshots/audio-parameters.png b/doc/images/screenshots/audio-parameters.png new file mode 100644 index 0000000000000000000000000000000000000000..7be7badab519fd06a3c5ef00f9c2916f12511f4b Binary files /dev/null and b/doc/images/screenshots/audio-parameters.png differ diff --git a/doc/images/screenshots/desktop-notif-voice mail.png b/doc/images/screenshots/desktop-notif-voice mail.png new file mode 100644 index 0000000000000000000000000000000000000000..4d2899877f696477da49f7cee1935e52d43189bf Binary files /dev/null and b/doc/images/screenshots/desktop-notif-voice mail.png differ diff --git a/doc/images/screenshots/desktop-notification.png b/doc/images/screenshots/desktop-notification.png new file mode 100644 index 0000000000000000000000000000000000000000..c854b8252253f8fdb9c89ee41fc02b2ef2ca9c3a Binary files /dev/null and b/doc/images/screenshots/desktop-notification.png differ diff --git a/doc/images/screenshots/gtk gui.png b/doc/images/screenshots/gtk gui.png new file mode 100644 index 0000000000000000000000000000000000000000..958beb4ee40b156630d41ecb7c5ce77f35cb4256 Binary files /dev/null and b/doc/images/screenshots/gtk gui.png differ diff --git a/doc/images/screenshots/several-calls.png b/doc/images/screenshots/several-calls.png new file mode 100644 index 0000000000000000000000000000000000000000..65dc12dbcbba742c04f3d974bca9fe660a004756 Binary files /dev/null and b/doc/images/screenshots/several-calls.png differ diff --git a/sflphone-gtk/src/Makefile.am b/sflphone-gtk/src/Makefile.am index e54bc24bc830d624de95f618e61e38ff9f13b607..47e5621c4b7b087327f5e2e9ddd3d2a3cac5b639 100644 --- a/sflphone-gtk/src/Makefile.am +++ b/sflphone-gtk/src/Makefile.am @@ -2,15 +2,15 @@ bin_PROGRAMS = sflphone-gtk sflphone_gtk_SOURCES = \ main.c \ + errors.c \ dbus.c \ - SFLnotify.c \ + sflnotify.c \ mainwindow.c \ calllist.c \ dialpad.c \ menus.c \ calltab.c \ calltree.c \ - screen.c \ actions.c \ configwindow.c \ accountlist.c \ @@ -22,8 +22,8 @@ sflphone_gtk_SOURCES = \ glwidget.c \ MemManager.c -noinst_HEADERS = actions.h dbus.h SFLnotify.h mainwindow.h calllist.h dialpad.h codeclist.h\ - callmanager-glue.h configurationmanager-glue.h instance-glue.h menus.h calltab.h calltree.h screen.h configwindow.h \ +noinst_HEADERS = actions.h dbus.h sflnotify.h mainwindow.h calllist.h dialpad.h codeclist.h\ + callmanager-glue.h errors.h sflphone_const.h configurationmanager-glue.h instance-glue.h menus.h calltab.h calltree.h configwindow.h \ accountlist.h accountwindow.h marshaller.h sliders.h statusicon.h EXTRA_DIST = marshaller.list sflphone_gtk_LDADD = $(DEPS_LIBS) -lnotify diff --git a/sflphone-gtk/src/SFLnotify.c b/sflphone-gtk/src/SFLnotify.c deleted file mode 100644 index 5a4308cd6a51468d091940beb6405ef68afc9072..0000000000000000000000000000000000000000 --- a/sflphone-gtk/src/SFLnotify.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2008 Savoir-Faire Linux inc. - * 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. - */ - -#include <SFLnotify.h> - -static NotifyNotification *notification; - -void -notify_incoming_call( call_t* c ) -{ - GdkPixbuf *pixbuf; - gchar* callerid; - gchar* title; - notify_init("sflphone"); - - title = g_markup_printf_escaped(_("%s account: %s") , - g_hash_table_lookup(account_list_get_by_id(c->accountID)->properties , ACCOUNT_TYPE) , - g_hash_table_lookup(account_list_get_by_id(c->accountID)->properties , ACCOUNT_ALIAS) ) ; - callerid = g_markup_printf_escaped(_("<i>From:</i> %s") , c->from); - - - //pixbuf = gdk_pixbuf_new_from_file(ICON_DIR "/sflphone.png", NULL); - pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL); - - notification = notify_notification_new( title, - callerid, - NULL, - NULL); - notify_notification_set_urgency( notification , NOTIFY_URGENCY_NORMAL ); - notify_notification_set_icon_from_pixbuf (notification, pixbuf); - notify_notification_attach_to_status_icon( notification , get_status_icon() ); - notify_notification_set_timeout( notification , (( g_strcasecmp(__TIMEOUT_MODE, "default") == 0 )? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER )); - g_object_set_data( G_OBJECT( notification ) , "call" , c ); - notify_notification_add_action( notification , "accept" , _("Accept") , (NotifyActionCallback) answer_call_cb , NULL, NULL ); - notify_notification_add_action( notification , "refuse" , _("Refuse") , (NotifyActionCallback) refuse_call_cb , NULL , NULL ); - notify_notification_add_action( notification , "ignore" , _("Ignore") , (NotifyActionCallback) ignore_call_cb , NULL , NULL ); - - if (!notify_notification_show (notification, NULL)) { - g_print("notify(), failed to send notification\n"); - } -} - -void -answer_call_cb( NotifyNotification *notification, gchar *action, gpointer data ) -{ - call_t* c = (call_t*)g_object_get_data( G_OBJECT( notification ) , "call" ); - dbus_accept(c); -#ifdef __POPUP_WINDOW - status_icon_unminimize(); -#endif - g_object_unref( notification ); -} - -void -refuse_call_cb( NotifyNotification *notification, gchar *action, gpointer data ) -{ - call_t* c = (call_t*)g_object_get_data( G_OBJECT( notification ) , "call" ); - dbus_refuse(c); - g_object_unref( notification ); -} - -void -ignore_call_cb( NotifyNotification *notification, gchar *action, gpointer data ) -{ - g_object_unref( notification ); -} - -void -notify_voice_mails( guint count , account_t* acc ) -{ - // the account is different from NULL - GdkPixbuf *pixbuf; - gchar* title; - gchar* body; - notify_init("sflphone"); - - title = g_markup_printf_escaped(_("%s account: %s") , - g_hash_table_lookup(acc->properties , ACCOUNT_TYPE) , - g_hash_table_lookup(acc->properties , ACCOUNT_ALIAS) ) ; - body = g_markup_printf_escaped(_("%d voice mails"), count); - - pixbuf = gdk_pixbuf_new_from_file(ICON_DIR "/sflphone.png", NULL); - - notification = notify_notification_new( title, - body, - NULL, - NULL); - notify_notification_set_urgency( notification , NOTIFY_URGENCY_NORMAL ); - notify_notification_set_icon_from_pixbuf (notification, pixbuf); - notify_notification_attach_to_status_icon( notification , get_status_icon() ); - notify_notification_set_timeout( notification , NOTIFY_EXPIRES_DEFAULT ); - notify_notification_add_action( notification , "ignore" , _("Ignore") , (NotifyActionCallback) ignore_call_cb , NULL , NULL ); - - if (!notify_notification_show (notification, NULL)) { - g_print("notify(), failed to send notification\n"); - } -} diff --git a/sflphone-gtk/src/accountlist.c b/sflphone-gtk/src/accountlist.c index c851238dc056a57311a28c8c7d23332af3bdff1d..a075d5799041cb9e60932ccf1d88aab4bef86608 100644 --- a/sflphone-gtk/src/accountlist.c +++ b/sflphone-gtk/src/accountlist.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,7 @@ #include <string.h> GQueue * accountQueue; -gchar * DEFAULT_ACCOUNT=NULL; +gchar* __CURRENT_ACCOUNT_ID = NULL; /* GCompareFunc to compare a accountID (gchar* and a account_t) */ gint @@ -126,23 +126,32 @@ account_list_get_nth ( guint n ) return g_queue_peek_nth (accountQueue, n); } -gchar * -account_list_get_default( ) +account_t* +account_list_get_current( ) { - return DEFAULT_ACCOUNT; + if( __CURRENT_ACCOUNT_ID != NULL ) + return account_list_get_by_id( __CURRENT_ACCOUNT_ID ); + else + return NULL; +} + +void +account_list_set_current_id(const gchar * accountID) +{ + __CURRENT_ACCOUNT_ID = g_strdup(accountID); } void -account_list_set_default(const gchar * accountID) +account_list_set_current_pos( guint n) { - DEFAULT_ACCOUNT = g_strdup(accountID); - g_print("DEFAULT_ACCOUNT = %s\n", DEFAULT_ACCOUNT); + __CURRENT_ACCOUNT_ID = account_list_get_nth(n)->accountID; } + const gchar * account_state_name(account_state_t s) { gchar * state; - switch(s) + switch(s) { case ACCOUNT_STATE_REGISTERED: state = _("Registered"); @@ -156,6 +165,14 @@ const gchar * account_state_name(account_state_t s) case ACCOUNT_STATE_ERROR: state = _("Error"); break; + case ACCOUNT_STATE_ERROR_AUTH: + state = _("Bad authentification"); + break; + case ACCOUNT_STATE_ERROR_NETWORK: + state = _("Network unreachable"); + + state = _("Host unreachable"); + break; default: state = _("Invalid"); break; @@ -169,3 +186,25 @@ account_list_clear ( ) g_queue_free (accountQueue); accountQueue = g_queue_new (); } + +void +account_list_move_up(guint index) +{ + if(index != 0) + { + gpointer acc = g_queue_pop_nth(accountQueue, index); + g_queue_push_nth(accountQueue, acc, index-1); + } + account_list_set_current_pos( 0 ); +} + +void +account_list_move_down(guint index) +{ + if(index != accountQueue->length) + { + gpointer acc = g_queue_pop_nth(accountQueue, index); + g_queue_push_nth(accountQueue, acc, index+1); + } + account_list_set_current_pos( 0 ); +} diff --git a/sflphone-gtk/src/accountlist.h b/sflphone-gtk/src/accountlist.h index 7269af52db8ea89943b65fb421efdce4c0cb46b0..e71ec3d9b9631eac945087188a73ee62ca11e6a5 100644 --- a/sflphone-gtk/src/accountlist.h +++ b/sflphone-gtk/src/accountlist.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify @@ -26,35 +26,27 @@ * @brief A list to hold accounts. */ -#define ACCOUNT_TYPE "Account.type" -#define ACCOUNT_ALIAS "Account.alias" -#define ACCOUNT_ENABLED "Account.enable" -//#define ACCOUNT_REGISTER "Account.autoregister" - -#define ACCOUNT_SIP_FULL_NAME "SIP.fullName" -#define ACCOUNT_SIP_HOST_PART "SIP.hostPart" -#define ACCOUNT_SIP_USER_PART "SIP.userPart" -#define ACCOUNT_SIP_AUTH_NAME "SIP.username" -#define ACCOUNT_SIP_PASSWORD "SIP.password" -#define ACCOUNT_SIP_PROXY "SIP.proxy" -#define ACCOUNT_SIP_STUN_SERVER "STUN.server" -#define ACCOUNT_SIP_STUN_ENABLED "STUN.enable" - -#define ACCOUNT_IAX_FULL_NAME "IAX.fullName" -#define ACCOUNT_IAX_HOST "IAX.host" -#define ACCOUNT_IAX_USER "IAX.user" -#define ACCOUNT_IAX_PASS "IAX.pass" - /** @enum account_state_t * 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, - ACCOUNT_STATE_ERROR + /** Error state. The account is not registered */ + ACCOUNT_STATE_ERROR, + /** An authentification error occured. Wrong password or wrong username. The account is not registered */ + ACCOUNT_STATE_ERROR_AUTH, + /** The network is unreachable. The account is not registered */ + ACCOUNT_STATE_ERROR_NETWORK, + /** Host is unreachable. The account is not registered */ + ACCOUNT_STATE_ERROR_HOST } account_state_t; /** @struct account_t @@ -73,54 +65,95 @@ typedef struct { -/** This function initialize the account list. */ +/** + * This function initialize the account list. + */ void account_list_init (); -/** This function empty and free the account list. */ +/** + * This function empty and free the account list. + */ void account_list_clean (); -/** This function append an account to list. - * @param a The account you want to add */ +/** + * This function append an account to list. + * @param a The account you want to add + */ void account_list_add (account_t * a); -/** This function remove an account from list. - * @param accountID The accountID of the account you want to remove - */ +/** + * This function remove an account from list. + * @param accountID The accountID of the account you want to remove + */ void account_list_remove (const gchar * accountID); -/** Return the first account that corresponds to the state - * @param s The state - * @return An account or NULL */ +/** + * 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); -/** Return the number of accounts in the list - * @return The number of accounts in the list */ +/** + * Return the number of accounts in the list + * @return guint The number of accounts in the list + */ 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 */ +/** + * 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 ); -/** Return the account's id chosen as default - * @return The default account */ -gchar * account_list_get_default( ); +/** + * Return the current account struct + * @return The current account struct + */ +account_t * account_list_get_current( ); -/** This function sets an account as default - * @param n The position of the account you want to select +/** + * This function sets an account as the current one + * @param accountID The ID of the current account */ -void account_list_set_default(const gchar * accountID); +void account_list_set_current_id(const gchar * accountID); -/** This function maps account_state_t enums to a description. - * @param s The state - * @return The full text description of the state */ +/** + * This function sets an account as the current one + * @param n the position of the account you want to use + */ +void account_list_set_current_pos( guint n ); + +/** + * 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); +/** + * This function clear the list + */ void account_list_clear ( ); -/** Return the account associated with an ID +/** + * Return the account associated with an ID * @param accountID The ID of the account - * @return An account or NULL */ + * @return An account or NULL + */ account_t * account_list_get_by_id(gchar * 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 ); + +/** + * 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 ); + #endif diff --git a/sflphone-gtk/src/accountwindow.c b/sflphone-gtk/src/accountwindow.c index 0ea3e8daf3fd0908975c98eba1d9d9d7846413c8..728faedd1a0991aecc93149a3a59c5a4ffc53dc7 100644 --- a/sflphone-gtk/src/accountwindow.c +++ b/sflphone-gtk/src/accountwindow.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -115,7 +115,7 @@ show_account_window (account_t * a) gchar * curFullName = ""; /* TODO: add curProxy, and add boxes for Proxy support */ gchar * stun_enabled = "FALSE"; - gchar * stun_server= ""; + gchar * stun_server= "stun.fwdnet.net:3478"; // Load from SIP/IAX/Unknown ? if(a) @@ -150,7 +150,7 @@ show_account_window (account_t * a) dialog = GTK_DIALOG(gtk_dialog_new_with_buttons (_("Account settings"), GTK_WINDOW(get_main_window()), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_SAVE, + GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, @@ -176,8 +176,9 @@ show_account_window (account_t * a) entryEnabled = gtk_check_button_new_with_mnemonic(_("_Enabled")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(entryEnabled), - strcmp(curAccountEnabled,"TRUE") == 0 ? TRUE: FALSE); + g_strcasecmp(curAccountEnabled,"TRUE") == 0 ? TRUE: FALSE); gtk_table_attach ( GTK_TABLE( table ), entryEnabled, 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_set_sensitive( GTK_WIDGET( entryEnabled ) , TRUE ); //entryRegister = gtk_check_button_new_with_mnemonic("_Register on startup "); //gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(entryRegister), @@ -311,8 +312,8 @@ show_account_window (account_t * a) gchar* proto = (gchar *)gtk_combo_box_get_active_text(GTK_COMBO_BOX(entryProtocol)); g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_ENABLED), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(entryEnabled)) ? "TRUE": "FALSE")); + g_strdup(ACCOUNT_ENABLED), + g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(entryEnabled)) ? "TRUE": "FALSE")); // g_hash_table_replace(currentAccount->properties, // g_strdup(ACCOUNT_REGISTER), // g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(entryRegister)) ? "TRUE": "FALSE")); diff --git a/sflphone-gtk/src/accountwindow.h b/sflphone-gtk/src/accountwindow.h index 1b88788f5deaad5ea7f2c2db40596409d38ffe2d..d0bcb0e6724f12439f6e4ea6b34c7da5ba14a0f9 100644 --- a/sflphone-gtk/src/accountwindow.h +++ b/sflphone-gtk/src/accountwindow.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -22,7 +23,11 @@ /** @file accountwindow.h * @brief The window to edit account details. */ - + +/** + * Display the main account widget + * @param a The account you want to edit or null for a new account + */ void show_account_window ( account_t * a ); #endif diff --git a/sflphone-gtk/src/actions.c b/sflphone-gtk/src/actions.c index 0eb060f298c564edd36961a8f0e04c1ffb220ef4..1eaa1c32b8635fd90795d1cab7bbf249c23a0426 100644 --- a/sflphone-gtk/src/actions.c +++ b/sflphone-gtk/src/actions.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,6 @@ #include <dbus.h> #include <mainwindow.h> #include <menus.h> -#include <screen.h> #include <statusicon.h> #include <calltab.h> @@ -34,18 +33,13 @@ #include <sys/types.h> #include <unistd.h> -#define ALSA_ERROR_CAPTURE_DEVICE 0 -#define ALSA_ERROR_PLAYBACK_DEVICE 1 - -#define TONE_WITHOUT_MESSAGE 0 -#define TONE_WITH_MESSAGE 1 - guint voice_mails; void -sflphone_notify_voice_mail (guint count) +sflphone_notify_voice_mail ( const gchar* accountID , guint count ) { voice_mails = count ; + gchar* id = g_strdup( accountID ); if(count > 0) { gchar * message = g_new0(gchar, 50); @@ -53,30 +47,15 @@ sflphone_notify_voice_mail (guint count) g_sprintf(message, _("%d voice mails"), count); else g_sprintf(message, _("%d voice mail"), count); - status_bar_message_add(message, __MSG_VOICE_MAILS); + statusbar_push_message(message, __MSG_VOICE_MAILS); g_free(message); } // TODO: add ifdef if( account_list_get_size() > 0 ) { - account_t* acc = account_list_get_by_state( ACCOUNT_STATE_REGISTERED ); - if( acc == NULL ) - { - // Notify that no account is registered - //notify_no_account_registered(); - } - else - { - if( account_list_get_default() == NULL ){ - // Notify that the first registered account has count voice mails + account_t* acc = account_list_get_by_id( id ); + if( acc != NULL ) notify_voice_mails( count , acc ); - } - else - { - // Notify that the default registered account has count voice mails - notify_voice_mails( count , account_list_get_by_id(account_list_get_default()) ); - } - } } } @@ -85,15 +64,14 @@ status_bar_display_account( call_t* c) { gchar* msg; account_t* acc; - if(c->accountID != NULL) + if(c->accountID != NULL){ acc = account_list_get_by_id(c->accountID); - else - acc = account_list_get_by_id( account_list_get_default()); - msg = g_markup_printf_escaped("%s account: %s" , - g_hash_table_lookup( acc->properties , ACCOUNT_TYPE), - g_hash_table_lookup( acc->properties , ACCOUNT_ALIAS)); - status_bar_message_add( msg , __MSG_ACCOUNT_DEFAULT); - g_free(msg); + msg = g_markup_printf_escaped("%s account- %s" , + (gchar*)g_hash_table_lookup( acc->properties , ACCOUNT_TYPE), + (gchar*)g_hash_table_lookup( acc->properties , ACCOUNT_ALIAS)); + statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT); + g_free(msg); + } } @@ -185,6 +163,18 @@ sflphone_fill_account_list() { a->state = ACCOUNT_STATE_ERROR; } + else if(strcmp( status , "ERROR_AUTH") == 0 ) + { + a->state = ACCOUNT_STATE_ERROR_AUTH; + } + else if(strcmp( status , "ERROR_NETWORK") == 0 ) + { + a->state = ACCOUNT_STATE_ERROR_NETWORK; + } + else if(strcmp( status , "ERROR_HOST") == 0 ) + { + a->state = ACCOUNT_STATE_ERROR_HOST; + } else { a->state = ACCOUNT_STATE_INVALID; @@ -213,8 +203,8 @@ sflphone_init() { dbus_register(getpid(), "Gtk+ Client"); sflphone_fill_account_list(); - sflphone_set_default_account(); sflphone_fill_codec_list(); + sflphone_set_current_account(); return TRUE; } } @@ -393,7 +383,7 @@ void process_dialing(call_t * c, guint keyval, gchar * key) // We stop the tone if(strlen(c->to) == 0 && c->state != CALL_STATE_TRANSFERT){ dbus_start_tone( FALSE , 0 ); - dbus_play_dtmf( key ); + //dbus_play_dtmf( key ); } switch (keyval) { @@ -435,6 +425,8 @@ void process_dialing(call_t * c, guint keyval, gchar * key) default: if (keyval < 255 || (keyval >65453 && keyval < 65466)) { + if(c->state != CALL_STATE_TRANSFERT) + dbus_play_dtmf( key ); gchar * before = c->to; c->to = g_strconcat(c->to, key, NULL); g_free(before); @@ -487,7 +479,7 @@ sflphone_keypad( guint keyval, gchar * key){ switch(c->state) { case CALL_STATE_DIALING: // Currently dialing => edit number - dbus_play_dtmf(key); + //dbus_play_dtmf(key); process_dialing(c, keyval, key); break; case CALL_STATE_CURRENT: @@ -496,7 +488,8 @@ sflphone_keypad( guint keyval, gchar * key){ case 65307: /* ESCAPE */ dbus_hang_up(c); break; - default: // TODO should this be here? + default: + // To play the dtmf when calling mail box for instance dbus_play_dtmf(key); if (keyval < 255 || (keyval >65453 && keyval < 65466)) { @@ -515,7 +508,7 @@ sflphone_keypad( guint keyval, gchar * key){ { case 65293: /* ENTER */ case 65421: /* ENTER numpad */ - status_bar_display_account(c); + //status_bar_display_account(c); dbus_accept(c); break; case 65307: /* ESCAPE */ @@ -569,7 +562,7 @@ sflphone_keypad( guint keyval, gchar * key){ } else { // Not in a call, not dialing, create a new call - dbus_play_dtmf(key); + //dbus_play_dtmf(key); switch (keyval) { case 65293: /* ENTER */ @@ -594,64 +587,59 @@ sflphone_keypad( guint keyval, gchar * key){ void sflphone_place_call ( call_t * c ) { - status_bar_display_account(c); - if(c->state == CALL_STATE_DIALING) + if(c->state == CALL_STATE_DIALING) + { + if( account_list_get_size() == 0 ) + notify_no_accounts(); + else if( account_list_get_by_state( ACCOUNT_STATE_REGISTERED ) == NULL ) + notify_no_registered_accounts(); + else + { + account_t * current = account_list_get_current(); + if( current ) + { + if(g_strcasecmp(g_hash_table_lookup( current->properties, "Status"),"REGISTERED")==0) + { + // OK, everything alright - the call is made with the current account + c -> accountID = current -> accountID; + status_bar_display_account(c); + dbus_place_call(c); + } + else { - account_t * account; - gchar * default_account = account_list_get_default(); - account = account_list_get_by_id(default_account); - - if(account) - { - if(strcmp(g_hash_table_lookup(account->properties, "Status"),"REGISTERED")==0) - { - c->accountID = default_account; - dbus_place_call(c); - } - else - { - main_window_error_message(_("The account selected as default is not registered.")); - } - - } - else{ - account = account_list_get_by_state (ACCOUNT_STATE_REGISTERED); - if(account) - { - c->accountID = account->accountID; - dbus_place_call(c); - } - else - { - main_window_error_message(_("There is no registered account to make this call with.")); - } - - } + // No current accounts have been setup. + // So we place a call with the first registered account + // And we change the current account + current = account_list_get_by_state( ACCOUNT_STATE_REGISTERED ); + c -> accountID = current -> accountID; + dbus_place_call(c); + notify_current_account( current ); + status_bar_display_account(c); + account_list_set_current_id( c-> accountID ); } + } + else + { + // No current accounts have been setup. + // So we place a call with the first registered account + // and we change the current account + current = account_list_get_by_state( ACCOUNT_STATE_REGISTERED ); + c -> accountID = current -> accountID; + dbus_place_call(c); + notify_current_account( current ); + status_bar_display_account(c); + account_list_set_current_id( c-> accountID ); + } + } + } } -/* Internal to action - set the DEFAULT_ACCOUNT variable */ +/* Internal to action - set the __CURRENT_ACCOUNT variable */ void -sflphone_set_default_account( ) +sflphone_set_current_account() { - gchar* default_id = strdup(dbus_get_default_account()); - account_list_set_default(default_id); -} - -void -sflphone_throw_exception( int errCode ) -{ - gchar* markup = malloc(1000); - switch( errCode ){ - case ALSA_ERROR_PLAYBACK_DEVICE: - sprintf( markup , _("<b>ALSA notification</b>\n\nError while opening playback device")); - break; - case ALSA_ERROR_CAPTURE_DEVICE: - sprintf( markup , _("<b>ALSA notification</b>\n\nError while opening capture device")); - break; - } - main_window_error_message( markup ); - free( markup ); + if( account_list_get_size() > 0 ) + account_list_set_current_pos( 0 ); } diff --git a/sflphone-gtk/src/actions.h b/sflphone-gtk/src/actions.h index f8ef7dfaf4124075fb4236de01bbb656f1440125..f364b639ae2d102299e7aec2997e572e8f8359aa 100644 --- a/sflphone-gtk/src/actions.h +++ b/sflphone-gtk/src/actions.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify @@ -21,20 +21,14 @@ #ifndef __ACTIONS_H__ #define __ACTIONS_H__ -#define _(STRING) gettext( STRING ) - #include <libintl.h> #include <locale.h> #include <calllist.h> #include <accountlist.h> #include <codeclist.h> - -#define __MSG_INCOMING_CALL 0 -#define __MSG_CALLING 1 -#define __MSG_VOICE_MAILS 2 -#define __MSG_ACCOUNT_DEFAULT 3 - +#include <sflphone_const.h> +#include <errors.h> /** @file actions.h * @brief General functions that change the state of the application. @@ -60,12 +54,40 @@ gboolean sflphone_quit ( ) ; */ void sflphone_hang_up (); +/** + * Put the selected call on hold + */ void sflphone_on_hold (); + +/** + * Put the selected call off hold + */ void sflphone_off_hold (); + +/** + * Open a new call + * @return call_t* A pointer on the call structure + */ call_t * sflphone_new_call(); -void sflphone_notify_voice_mail (guint count); + +/** + * Notify voice mails to the application + * @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 ); + +/** + * Prepare SFLphone to transfer a call and wait for the user to dial the number to transfer to + * Put the selected call in Transfer state + */ void sflphone_set_transfert(); + +/** + * Cancel the transfer and puts back the selected call to Current state + */ void sflphone_unset_transfert(); + /** * Accept / dial the current call */ @@ -73,38 +95,51 @@ void sflphone_pick_up (); /** * Put the call on hold state + * @param c The current call */ void sflphone_hold ( call_t * c); /** * Put the call in Ringing state + * @param c* The current call */ void sflphone_ringing(call_t * c ); +/** + * Put the call in Busy state + * @param c* The current call + */ void sflphone_busy( call_t * c ); + +/** + * Put the call in Failure state + * @param c* The current call + */ void sflphone_fail( call_t * c ); /** * Put the call in Current state + * @param c The current call */ void sflphone_current ( call_t * c); /** * The callee has hung up + * @param c The current call */ void sflphone_hung_up( call_t * c); /** * Incoming call + * @param c The incoming call */ void sflphone_incoming_call ( call_t * c); /** * Dial the number * If the call is in DIALING state, the char will be append to the number - * @TODO If the call is in CURRENT state, the char will be also sent to the server * @param keyval The unique int representing the key - * @param keyval The char value of the key + * @param key The char value of the key */ void sflphone_keypad ( guint keyval, gchar * key); @@ -114,9 +149,20 @@ void sflphone_keypad ( guint keyval, gchar * key); */ void sflphone_place_call ( call_t * c ); +/** + * Initialize the accounts data structure + */ void sflphone_fill_account_list(); -void sflphone_set_default_account(); -void sflphone_throw_exception( int errCode ); +/** + * 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 ) + */ +void sflphone_set_current_account(); + +/** + * Initialialize the codecs data structure + */ void sflphone_fill_codec_list(); + #endif diff --git a/sflphone-gtk/src/calllist.c b/sflphone-gtk/src/calllist.c index f3154dbfbb0467ecf82e11e6654171f7ebf9efca..74dfe8c98c835418ebaefdb337843138deb43bfd 100644 --- a/sflphone-gtk/src/calllist.c +++ b/sflphone-gtk/src/calllist.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/sflphone-gtk/src/calllist.h b/sflphone-gtk/src/calllist.h index 17367070431c3343bc6700289571b01a5a417025..9465b9376837af87ce6c0c043b6f2abeedab92ed 100644 --- a/sflphone-gtk/src/calllist.h +++ b/sflphone-gtk/src/calllist.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -88,7 +88,8 @@ void call_list_init (calltab_t* tab); void call_list_clean (calltab_t* tab); /** This function append a call to list. - * @param c The call you want to add */ + * @param c The call you want to add + * */ void call_list_add (calltab_t* tab, call_t * c); /** This function remove a call from list. @@ -121,9 +122,11 @@ call_t * call_list_get (calltab_t* tab, const gchar * callID ); * @return The full name of the caller or an empty string */ gchar * call_get_name ( const call_t * c); -/** This function parse the call_t.from field to return the number - * @param c The call - * @return The number of the caller */ +/** + * This function parse the call_t.from field to return the number + * @param c The call + * @return The number of the caller + */ gchar * call_get_number (const call_t * c); /** Mark a call as selected. There can be only one selected call. This call diff --git a/sflphone-gtk/src/calltree.c b/sflphone-gtk/src/calltree.c index e7bd6825dd0f02948f09af7ca4f6630ae9ef340f..e3c07c53a1acde3a99e77382b9c133166a47b885 100644 --- a/sflphone-gtk/src/calltree.c +++ b/sflphone-gtk/src/calltree.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify diff --git a/sflphone-gtk/src/calltree.h b/sflphone-gtk/src/calltree.h index 8abfdf619ca3f5ccbe2d31379cdc6ec0cf6bc0ec..c2bad5b661f1a0b75a8b993ee14375ec60975c17 100644 --- a/sflphone-gtk/src/calltree.h +++ b/sflphone-gtk/src/calltree.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -30,15 +30,38 @@ */ calltab_t* active_calltree; +/** + * Create a new widget calltree + * @return GtkWidget* A new widget + */ void create_call_tree(calltab_t* tab); +/** + * Update the toolbar's buttons state, according to the call state + */ void toolbar_update_buttons(); static void toggle_history(GtkToggleToolButton *toggle_tool_button, gpointer user_data); +/** + * Add a call in the calltree + * @param c The call to add + */ void update_call_tree_add (calltab_t* ct, call_t * c); +/** + * Update the call tree if the call state changes + * @param c The call to update + */ void update_call_tree (calltab_t* ct, call_t * c); +/** + * Remove a call from the call tree + * @param c The call to remove + */ void update_call_tree_remove (calltab_t* ct, call_t * c); +/** + * Build the toolbar + * @return GtkWidget* The toolbar + */ GtkWidget * create_toolbar(); #endif diff --git a/sflphone-gtk/src/codeclist.h b/sflphone-gtk/src/codeclist.h index ce5a806ac1676862da59547d07b67472ad066a4d..671060c68d2af585ace6570f45c0f5f98e3c7946 100644 --- a/sflphone-gtk/src/codeclist.h +++ b/sflphone-gtk/src/codeclist.h @@ -26,22 +26,72 @@ */ typedef struct { + /** Payload of the codec */ int _payload; + /** Tells if the codec has been activated */ gboolean is_active; + /** String description */ gchar * name; + /** Sample rate */ int sample_rate; + /** Bitrate */ gdouble _bitrate; + /** Bandwidth */ gdouble _bandwidth; }codec_t; +/** @struct codec_t + * @brief Codec information. + * This struct holds information about a codec. + * This match how the server internally works and the dbus API to save and retrieve the codecs details. + */ + +/** + * This function initialize the codec list. + */ void codec_list_init(); + +/** + * This function empty and free the codec list. + */ void codec_list_clear(); + +/** + * This function append an codec to list. + * @param c The codec you want to add + */ void codec_list_add(codec_t * c); + +/** + * Set a codec active. An active codec will be used for codec negociation + * @param name The string description of the codec + */ void codec_set_active(gchar* name); + +/** + * Set a codec inactive. An active codec won't be used for codec negociation + * @param name The string description of the codec + */ void codec_set_inactive(gchar* name); + +/** + * Return the number of codecs in the list + * @return guint The number of codecs in the list + */ guint codec_list_get_size(); + +/** + * Return the codec structure that corresponds to the string description + * @param name The string description of the codec + * @return codec_t* A codec or NULL + */ codec_t * codec_list_get(const gchar * name); -//codec_t * codec_list_get(const int payload); + +/** + * Return the codec at the nth position in the list + * @param index The position of the codec you want + * @return codec_t* A codec or NULL + */ codec_t* codec_list_get_nth(guint index); /** @@ -49,11 +99,22 @@ codec_t* codec_list_get_nth(guint index); * @param index The position in the list of the prefered codec */ void codec_set_prefered_order(guint index); -//gchar * codec_get_name(codec_t * c); -//guint codec_get_rate(gchar * codec_name); +/** + * Move the codec from an unit up in the codec_list + * @param index The current index in the list + */ void codec_list_move_codec_up(guint index); + +/** + * Move the codec from an unit down in the codec_list + * @param index The current index in the list + */ void codec_list_move_codec_down(guint index); + +/** + * Notify modifications on codecs to the server + */ void codec_list_update_to_daemon(); #endif diff --git a/sflphone-gtk/src/configurationmanager-glue.h b/sflphone-gtk/src/configurationmanager-glue.h index 565dec6f1fca13b700af10b28194e72148ad4c86..334ce53aca4c18d55b3fc1822ec28e143dfc9d63 100644 --- a/sflphone-gtk/src/configurationmanager-glue.h +++ b/sflphone-gtk/src/configurationmanager-glue.h @@ -276,6 +276,43 @@ static inline #endif gboolean +org_sflphone_SFLphone_ConfigurationManager_send_register (DBusGProxy *proxy, const char * IN_accountID, const gint IN_expire, GError **error) + +{ + return dbus_g_proxy_call (proxy, "sendRegister", error, G_TYPE_STRING, IN_accountID, G_TYPE_INT, IN_expire, G_TYPE_INVALID, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_send_register_reply) (DBusGProxy *proxy, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_send_register_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_send_register_reply)data->cb) (proxy, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_send_register_async (DBusGProxy *proxy, const char * IN_accountID, const gint IN_expire, org_sflphone_SFLphone_ConfigurationManager_send_register_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "sendRegister", org_sflphone_SFLphone_ConfigurationManager_send_register_async_callback, stuff, g_free, G_TYPE_STRING, IN_accountID, G_TYPE_INT, IN_expire, G_TYPE_INVALID); +} +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean org_sflphone_SFLphone_ConfigurationManager_get_tone_locale_list (DBusGProxy *proxy, char *** OUT_list, GError **error) { @@ -1214,6 +1251,231 @@ org_sflphone_SFLphone_ConfigurationManager_is_iax2_enabled_async (DBusGProxy *pr stuff->userdata = userdata; return dbus_g_proxy_begin_call (proxy, "isIax2Enabled", org_sflphone_SFLphone_ConfigurationManager_is_iax2_enabled_async_callback, stuff, g_free, G_TYPE_INVALID); } +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean +org_sflphone_SFLphone_ConfigurationManager_get_dialpad (DBusGProxy *proxy, gint* OUT_state, GError **error) + +{ + return dbus_g_proxy_call (proxy, "getDialpad", error, G_TYPE_INVALID, G_TYPE_INT, OUT_state, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_get_dialpad_reply) (DBusGProxy *proxy, gint OUT_state, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_get_dialpad_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + gint OUT_state; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INT, &OUT_state, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_get_dialpad_reply)data->cb) (proxy, OUT_state, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_get_dialpad_async (DBusGProxy *proxy, org_sflphone_SFLphone_ConfigurationManager_get_dialpad_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "getDialpad", org_sflphone_SFLphone_ConfigurationManager_get_dialpad_async_callback, stuff, g_free, G_TYPE_INVALID); +} +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean +org_sflphone_SFLphone_ConfigurationManager_set_dialpad (DBusGProxy *proxy, GError **error) + +{ + return dbus_g_proxy_call (proxy, "setDialpad", error, G_TYPE_INVALID, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_set_dialpad_reply) (DBusGProxy *proxy, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_set_dialpad_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_set_dialpad_reply)data->cb) (proxy, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_set_dialpad_async (DBusGProxy *proxy, org_sflphone_SFLphone_ConfigurationManager_set_dialpad_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "setDialpad", org_sflphone_SFLphone_ConfigurationManager_set_dialpad_async_callback, stuff, g_free, G_TYPE_INVALID); +} +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean +org_sflphone_SFLphone_ConfigurationManager_start_hidden (DBusGProxy *proxy, GError **error) + +{ + return dbus_g_proxy_call (proxy, "startHidden", error, G_TYPE_INVALID, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_start_hidden_reply) (DBusGProxy *proxy, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_start_hidden_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_start_hidden_reply)data->cb) (proxy, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_start_hidden_async (DBusGProxy *proxy, org_sflphone_SFLphone_ConfigurationManager_start_hidden_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "startHidden", org_sflphone_SFLphone_ConfigurationManager_start_hidden_async_callback, stuff, g_free, G_TYPE_INVALID); +} +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean +org_sflphone_SFLphone_ConfigurationManager_is_start_hidden (DBusGProxy *proxy, gint* OUT_state, GError **error) + +{ + return dbus_g_proxy_call (proxy, "isStartHidden", error, G_TYPE_INVALID, G_TYPE_INT, OUT_state, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_is_start_hidden_reply) (DBusGProxy *proxy, gint OUT_state, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_is_start_hidden_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + gint OUT_state; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INT, &OUT_state, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_is_start_hidden_reply)data->cb) (proxy, OUT_state, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_is_start_hidden_async (DBusGProxy *proxy, org_sflphone_SFLphone_ConfigurationManager_is_start_hidden_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "isStartHidden", org_sflphone_SFLphone_ConfigurationManager_is_start_hidden_async_callback, stuff, g_free, G_TYPE_INVALID); +} +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean +org_sflphone_SFLphone_ConfigurationManager_popup_mode (DBusGProxy *proxy, gint* OUT_state, GError **error) + +{ + return dbus_g_proxy_call (proxy, "popupMode", error, G_TYPE_INVALID, G_TYPE_INT, OUT_state, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_popup_mode_reply) (DBusGProxy *proxy, gint OUT_state, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_popup_mode_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + gint OUT_state; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INT, &OUT_state, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_popup_mode_reply)data->cb) (proxy, OUT_state, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_popup_mode_async (DBusGProxy *proxy, org_sflphone_SFLphone_ConfigurationManager_popup_mode_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "popupMode", org_sflphone_SFLphone_ConfigurationManager_popup_mode_async_callback, stuff, g_free, G_TYPE_INVALID); +} +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean +org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode (DBusGProxy *proxy, GError **error) + +{ + return dbus_g_proxy_call (proxy, "switchPopupMode", error, G_TYPE_INVALID, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode_reply) (DBusGProxy *proxy, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode_reply)data->cb) (proxy, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode_async (DBusGProxy *proxy, org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "switchPopupMode", org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode_async_callback, stuff, g_free, G_TYPE_INVALID); +} #endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_org_sflphone_SFLphone_ConfigurationManager */ G_END_DECLS diff --git a/sflphone-gtk/src/configwindow.c b/sflphone-gtk/src/configwindow.c index 0929f04314afd116a8a72263522eae67a169a9e1..d43ec5b6e5330fb2beb57f769b38668cb963c225 100644 --- a/sflphone-gtk/src/configwindow.c +++ b/sflphone-gtk/src/configwindow.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@savoirfairelinux.com> * @@ -48,18 +48,32 @@ GtkListStore *inputAudioDeviceManagerStore; GtkWidget *addButton; GtkWidget *editButton; GtkWidget *deleteButton; -GtkWidget *defaultButton; +//GtkWidget *defaultButton; GtkWidget *restoreButton; +GtkWidget *accountMoveDownButton; +GtkWidget *accountMoveUpButton; GtkWidget *outputDeviceComboBox; GtkWidget *inputDeviceComboBox; GtkWidget *pluginComboBox; -GtkWidget *moveUpButton; -GtkWidget *moveDownButton; +GtkWidget *codecMoveUpButton; +GtkWidget *codecMoveDownButton; + +GtkWidget* status; account_t *selectedAccount; +// Account properties +enum { + COLUMN_ACCOUNT_ALIAS, + COLUMN_ACCOUNT_TYPE, + COLUMN_ACCOUNT_STATUS, + COLUMN_ACCOUNT_ACTIVE, + COLUMN_ACCOUNT_DATA, + COLUMN_ACCOUNT_COUNT +}; + // Codec properties ID enum { COLUMN_CODEC_ACTIVE, @@ -87,25 +101,26 @@ config_window_fill_account_list() account_t * a = account_list_get_nth (i); if (a) { + g_print("fill account list : %s\n" , (gchar*)g_hash_table_lookup(a->properties, ACCOUNT_ENABLED)); gtk_list_store_append (accountStore, &iter); gtk_list_store_set(accountStore, &iter, - 0, g_hash_table_lookup(a->properties, ACCOUNT_ALIAS), // Name - 1, g_hash_table_lookup(a->properties, ACCOUNT_TYPE), // Protocol - 2, account_state_name(a->state), // Status - 3, a, // Pointer + 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); } } gtk_widget_set_sensitive( GTK_WIDGET(editButton), FALSE); gtk_widget_set_sensitive( GTK_WIDGET(deleteButton), FALSE); - gtk_widget_set_sensitive( GTK_WIDGET(defaultButton), FALSE); } } /** * Fills the tree list with supported codecs - */ +*/ void config_window_fill_codec_list() { @@ -356,7 +371,6 @@ select_active_output_audio_plugin() { GtkTreeModel* model; GtkTreeIter iter; - gchar** devices; gchar* plugin; gchar* tmp; @@ -479,25 +493,22 @@ add_account(GtkWidget *widget, gpointer data) show_account_window(NULL); } -/* - * Should mark the account as default - */ +int +is_ringtone_enabled( void ) +{ + return dbus_is_ringtone_enabled(); +} + void -default_account(GtkWidget *widget, gpointer data) +start_hidden( void ) { - // set account as default - if(selectedAccount) - { - account_list_set_default(selectedAccount->accountID); - dbus_set_default_account(selectedAccount->accountID); - } + dbus_start_hidden(); } -int -is_ringtone_enabled( void ) +void +set_popup_mode( void ) { - int res = dbus_is_ringtone_enabled(); - return res; + dbus_switch_popup_mode(); } void @@ -531,11 +542,13 @@ select_account(GtkTreeSelection *selection, GtkTreeModel *model) 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); return; } val.g_type = G_TYPE_POINTER; - gtk_tree_model_get_value(model, &iter, 3, &val); + gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_DATA, &val); selectedAccount = (account_t*)g_value_get_pointer(&val); g_value_unset(&val); @@ -544,7 +557,8 @@ select_account(GtkTreeSelection *selection, GtkTreeModel *model) { gtk_widget_set_sensitive(GTK_WIDGET(editButton), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(defaultButton), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), TRUE); } g_print("select"); } @@ -559,13 +573,13 @@ select_codec(GtkTreeSelection *selection, GtkTreeModel *model) if(!gtk_tree_selection_get_selected(selection, &model, &iter)) { - gtk_widget_set_sensitive(GTK_WIDGET(moveUpButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(moveDownButton), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(codecMoveUpButton), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(codecMoveDownButton), FALSE); } else { - gtk_widget_set_sensitive(GTK_WIDGET(moveUpButton), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(moveDownButton), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(codecMoveUpButton), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(codecMoveDownButton), TRUE); } } @@ -615,9 +629,42 @@ codec_active_toggled(GtkCellRendererToggle *renderer, gchar *path, gpointer data codec_list_update_to_daemon(); } +static void +enable_account(GtkCellRendererToggle *rend , gchar* path, gpointer data ) +{ + GtkTreeIter iter; + GtkTreePath *treePath; + GtkTreeModel *model; + gboolean enable; + account_t* acc ; + + // Get path of clicked codec active toggle box + 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); + + // Get pointer on object + gtk_tree_model_get(model, &iter, + COLUMN_ACCOUNT_ACTIVE, &enable, + COLUMN_ACCOUNT_DATA, &acc, + -1); + enable = !enable; + + // Store value + gtk_list_store_set(GTK_LIST_STORE(model), &iter, + COLUMN_ACCOUNT_ACTIVE, enable, + -1); + + gtk_tree_path_free(treePath); + + // Modify account state + g_hash_table_replace( acc->properties , g_strdup(ACCOUNT_ENABLED) , g_strdup((enable == 1)? "TRUE":"FALSE")); + dbus_send_register( acc->accountID , enable ); +} + /** * Move codec in list depending on direction and selected codec and - * update changes in the deamon list and the configuration files + * update changes in the daemon list and the configuration files */ static void codec_move(gboolean moveUp, gpointer data) @@ -674,14 +721,69 @@ codec_move(gboolean moveUp, gpointer data) codec_list_update_to_daemon(); } +/** + * Move account in list depending on direction and selected account + */ +static void +account_move(gboolean moveUp, 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)); + + // Find selected iteration and create a copy + gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter); + iter2 = gtk_tree_iter_copy(&iter); + + // Find path of iteration + path = gtk_tree_model_get_string_from_iter(GTK_TREE_MODEL(model), &iter); + treePath = gtk_tree_path_new_from_string(path); + gint *indices = gtk_tree_path_get_indices(treePath); + gint indice = indices[0]; + + // Depending on button direction get new path + if(moveUp) + gtk_tree_path_prev(treePath); + else + gtk_tree_path_next(treePath); + gtk_tree_model_get_iter(model, &iter, treePath); + + // 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); + + // Scroll to new position + gtk_tree_view_scroll_to_cell(treeView, treePath, NULL, FALSE, 0, 0); + + // Free resources + gtk_tree_path_free(treePath); + gtk_tree_iter_free(iter2); + g_free(path); + + // Perpetuate changes in account queue + if(moveUp) + account_list_move_up(indice); + else + account_list_move_down(indice); +} + /** * Called from move up codec button signal */ static void codec_move_up(GtkButton *button, gpointer data) { - // Change tree view ordering and get indice changed - codec_move(TRUE, data); + // Change tree view ordering and get indice changed + codec_move(TRUE, data); } /** @@ -690,28 +792,28 @@ codec_move_up(GtkButton *button, gpointer data) static void codec_move_down(GtkButton *button, gpointer data) { - // Change tree view ordering and get indice changed - codec_move(FALSE, data); + // Change tree view ordering and get indice changed + codec_move(FALSE, data); } /** - * Select default account that is rendered in bold + * Called from move up account button signal */ -void -bold_if_default_account(GtkTreeViewColumn *col, - GtkCellRenderer *rend, - GtkTreeModel *tree_model, - GtkTreeIter *iter, - gpointer data) +static void +account_move_up(GtkButton *button, gpointer data) { - GValue val = { 0, }; - gtk_tree_model_get_value(tree_model, iter, 3, &val); - account_t *current = (account_t*)g_value_get_pointer(&val); - g_value_unset(&val); - if(g_strcasecmp(current->accountID, account_list_get_default()) == 0) - g_object_set(G_OBJECT(rend), "weight", 800, NULL); - else - g_object_set(G_OBJECT(rend), "weight", 400, NULL); + // Change tree view ordering and get indice changed + account_move(TRUE, data); +} + +/** + * Called from move down account button signal + */ +static void +account_move_down(GtkButton *button, gpointer data) +{ + // Change tree view ordering and get indice changed + account_move(FALSE, data); } GtkWidget* @@ -787,15 +889,15 @@ create_codec_table() gtk_container_set_border_width(GTK_CONTAINER(buttonBox), 10); gtk_box_pack_start(GTK_BOX(ret), buttonBox, FALSE, FALSE, 0); - moveUpButton = gtk_button_new_from_stock(GTK_STOCK_GO_UP); - gtk_widget_set_sensitive(GTK_WIDGET(moveUpButton), FALSE); - gtk_box_pack_start(GTK_BOX(buttonBox), moveUpButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(moveUpButton), "clicked", G_CALLBACK(codec_move_up), codecTreeView); + 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), codecTreeView); - moveDownButton = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); - gtk_widget_set_sensitive(GTK_WIDGET(moveDownButton), FALSE); - gtk_box_pack_start(GTK_BOX(buttonBox), moveDownButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(moveDownButton), "clicked", G_CALLBACK(codec_move_down), codecTreeView); + 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), codecTreeView); config_window_fill_codec_list(); @@ -826,10 +928,11 @@ create_accounts_tab() gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_SHADOW_IN); gtk_box_pack_start(GTK_BOX(ret), scrolledWindow, TRUE, TRUE, 0); - accountStore = gtk_list_store_new(4, + 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 ); @@ -839,16 +942,12 @@ create_accounts_tab() G_CALLBACK (select_account), accountStore); - gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(accountStore), - 2, GTK_SORT_ASCENDING); - renderer = gtk_cell_renderer_text_new(); treeViewColumn = gtk_tree_view_column_new_with_attributes ("Alias", renderer, - "markup", 0, + "markup", COLUMN_ACCOUNT_ALIAS, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(treeView), treeViewColumn); - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, bold_if_default_account, NULL,NULL); // 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 ) , NULL ); @@ -856,25 +955,44 @@ create_accounts_tab() renderer = gtk_cell_renderer_text_new(); treeViewColumn = gtk_tree_view_column_new_with_attributes (_("Protocol"), renderer, - "markup", 1, + "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, bold_if_default_account, NULL,NULL); renderer = gtk_cell_renderer_text_new(); treeViewColumn = gtk_tree_view_column_new_with_attributes (_("Status"), renderer, - "markup", 2, + "markup", COLUMN_ACCOUNT_STATUS, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(treeView), treeViewColumn); - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, bold_if_default_account, NULL,NULL); + + renderer = gtk_cell_renderer_toggle_new(); + treeViewColumn = gtk_tree_view_column_new_with_attributes("", 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), (gpointer)treeView ); + g_object_unref(G_OBJECT(accountStore)); gtk_container_add(GTK_CONTAINER(scrolledWindow), treeView); + // Create button box + buttonBox = gtk_vbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(buttonBox), 10); + gtk_box_pack_start(GTK_BOX(ret), buttonBox, FALSE, FALSE, 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), 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), treeView); + /* The buttons to press! */ buttonBox = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(buttonBox), 10); //GAIM_HIG_BOX_SPACE - gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_START); + gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_CENTER); gtk_box_pack_start(GTK_BOX(ret), buttonBox, FALSE, FALSE, 0); gtk_widget_show (buttonBox); @@ -896,13 +1014,6 @@ create_accounts_tab() gtk_box_pack_start(GTK_BOX(buttonBox), deleteButton, FALSE, FALSE, 0); gtk_widget_show(deleteButton); - defaultButton = gtk_button_new_with_mnemonic(_("Default")); - gtk_widget_set_tooltip_text( GTK_WIDGET( defaultButton ) , _("Set the selected account as the default one to make calls")); - g_signal_connect_swapped(G_OBJECT(defaultButton), "clicked", - G_CALLBACK(default_account), NULL); - gtk_box_pack_start(GTK_BOX(buttonBox), defaultButton, FALSE, FALSE, 0); - gtk_widget_show(defaultButton); - gtk_widget_show_all(ret); config_window_fill_account_list(); @@ -927,7 +1038,6 @@ create_audio_tab () GtkWidget *fileChooser; GtkWidget *titleLabel; - GtkWidget *comboBox; GtkWidget *refreshButton; GtkCellRenderer *renderer; @@ -1071,9 +1181,9 @@ create_audio_tab () GtkWidget* box = gtk_hbox_new( TRUE , 1); gtk_box_pack_start( GTK_BOX(ret) , box , FALSE , FALSE , 1); enableTone = gtk_check_button_new_with_mnemonic( _("_Enable ringtones")); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(enableTone), dbus_is_ringtone_enabled() ); - gtk_box_pack_start( GTK_BOX(box) , enableTone , TRUE , TRUE , 1); - g_signal_connect(G_OBJECT( enableTone) , "clicked" , G_CALLBACK( ringtone_enabled ) , NULL); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(enableTone), dbus_is_ringtone_enabled() ); + gtk_box_pack_start( GTK_BOX(box) , enableTone , TRUE , TRUE , 1); + g_signal_connect(G_OBJECT( enableTone) , "clicked" , G_CALLBACK( ringtone_enabled ) , NULL); // file chooser button fileChooser = gtk_file_chooser_button_new(_("Choose a ringtone"), GTK_FILE_CHOOSER_ACTION_OPEN); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER( fileChooser) , g_get_home_dir()); @@ -1093,6 +1203,79 @@ create_audio_tab () return ret; } +GtkWidget* +create_general_settings () +{ + GtkWidget *ret; + + GtkWidget *notifFrame; + GtkWidget *notifBox; + GtkWidget *notifAll; + GtkWidget *notifIncoming; + GtkWidget *notifMails; + + GtkWidget *trayFrame; + GtkWidget *trayBox; + GtkWidget *trayItem; + + // Main widget + ret = gtk_vbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(ret), 10); + + // Notifications Frame + notifFrame = gtk_frame_new(_("Notifications")); + gtk_box_pack_start(GTK_BOX(ret), notifFrame, FALSE, FALSE, 0); + gtk_widget_show( notifFrame ); + + notifBox = gtk_vbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(notifFrame), notifBox, FALSE, FALSE, 0); + gtk_widget_show( notifBox ); + gtk_container_add( GTK_CONTAINER(notifFrame) , notifBox); + + notifAll = gtk_radio_button_new_with_label( NULL, _("Enable All")); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(notifAll), TRUE ); + gtk_box_pack_start( GTK_BOX(notifBox) , notifAll , TRUE , TRUE , 1); + //TODO callback + + notifIncoming = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(notifAll) , _("Only Incoming Calls")); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(notifIncoming), FALSE ); + gtk_box_pack_start( GTK_BOX(notifBox) , notifIncoming , TRUE , TRUE , 1); + //TODO callback + + notifMails = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(notifAll) , _("Only Voice Mails")); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(notifMails), FALSE ); + gtk_box_pack_start( GTK_BOX(notifBox) , notifMails , TRUE , TRUE , 1); + //TODO callback + + // System Tray option frame + trayFrame = gtk_frame_new(_("System Tray Icon")); + gtk_box_pack_start(GTK_BOX(ret), trayFrame, FALSE, FALSE, 0); + gtk_widget_show( trayFrame ); + + trayBox = gtk_vbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(trayFrame), trayBox, FALSE, FALSE, 0); + gtk_widget_show( trayBox ); + gtk_container_add( GTK_CONTAINER(trayFrame) , trayBox); + + GtkWidget* trayItem1 = gtk_radio_button_new_with_label(NULL, _("Popup Main Window On Incoming Call")); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(trayItem1), dbus_popup_mode() ); + gtk_box_pack_start( GTK_BOX(trayBox) , trayItem1 , TRUE , TRUE , 1); + g_signal_connect(G_OBJECT( trayItem1 ) , "clicked" , G_CALLBACK( set_popup_mode ) , NULL); + + trayItem = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(trayItem1), _("Never Popup Main Window")); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(trayItem), !dbus_popup_mode() ); + gtk_box_pack_start( GTK_BOX(trayBox) , trayItem , TRUE , TRUE , 1); + + trayItem = gtk_check_button_new_with_label(_("Start Hidden")); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(trayItem), dbus_is_start_hidden() ); + gtk_box_pack_start( GTK_BOX(trayBox) , trayItem , TRUE , TRUE , 1); + g_signal_connect(G_OBJECT( trayItem ) , "clicked" , G_CALLBACK( start_hidden ) , NULL); + + gtk_widget_show_all(ret); + return ret; +} + + /** * Show configuration window with tabs */ @@ -1123,10 +1306,10 @@ show_config_window () gtk_container_set_border_width(GTK_CONTAINER(notebook), 10); gtk_widget_show(notebook); - // Accounts tab - //tab = create_accounts_tab(); - //gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tab, gtk_label_new(_("Accounts"))); - //gtk_notebook_page_num(GTK_NOTEBOOK(notebook), tab); + // General settings tab + tab = create_general_settings(); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tab, gtk_label_new(_("General Settings"))); + gtk_notebook_page_num(GTK_NOTEBOOK(notebook), tab); // Audio tab tab = create_audio_tab(); @@ -1170,7 +1353,8 @@ show_accounts_window( void ) gtk_box_pack_start( GTK_BOX( dialog->vbox ), accountFrame , TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(accountFrame), 10); gtk_widget_show(accountFrame); - // Accounts tab + + // Accounts tab tab = create_accounts_tab(); gtk_container_add(GTK_CONTAINER(accountFrame) , tab); @@ -1179,3 +1363,4 @@ show_accounts_window( void ) dialogOpen=FALSE; gtk_widget_destroy(GTK_WIDGET(dialog)); } + diff --git a/sflphone-gtk/src/configwindow.h b/sflphone-gtk/src/configwindow.h index 778ed81d962ceb7232801730b7cdcc2ae9666be0..a954d77ffe4a55e2d9662a884f3048ff1a5ee11c 100644 --- a/sflphone-gtk/src/configwindow.h +++ b/sflphone-gtk/src/configwindow.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -26,23 +26,87 @@ * @file configwindow.h * @brief The Preferences window. */ + +/** + * Fill the account list widget with the data the server send + */ void config_window_fill_account_list(); + +/** + * Fill the codec list widget with the data the server send + */ void config_window_fill_codec_list(); + +/** + * Fill the input audio plugin list widget with the data the server send + * Currently not used + */ void config_window_fill_input_audio_plugin_list(); + +/** + * Fill the output audio plugin list widget with the data the server send + */ void config_window_fill_output_audio_plugin_list(); + +/** + * Fill the output audio device list widget with the data the server send + */ void config_window_fill_output_audio_device_list(); + +/** + * Select an output audio device + */ void select_active_output_audio_device(); + +/** + * Fill the input audio device list widget with the data the server send + */ void config_window_fill_input_audio_device_list(); + +/** + * Select an input audio device + */ void select_active_input_audio_device(); + +/** + * Select an output audio plugin + */ void select_active_output_audio_plugin(); + +/** + * Update the combo box state. + * If the default plugin has been selected, the audio devices have to been unsensitive + * because the default plugin always use default audio device + * @param plugin The description of the selected plugin + */ void update_combo_box( gchar* plugin ); -void default_account(GtkWidget *widget, gpointer data); -void bold_if_default_account(GtkTreeViewColumn *col, GtkCellRenderer *rend, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data); -void default_codecs(GtkWidget* widget, gpointer data); + +/** + * Build the widget to display codec list + * @return GtkWidget* The widget created + */ GtkWidget * create_codec_table(); + +/** + * Create the main account window in a new window + * @return GtkWidget* The widget created + */ GtkWidget * create_accounts_tab(); + +/** + * Create the audio configuration tab and add it to the main configuration window + * @return GtkWidget* The widget created + */ GtkWidget * create_audio_tab(); + +/** + * Display the main configuration window + */ void show_config_window(); + +/** + * Display the main account window + */ void show_accounts_window(); #endif diff --git a/sflphone-gtk/src/dbus.c b/sflphone-gtk/src/dbus.c index 50bda6455a9e73296ce501bfbd44c4d0d8a5da7b..eaac7692394fad55c00523ffb9a7297765694e8f 100644 --- a/sflphone-gtk/src/dbus.c +++ b/sflphone-gtk/src/dbus.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@savoirfairelinux.com> * @@ -74,11 +74,11 @@ volume_changed_cb (DBusGProxy *proxy, static void voice_mail_cb (DBusGProxy *proxy, const gchar* accountID, - const gint nb, + const guint nb, void * foo ) { g_print ("%d Voice mail waiting! \n",nb); - sflphone_notify_voice_mail (nb); + sflphone_notify_voice_mail (accountID , nb); } static void @@ -87,7 +87,7 @@ incoming_message_cb (DBusGProxy *proxy, const gchar* msg, void * foo ) { - g_print ("Messge %s! \n",msg); + g_print ("Message %s! \n",msg); } @@ -273,6 +273,7 @@ dbus_clean () g_object_unref (configurationManagerProxy); } + void dbus_hold (const call_t * c) { @@ -367,8 +368,6 @@ dbus_accept (const call_t * c) void dbus_refuse (const call_t * c) { - // Remove the account message from the status bar stack - status_bar_message_remove( __MSG_ACCOUNT_DEFAULT ); status_tray_icon_blink( FALSE ); GError *error = NULL; org_sflphone_SFLphone_CallManager_refuse ( callManagerProxy, c->callID, &error); @@ -457,49 +456,23 @@ dbus_account_details(gchar * accountID) return details; } -gchar * -dbus_get_default_account( ) -{ - GError *error = NULL; - char * accountID; - org_sflphone_SFLphone_ConfigurationManager_get_default_account ( - configurationManagerProxy, - &accountID, - &error); - if (error) - { - g_printerr("Failed to call get_default_account() on ConfigurationManager: %s\n",error->message); - g_error_free (error); - } - else - { - g_print ("DBus called get_default_account() on ConfigurationManager\n"); - } - - return accountID; - -} - - void -dbus_set_default_account(gchar * accountID) +dbus_send_register ( gchar* accountID , int expire) { - GError *error = NULL; - org_sflphone_SFLphone_ConfigurationManager_set_default_account ( - configurationManagerProxy, - accountID, - &error); - if (error) - { - g_printerr("Failed to call set_default_account() on ConfigurationManager: %s\n",error->message); - g_error_free (error); - } - else - { - g_print ("DBus called set_default_account() on ConfigurationManager\n"); - } - + GError *error = NULL; + org_sflphone_SFLphone_ConfigurationManager_send_register ( configurationManagerProxy, accountID, expire ,&error); + if (error) + { + g_printerr ("Failed to call send_register() on ConfigurationManager: %s\n", + error->message); + g_error_free (error); + } + else + { + g_print ("DBus called send_register() on ConfigurationManager\n"); + } } + void dbus_remove_account(gchar * accountID) { @@ -708,30 +681,6 @@ dbus_unregister(int pid) } } -int -dbus_get_registration_count( void ) -{ - GError *error = NULL; - int n; - - org_sflphone_SFLphone_Instance_get_registration_count( - instanceProxy, - &n, - &error); - - if (error) - { - g_printerr ("Failed to call get_registration_count() on instanceProxy: %s\n", - error->message); - g_error_free (error); - } - else - { - g_print ("DBus called get_registration_count() on instanceProxy\n"); - } - return n; -} - gchar** dbus_codec_list() { @@ -889,9 +838,6 @@ dbus_get_output_audio_plugin_list() return array; } -/** - * Sets the input audio plugin from its name - */ void dbus_set_input_audio_plugin(gchar* audioPlugin) { @@ -911,9 +857,6 @@ dbus_set_input_audio_plugin(gchar* audioPlugin) g_print("DBus called set_input_audio_plugin() on ConfigurationManager\n"); } -/** - * Sets the output audio plugin from its name - */ void dbus_set_output_audio_plugin(gchar* audioPlugin) { @@ -1187,3 +1130,106 @@ dbus_is_iax2_enabled() g_print("DBus called is_iax2_enabled() on ConfigurationManager\n"); return res; } + +int +dbus_get_dialpad() +{ + int state; + GError* error = NULL; + org_sflphone_SFLphone_ConfigurationManager_get_dialpad( + configurationManagerProxy, + &state, + &error); + g_print("After"); + if(error) + { + g_error_free(error); + } + else + g_print("DBus called get_dialpad on ConfigurationManager\n"); + return state; +} + +void +dbus_set_dialpad( ) +{ + GError* error = NULL; + org_sflphone_SFLphone_ConfigurationManager_set_dialpad( + configurationManagerProxy, + &error); + g_print("After"); + if(error) + { + g_error_free(error); + } + else + g_print("DBus called set_dialpad on ConfigurationManager\n"); +} + +void +dbus_start_hidden( void ) +{ + GError* error = NULL; + org_sflphone_SFLphone_ConfigurationManager_start_hidden( + configurationManagerProxy, + &error); + g_print("After"); + if(error) + { + g_error_free(error); + } + else + g_print("DBus called start_hidden on ConfigurationManager\n"); +} + + +int +dbus_is_start_hidden( void ) +{ + GError* error = NULL; + int state; + org_sflphone_SFLphone_ConfigurationManager_is_start_hidden( + configurationManagerProxy, + &state, + &error); + g_print("After"); + if(error) + { + g_error_free(error); + } + else + g_print("DBus called start_hidden on ConfigurationManager\n"); + return state; +} + +int +dbus_popup_mode( void ) +{ + GError* error = NULL; + int state; + org_sflphone_SFLphone_ConfigurationManager_popup_mode( + configurationManagerProxy, + &state, + &error); + g_print("After"); + if(error) + { + g_error_free(error); + } + else + g_print("DBus called popup_mode on ConfigurationManager\n"); + return state; +} + +void +dbus_switch_popup_mode( void ) +{ + GError* error = NULL; + org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode( + configurationManagerProxy, + &error); + if(error) + { + g_error_free(error); + } +} diff --git a/sflphone-gtk/src/dbus.h b/sflphone-gtk/src/dbus.h index 291c20cce2828633e14d082d41fe09f00409e329..0b6ae4bd006ab719912b03876571f5da311777be 100644 --- a/sflphone-gtk/src/dbus.h +++ b/sflphone-gtk/src/dbus.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@savoirfairelinux.com> * @@ -25,66 +25,320 @@ #include <accountlist.h> #include <calllist.h> -#include <SFLnotify.h> +#include <sflnotify.h> /** @file dbus.h * @brief General DBus functions wrappers. */ -/** @return TRUE if connection succeeded, FALSE otherwise */ + +/** + * Try to connect to DBus services + * @return TRUE if connection succeeded, FALSE otherwise + */ gboolean dbus_connect (); + +/** + * Unreferences the proxies + */ void dbus_clean (); -/* CallManager */ +/** + * CallManager - Hold a call + * @param c The call to hold + */ void dbus_hold (const call_t * c ); + +/** + * CallManager - Unhold a call + * @param c The call to unhold + */ void dbus_unhold (const call_t * c ); + +/** + * CallManager - Hang up a call + * @param c The call to hang up + */ void dbus_hang_up (const call_t * c ); + +/** + * CallManager - Transfer a call + * @param c The call to transfer + */ void dbus_transfert (const call_t * c); + +/** + * CallManager - Accept a call + * @param c The call to accept + */ void dbus_accept (const call_t * c); + +/** + * CallManager - Refuse a call + * @param c The call to refuse + */ void dbus_refuse (const call_t * c); + +/** + * CallManager - Place a call + * @param c The call to place + */ void dbus_place_call (const call_t * c); -/* ConfigurationManager */ -/** Returns a NULL terminated array of gchar pointers */ + +/** + * ConfigurationManager - Get the list of the setup accounts + * @return gchar** The list of accounts + */ gchar ** dbus_account_list(); + +/** + * ConfigurationManager - Get the details of a specific account + * @param accountID The unique of the account + * @return GHashTable* The details of the account + */ GHashTable * dbus_account_details(gchar * accountID); + +/** + * ConfigurationManager - Set the details of a specific account + * @param a The account to update + */ void dbus_set_account_details(account_t *a); + +/** + * ConfigurationManager - Send registration request + * @param accountID The account to register/unregister + * @param expire The flag for the type of registration + * 0 for unregistration request + * 1 for registration request + */ +void dbus_send_register( gchar* accountID , int expire ); + +/** + * ConfigurationManager - Add an account to the list + * @param a The account to add + */ void dbus_add_account(account_t *a); + +/** + * ConfigurationManager - Remove an account from the list + * @param accountID The account to remove + */ void dbus_remove_account(gchar * accountID); + +/** + * ConfigurationManager - Set volume for speaker/mic + * @param device The speaker or the mic + * @param value The new value + */ void dbus_set_volume(const gchar * device, gdouble value); + +/** + * ConfigurationManager - Get the volume of a device + * @param device The speaker or the mic + */ gdouble dbus_get_volume(const gchar * device); + +/** + * ConfigurationManager - Play DTMF + * @param key The DTMF to send + */ void dbus_play_dtmf(const gchar * key); -gchar* dbus_get_default_account(); -void dbus_set_default_account(gchar * accountID); + +/** + * ConfigurationManager - Get the codecs list + * @return gchar** The list of codecs + */ gchar** dbus_codec_list(); + +/** + * ConfigurationManager - Get the codec details + * @param payload The payload of the codec + * @return gchar** The codec details + */ gchar** dbus_codec_details(int payload); + +/** + * ConfigurationManager - Get the default codec list + * The default codec list are the codecs selected by the server if the user hasn't made any changes + * @return gchar** The default codec list + */ gchar** dbus_default_codec_list(); + +/** + * ConfigurationManager - Get the list of the codecs used for media negociation + * @return gchar** The list of codecs + */ gchar** dbus_get_active_codec_list( void ); + +/** + * ConfigurationManager - Set the list of codecs used for media negociation + * @param list The list of codecs + */ void dbus_set_active_codec_list( const gchar** list ); -// Audio devices related methods +/** + * ConfigurationManager - Get the list of available input audio plugins + * @return gchar** The list of plugins + */ gchar** dbus_get_input_audio_plugin_list(); + +/** + * ConfigurationManager - Get the list of available output audio plugins + * @return gchar** The list of plugins + */ gchar** dbus_get_output_audio_plugin_list(); + +/** + * ConfigurationManager - Select an input audio plugin + * @param audioPlugin The string description of the plugin + */ void dbus_set_input_audio_plugin(gchar* audioPlugin); + +/** + * ConfigurationManager - Select an output audio plugin + * @param audioPlugin The string description of the plugin + */ void dbus_set_output_audio_plugin(gchar* audioPlugin); + +/** + * ConfigurationManager - Get the list of available output audio devices + * @return gchar** The list of devices + */ gchar** dbus_get_audio_output_device_list(); + +/** + * ConfigurationManager - Select an output audio device + * @param index The index of the soundcard + */ void dbus_set_audio_output_device(const int index); + +/** + * ConfigurationManager - Get the list of available input audio devices + * @return gchar** The list of devices + */ gchar** dbus_get_audio_input_device_list(); + +/** + * ConfigurationManager - Select an input audio device + * @param index The index of the soundcard + */ void dbus_set_audio_input_device(const int index); -// Output and input current devices + +/** + * ConfigurationManager - Get the current audio devices + * @return gchar** The index of the current soundcard + */ gchar** dbus_get_current_audio_devices_index(); + +/** + * ConfigurationManager - Get the index of the specified audio device + * @param name The string description of the audio device + * @return int The index of the device + */ int dbus_get_audio_device_index(const gchar* name); + +/** + * ConfigurationManager - Get the current output audio plugin + * @return gchar* The current plugin + * default + * plughw + * dmix + */ gchar* dbus_get_current_audio_output_plugin(); + +/** + * ConfigurationManager - Tells the GUI if IAX2 support is enabled + * @return int 1 if IAX2 is enabled + * 0 otherwise + */ int dbus_is_iax2_enabled( void ); + +/** + * ConfigurationManager - Query the server about the ringtone option. + * If ringtone is enabled, ringtone on incoming call use custom choice. If not, only standart tone. + * @return int 1 if enabled + * 0 otherwise + */ int dbus_is_ringtone_enabled( void ); + +/** + * ConfigurationManager - Set the ringtone option + * Inverse current value + */ void dbus_ringtone_enabled( void ); + +/** + * ConfigurationManager - Get the ringtone + * @return gchar* The file name selected as a ringtone + */ gchar* dbus_get_ringtone_choice( void ); + +/** + * ConfigurationManager - Set a ringtone + * @param tone The file name of the ringtone + */ void dbus_set_ringtone_choice( const gchar* tone ); -/* Instance */ -void dbus_register( int pid, gchar * name); -void dbus_unregister(int pid); -int dbus_get_registration_count( void ); +/** + * ConfigurationManager - Set the dialpad visible or not + */ +void dbus_set_dialpad( ); + +/** + * ConfigurationManager - Tells if the user wants to display the dialpad or not + * @return int 1 if dialpad has to be displayed + * 0 otherwise + */ +int dbus_get_dialpad( void ); +/** + * ConfigurationManager - Configure the start-up option + * At startup, SFLphone can be displayed or start hidden in the system tray + */ +void dbus_start_hidden( void ); + +/** + * ConfigurationManager - Configure the start-up option + * @return int 1 if SFLphone should start in the system tray + * 0 otherwise + */ +int dbus_is_start_hidden( void ); +/** + * ConfigurationManager - Configure the popup behaviour + * When SFLphone is in the system tray, you can configure when it popups + * Never or only on incoming calls + */ +void dbus_switch_popup_mode( void ); + +/** + * ConfigurationManager - Configure the popup behaviour + * @return int 1 if it should popup on incoming calls + * 0 if it should never popups + */ +int dbus_popup_mode( void ); + +/** + * ConfigurationManager - Start a tone when a new call is open and no numbers have been dialed + * @param start 1 to start + * 0 to stop + * @param type TONE_WITH_MESSAGE + * TONE_WITHOUT_MESSAGE + */ +void dbus_start_tone(const int start , const guint type); + +/** + * Instance - Send registration request to dbus service. + * Manage the instances of clients connected to the server + * @param pid The pid of the processus client + * @param name The string description of the client. Here : GTK+ Client + */ +void dbus_register( int pid, gchar * name); + +/** + * Instance - Send unregistration request to dbus services + * @param pid The pid of the processus + */ +void dbus_unregister(int pid); #endif diff --git a/sflphone-gtk/src/dialpad.c b/sflphone-gtk/src/dialpad.c index e6345cb1d2092a0eacce8933f69e97966586d7c8..71bee58bd5da51b955c8033834ba95e700fc9a1e 100644 --- a/sflphone-gtk/src/dialpad.c +++ b/sflphone-gtk/src/dialpad.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/sflphone-gtk/src/dialpad.h b/sflphone-gtk/src/dialpad.h index 58ee975e89649ea1806dd0cd8d933203f009e80f..2a87148b3b9f12efb53c8865b557d151d4d1b005 100644 --- a/sflphone-gtk/src/dialpad.h +++ b/sflphone-gtk/src/dialpad.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -24,6 +24,11 @@ /** @file dialpad.h * @brief The dialpad widgets. */ + +/** + * Build the dialpad + * @return GtkWidget* The widge representing the dialpad + */ GtkWidget * create_dialpad(); #endif diff --git a/sflphone-gtk/src/errors.c b/sflphone-gtk/src/errors.c new file mode 100644 index 0000000000000000000000000000000000000000..00db523d7842547f407df60ea04bba191bf3d96f --- /dev/null +++ b/sflphone-gtk/src/errors.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * 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. + */ + +#include <errors.h> + + void +sflphone_throw_exception( int err ) +{ + gchar* markup; + switch( err ){ + case ALSA_PLAYBACK_DEVICE: + markup = g_markup_printf_escaped(_("<b>ALSA notification</b>\n\nError while opening playback device")); + break; + case ALSA_CAPTURE_DEVICE: + markup = g_markup_printf_escaped(_("<b>ALSA notification</b>\n\nError while opening capture device")); + break; + } + main_window_error_message( markup ); + free( markup ); +} diff --git a/sflphone-gtk/src/screen.h b/sflphone-gtk/src/errors.h similarity index 69% rename from sflphone-gtk/src/screen.h rename to sflphone-gtk/src/errors.h index 9d78edc164e2e96966665cfea543adf1d15e8249..4f3a9c32ecdcf18a65f3d3510c392dbc3959301e 100644 --- a/sflphone-gtk/src/screen.h +++ b/sflphone-gtk/src/errors.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Copyright (C) 2008 Savoir-Faire Linux inc. + * 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 @@ -17,19 +17,21 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef __SCREEN_H__ -#define __SCREEN_H__ +#ifndef __ERRORS_H +#define __ERRORS_H -#include <gtk/gtk.h> -#include <calllist.h> - -/** @file screen.h - * @brief The screen at the top of the main window. +/** @file errors.h + * @brief Implements internal errors notifications to the client. */ -GtkWidget * create_screen(); -void screen_clear(); +#include <sflphone_const.h> -void screen_set_call(const call_t * c); +/** + * Display an internal error. + * @param err The error code + * ALSA_PLAYBACK_ERROR + * ALSA_CAPTURE_ERROR + */ +void sflphone_throw_exception( int err ); -#endif +#endif diff --git a/sflphone-gtk/src/main.c b/sflphone-gtk/src/main.c index 36ccc06367ba591cc588ad1ab7abc1f58970f729..5d7509ac7890cd8436e6a0f7ec26e2d2f4f33b79 100644 --- a/sflphone-gtk/src/main.c +++ b/sflphone-gtk/src/main.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -49,6 +49,12 @@ There is NO WARRANTY, to the extent permitted by law.\n\n"); show_status_icon(); create_main_window (); + if( dbus_is_start_hidden() ) + { + gtk_widget_hide(GTK_WIDGET( get_main_window() )); + set_minimized( TRUE ); + } + /* start the main loop */ gtk_main (); } diff --git a/sflphone-gtk/src/mainwindow.c b/sflphone-gtk/src/mainwindow.c index 3fa57c779619bd18a2662de572cf3c231dae4ac8..49f6d26226746b7da704eacad5b60c4ccec721ee 100644 --- a/sflphone-gtk/src/mainwindow.c +++ b/sflphone-gtk/src/mainwindow.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -26,7 +26,6 @@ #include <dialpad.h> #include <mainwindow.h> #include <menus.h> -#include <screen.h> #include <sliders.h> #include <gtk/gtk.h> @@ -39,7 +38,6 @@ GtkWidget * dialpad = NULL; GtkWidget * statusBar = NULL; GtkWidget * infoScreen = NULL; gboolean showDialpad = FALSE; // true if the dialpad have been shown -gboolean showInfoScreen = FALSE; // true if the info screen have been shown /** * Terminate the main loop. @@ -252,13 +250,13 @@ main_window_dialpad(gboolean show){ } void -status_bar_message_add(const gchar * message, guint id) +statusbar_push_message(const gchar * message, guint id) { gtk_statusbar_push(GTK_STATUSBAR(statusBar), id, message); } void -status_bar_message_remove(guint id) +statusbar_pop_message(guint id) { gtk_statusbar_pop(GTK_STATUSBAR(statusBar), id); } diff --git a/sflphone-gtk/src/mainwindow.h b/sflphone-gtk/src/mainwindow.h index d1bf8a02e561624995f4d0414c03cf652b68fe07..0f3e7db65db11298da1c182db1256fe2a861f4c2 100644 --- a/sflphone-gtk/src/mainwindow.h +++ b/sflphone-gtk/src/mainwindow.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -26,24 +26,61 @@ * @brief The main window of the client. */ GtkAccelGroup * get_accel_group(); + +/** + * Display the main window + * @return GtkWidget* The main window + */ GtkWidget * get_main_window(); +/** + * Build the main window + */ void create_main_window ( ); +/** + * Display a dialog window + * Ask the user if he wants to hangup current calls before quiting + * @return gboolean TRUE if the user wants to hang up + * FALSE otherwise + */ gboolean main_window_ask_quit() ; + /** * Shows the dialpad on the mainwindow * @param show TRUE if you want to show the dialpad, FALSE to hide it */ void main_window_dialpad(gboolean show); +/** + * Display an error message + * @param markup The error message + */ void main_window_error_message(gchar * markup); +/** + * Display a warning message + * @param markup The warning message + */ void main_window_warning_message(gchar * markup); +/** + * Display an info message + * @param markup The info message + */ void main_window_info_message(gchar * markup); -void status_bar_message_add(const gchar * message , guint id); -void status_bar_message_remove(guint id); +/** + * Push a message on the statusbar stack + * @param message The message to display + * @param id The identifier of the message + */ +void statusbar_push_message( const gchar* message , guint id ); + +/** + * Pop a message from the statusbar stack + * @param id The identifier of the message + */ +void statusbar_pop_message( guint id ); #endif diff --git a/sflphone-gtk/src/menus.c b/sflphone-gtk/src/menus.c index 1d013708820e4a6908063686cea3272d0202d216..199959ee36ccc2b54a79fd70f5741936155ca180 100644 --- a/sflphone-gtk/src/menus.c +++ b/sflphone-gtk/src/menus.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + #include <menus.h> #include <actions.h> #include <calllist.h> @@ -25,7 +25,6 @@ #include <configwindow.h> #include <dbus.h> #include <mainwindow.h> -#include <screen.h> #include <calltab.h> #include <gtk/gtk.h> @@ -41,64 +40,64 @@ guint holdConnId; //The hold_menu signal connection ID void update_menus() { - //Block signals for holdMenu - gtk_signal_handler_block(GTK_OBJECT(holdMenu), holdConnId); - - gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), FALSE); - gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), FALSE); - gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu),FALSE); - gtk_widget_set_sensitive( GTK_WIDGET(holdMenu), FALSE); - gtk_widget_set_sensitive( GTK_WIDGET(copyMenu), FALSE); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(holdMenu), FALSE); - - call_t * selectedCall = call_get_selected(active_calltree); - if (selectedCall) - { - gtk_widget_set_sensitive( GTK_WIDGET(copyMenu), TRUE); - switch(selectedCall->state) - { - case CALL_STATE_INCOMING: - gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), TRUE); - gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); - break; - case CALL_STATE_HOLD: - gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); - gtk_widget_set_sensitive( GTK_WIDGET(holdMenu), TRUE); - gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu),TRUE); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(holdMenu), TRUE); - break; - case CALL_STATE_RINGING: - gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), TRUE); - gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); - break; - case CALL_STATE_DIALING: - gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), TRUE); - gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); - gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu),TRUE); - break; - case CALL_STATE_CURRENT: - gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); - gtk_widget_set_sensitive( GTK_WIDGET(holdMenu), TRUE); - gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu),TRUE); - break; - case CALL_STATE_BUSY: - case CALL_STATE_FAILURE: - gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); - break; - default: - g_warning("Should not happen in update_menus()!"); - break; - } - } - else - { - gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu), TRUE); - } - gtk_signal_handler_unblock(holdMenu, holdConnId); + //Block signals for holdMenu + gtk_signal_handler_block(GTK_OBJECT(holdMenu), holdConnId); + + gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), FALSE); + gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), FALSE); + gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu),FALSE); + gtk_widget_set_sensitive( GTK_WIDGET(holdMenu), FALSE); + gtk_widget_set_sensitive( GTK_WIDGET(copyMenu), FALSE); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(holdMenu), FALSE); + + call_t * selectedCall = call_get_selected(active_calltree); + if (selectedCall) + { + gtk_widget_set_sensitive( GTK_WIDGET(copyMenu), TRUE); + switch(selectedCall->state) + { + case CALL_STATE_INCOMING: + gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), TRUE); + gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); + break; + case CALL_STATE_HOLD: + gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); + gtk_widget_set_sensitive( GTK_WIDGET(holdMenu), TRUE); + gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu),TRUE); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(holdMenu), TRUE); + break; + case CALL_STATE_RINGING: + gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), TRUE); + gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); + break; + case CALL_STATE_DIALING: + gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), TRUE); + gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); + gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu),TRUE); + break; + case CALL_STATE_CURRENT: + gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); + gtk_widget_set_sensitive( GTK_WIDGET(holdMenu), TRUE); + gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu),TRUE); + break; + case CALL_STATE_BUSY: + case CALL_STATE_FAILURE: + gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), TRUE); + break; + default: + g_warning("Should not happen in update_menus()!"); + break; + } + } + else + { + gtk_widget_set_sensitive( GTK_WIDGET(newCallMenu), TRUE); + } + gtk_signal_handler_unblock(holdMenu, holdConnId); } /* ----------------------------------------------------------------- */ -static void + static void help_about ( void * foo) { gchar *authors[] = { @@ -106,75 +105,82 @@ help_about ( void * foo) "Jérôme Oufella <jerome.oufella@savoirfairelinux.com>", "Julien Plissonneau Duquene <julien.plissonneau.duquene@savoirfairelinux.com>", "Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>", - "Pierre-Luc Beaudoin <pierre-luc@squidy.info>", + "Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>", "Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>" - "Jean-Philippe Barrette-LaPierre", + "Jean-Philippe Barrette-LaPierre", "Laurielle Lea", NULL}; gchar *artists[] = { - "Pierre-Luc Beaudoin <pierre-luc@squidy.info>", + "Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>", NULL}; - + gtk_show_about_dialog( GTK_WINDOW(get_main_window()), - "name", PACKAGE, - "title", _("About SFLphone"), - "version", VERSION, - "website", "http://www.sflphone.org", - "copyright", "Copyright © 2004-2007 Savoir-faire Linux Inc.", - "translator-credits", "", - "comments", _("SFLphone is a VoIP client compatible with SIP and IAX2 protocols."), - "artists", artists, - "authors", authors, - NULL); + "name", PACKAGE, + "title", _("About SFLphone"), + "version", VERSION, + "website", "http://www.sflphone.org", + "copyright", "Copyright © 2004-2007 Savoir-faire Linux Inc.", + "translator-credits", "", + "comments", _("SFLphone is a VoIP client compatible with SIP and IAX2 protocols."), + "artists", artists, + "authors", authors, + NULL); } -GtkWidget * + GtkWidget * create_help_menu() { GtkWidget * menu; GtkWidget * root_menu; GtkWidget * menu_items; - + menu = gtk_menu_new (); - + /*menu_items = gtk_separator_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); - */ + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); + */ menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_ABOUT, get_accel_group()); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", - G_CALLBACK (help_about), - NULL); + G_CALLBACK (help_about), + NULL); gtk_widget_show (menu_items); - + root_menu = gtk_menu_item_new_with_mnemonic (_("_Help")); gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu); return root_menu; } /* ----------------------------------------------------------------- */ -static void + static void call_new_call ( void * foo) { sflphone_new_call(); } -static void + static void call_quit ( void * foo) { sflphone_quit(); } -static void + static void call_minimize ( void * foo) { gtk_widget_hide(GTK_WIDGET( get_main_window() )); - set_minimized( TRUE ); } -static void + static void +switch_account( GtkWidget* item , gpointer data ) +{ + account_t* acc = g_object_get_data( G_OBJECT(item) , "account" ); + g_print("%s\n" , acc->accountID); + account_list_set_current_id( acc->accountID ); +} + + static void call_hold (void* foo) { call_t * selectedCall = call_get_selected(current_calls); @@ -192,73 +198,73 @@ call_hold (void* foo) } } -static void + static void call_pick_up ( void * foo) { sflphone_pick_up(); } -static void + static void call_hang_up ( void * foo) { sflphone_hang_up(); } -GtkWidget * + GtkWidget * create_call_menu() { GtkWidget * menu; GtkWidget * root_menu; GtkWidget * menu_items; - + menu = gtk_menu_new (); - + newCallMenu = gtk_image_menu_item_new_with_mnemonic(_("_New call")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), newCallMenu); g_signal_connect_swapped (G_OBJECT (newCallMenu), "activate", - G_CALLBACK (call_new_call), - NULL); + G_CALLBACK (call_new_call), + NULL); gtk_widget_show (newCallMenu); - + menu_items = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); - + pickUpMenu = gtk_image_menu_item_new_with_mnemonic(_("_Pick up")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), pickUpMenu); gtk_widget_set_sensitive( GTK_WIDGET(pickUpMenu), FALSE); g_signal_connect_swapped (G_OBJECT (pickUpMenu), "activate", - G_CALLBACK (call_pick_up), - NULL); + G_CALLBACK (call_pick_up), + NULL); gtk_widget_show (pickUpMenu); - + hangUpMenu = gtk_image_menu_item_new_with_mnemonic(_("_Hang up")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), hangUpMenu); gtk_widget_set_sensitive( GTK_WIDGET(hangUpMenu), FALSE); g_signal_connect_swapped (G_OBJECT (hangUpMenu), "activate", - G_CALLBACK (call_hang_up), - NULL); + G_CALLBACK (call_hang_up), + NULL); gtk_widget_show (hangUpMenu); - + holdMenu = gtk_check_menu_item_new_with_mnemonic (_("On _Hold")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), holdMenu); gtk_widget_set_sensitive( GTK_WIDGET(holdMenu), FALSE); //Here we connect only to activate //The toggled state is managed from update_menus() holdConnId = g_signal_connect(G_OBJECT (holdMenu), "activate", - G_CALLBACK (call_hold), - NULL); + G_CALLBACK (call_hold), + NULL); gtk_widget_show (menu_items); - + // Separator menu_items = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); - + // Close menu to minimize the main window to the system tray menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_CLOSE, get_accel_group()); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", - G_CALLBACK (call_minimize), - NULL); + G_CALLBACK (call_minimize), + NULL); gtk_widget_show (menu_items); // Separator @@ -269,11 +275,11 @@ create_call_menu() menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_QUIT, get_accel_group()); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", - G_CALLBACK (call_quit), - NULL); + G_CALLBACK (call_quit), + NULL); gtk_widget_show (menu_items); - - + + root_menu = gtk_menu_item_new_with_mnemonic (_("_Call")); gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu); @@ -281,26 +287,26 @@ create_call_menu() } /* ----------------------------------------------------------------- */ -static void + static void edit_preferences ( void * foo) { show_config_window(); } -static void + static void edit_accounts ( void * foo) { show_accounts_window(); } // The menu Edit/Copy should copy the current selected call's number -static void + static void edit_copy ( void * foo) { GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); call_t * selectedCall = call_get_selected(current_calls); gchar * no = NULL; - + if(selectedCall) { switch(selectedCall->state) @@ -308,197 +314,188 @@ edit_copy ( void * foo) case CALL_STATE_TRANSFERT: case CALL_STATE_DIALING: case CALL_STATE_RINGING: - no = selectedCall->to; - break; + no = selectedCall->to; + break; case CALL_STATE_CURRENT: case CALL_STATE_HOLD: case CALL_STATE_BUSY: case CALL_STATE_FAILURE: case CALL_STATE_INCOMING: default: - no = call_get_number(selectedCall); - break; + no = call_get_number(selectedCall); + break; } - + gtk_clipboard_set_text (clip, no, strlen(no) ); } - + } // The menu Edit/Paste should paste the clipboard into the current selected call -static void + static void edit_paste ( void * foo) { GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); call_t * selectedCall = call_get_selected(current_calls); gchar * no = gtk_clipboard_wait_for_text (clip); - + if(no && selectedCall) { switch(selectedCall->state) { case CALL_STATE_TRANSFERT: case CALL_STATE_DIALING: - // Add the text to the number - { - gchar * before = selectedCall->to; - selectedCall->to = g_strconcat(selectedCall->to, no, NULL); - g_free(before); - g_print("TO: %s\n", selectedCall->to); - - if(selectedCall->state == CALL_STATE_DIALING) - { - g_free(selectedCall->from); - selectedCall->from = g_strconcat("\"\" <", selectedCall->to, ">", NULL); - } - screen_set_call(selectedCall); - update_call_tree(current_calls, selectedCall); - } - break; + // Add the text to the number + { + gchar * before = selectedCall->to; + selectedCall->to = g_strconcat(selectedCall->to, no, NULL); + g_free(before); + g_print("TO: %s\n", selectedCall->to); + + if(selectedCall->state == CALL_STATE_DIALING) + { + g_free(selectedCall->from); + selectedCall->from = g_strconcat("\"\" <", selectedCall->to, ">", NULL); + } + update_call_tree(current_calls, selectedCall); + } + break; case CALL_STATE_RINGING: case CALL_STATE_INCOMING: case CALL_STATE_BUSY: case CALL_STATE_FAILURE: case CALL_STATE_HOLD: - { // Create a new call to hold the new text - selectedCall = sflphone_new_call(); - - gchar * before = selectedCall->to; - selectedCall->to = g_strconcat(selectedCall->to, no, NULL); - g_free(before); - g_print("TO: %s\n", selectedCall->to); - - g_free(selectedCall->from); - selectedCall->from = g_strconcat("\"\" <", selectedCall->to, ">", NULL); - - screen_set_call(selectedCall); - update_call_tree(current_calls, selectedCall); - } - break; + { // Create a new call to hold the new text + selectedCall = sflphone_new_call(); + + gchar * before = selectedCall->to; + selectedCall->to = g_strconcat(selectedCall->to, no, NULL); + g_free(before); + g_print("TO: %s\n", selectedCall->to); + + g_free(selectedCall->from); + selectedCall->from = g_strconcat("\"\" <", selectedCall->to, ">", NULL); + + update_call_tree(current_calls, selectedCall); + } + break; case CALL_STATE_CURRENT: default: - { - int i; - for(i = 0; i < strlen(no); i++) - { - gchar * oneNo = g_strndup(&no[i], 1); - g_print("<%s>\n", oneNo); - dbus_play_dtmf(oneNo); - - gchar * temp = g_strconcat(call_get_number(selectedCall), oneNo, NULL); - gchar * before = selectedCall->from; - selectedCall->from = g_strconcat("\"",call_get_name(selectedCall) ,"\" <", temp, ">", NULL); - g_free(before); - g_free(temp); - screen_set_call(selectedCall); - update_call_tree(current_calls, selectedCall); - - } - } - break; + { + int i; + for(i = 0; i < strlen(no); i++) + { + gchar * oneNo = g_strndup(&no[i], 1); + g_print("<%s>\n", oneNo); + dbus_play_dtmf(oneNo); + + gchar * temp = g_strconcat(call_get_number(selectedCall), oneNo, NULL); + gchar * before = selectedCall->from; + selectedCall->from = g_strconcat("\"",call_get_name(selectedCall) ,"\" <", temp, ">", NULL); + g_free(before); + g_free(temp); + update_call_tree(current_calls, selectedCall); + + } + } + break; } - + } else // There is no current call, create one { selectedCall = sflphone_new_call(); - + gchar * before = selectedCall->to; selectedCall->to = g_strconcat(selectedCall->to, no, NULL); g_free(before); g_print("TO: %s\n", selectedCall->to); - + g_free(selectedCall->from); selectedCall->from = g_strconcat("\"\" <", selectedCall->to, ">", NULL); - - screen_set_call(selectedCall); - update_call_tree(current_calls, selectedCall); + update_call_tree(current_calls,selectedCall); } - + } -GtkWidget * + GtkWidget * create_edit_menu() { GtkWidget * menu; GtkWidget * root_menu; GtkWidget * menu_items; - + menu = gtk_menu_new (); copyMenu = gtk_image_menu_item_new_from_stock( GTK_STOCK_COPY, get_accel_group()); gtk_menu_shell_append (GTK_MENU_SHELL (menu), copyMenu); g_signal_connect_swapped (G_OBJECT (copyMenu), "activate", - G_CALLBACK (edit_copy), - NULL); + G_CALLBACK (edit_copy), + NULL); gtk_widget_show (copyMenu); - + pasteMenu = gtk_image_menu_item_new_from_stock( GTK_STOCK_PASTE, get_accel_group()); gtk_menu_shell_append (GTK_MENU_SHELL (menu), pasteMenu); g_signal_connect_swapped (G_OBJECT (pasteMenu), "activate", - G_CALLBACK (edit_paste), - NULL); + G_CALLBACK (edit_paste), + NULL); gtk_widget_show (pasteMenu); - + menu_items = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); - + menu_items = gtk_menu_item_new_with_mnemonic( _("_Accounts") ); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", - G_CALLBACK (edit_accounts), - NULL); + G_CALLBACK (edit_accounts), + NULL); gtk_widget_show (menu_items); menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_PREFERENCES, get_accel_group()); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", - G_CALLBACK (edit_preferences), - NULL); + G_CALLBACK (edit_preferences), + NULL); gtk_widget_show (menu_items); - - + + root_menu = gtk_menu_item_new_with_mnemonic (_("_Edit")); gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu); return root_menu; } /* ----------------------------------------------------------------- */ -static void -view_dial_pad (GtkCheckMenuItem *checkmenuitem, - void* foo) + static void +view_dialpad (GtkCheckMenuItem *checkmenuitem, + void* foo) { main_window_dialpad(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(checkmenuitem))); + dbus_set_dialpad(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(checkmenuitem))); } -GtkWidget * + GtkWidget * create_view_menu() { GtkWidget * menu; GtkWidget * root_menu; GtkWidget * menu_items; - GtkWidget * submenu; - GtkWidget * submenu_items; menu = gtk_menu_new (); menu_items = gtk_check_menu_item_new_with_mnemonic (_("_Dialpad")); - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM ( menu_items ), TRUE); + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM ( menu_items ), dbus_get_dialpad()); main_window_dialpad(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_items))); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect(G_OBJECT (menu_items), "toggled", - G_CALLBACK (view_dial_pad), - NULL); + G_CALLBACK (view_dialpad), + NULL); gtk_widget_show (menu_items); - + menu_items = gtk_check_menu_item_new_with_mnemonic (_("_Volume controls")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); gtk_widget_set_sensitive( GTK_WIDGET(menu_items), FALSE); - g_signal_connect(G_OBJECT (menu_items), "toggled", - G_CALLBACK (view_dial_pad), - NULL); gtk_widget_show (menu_items); - + menu_items = gtk_menu_item_new_with_mnemonic(_("_Toolbar")); gtk_widget_set_sensitive( GTK_WIDGET(menu_items) , FALSE); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); @@ -509,7 +506,7 @@ create_view_menu() return root_menu; } /* ----------------------------------------------------------------- */ -GtkWidget * + GtkWidget * create_menus ( ) { @@ -517,13 +514,13 @@ create_menus ( ) GtkWidget * root_menu; menu_bar = gtk_menu_bar_new (); - + root_menu = create_call_menu(); gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), root_menu); - + root_menu = create_edit_menu(); gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), root_menu); - + root_menu = create_view_menu(); gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), root_menu); @@ -531,55 +528,57 @@ create_menus ( ) gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), root_menu); gtk_widget_show (menu_bar); - - + + return menu_bar; } /* ----------------------------------------------------------------- */ -void + 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; - - call_t * selectedCall = call_get_selected(current_calls); - if (selectedCall) - { + gboolean accounts = FALSE; + + call_t * selectedCall = call_get_selected(current_calls); + if (selectedCall) + { copy = TRUE; switch(selectedCall->state) - { - case CALL_STATE_INCOMING: - pickup = TRUE; - hangup = TRUE; - break; + { + case CALL_STATE_INCOMING: + pickup = TRUE; + hangup = TRUE; + break; case CALL_STATE_HOLD: - hangup = TRUE; - hold = TRUE; - break; + hangup = TRUE; + hold = TRUE; + break; case CALL_STATE_RINGING: - hangup = TRUE; - break; + hangup = TRUE; + break; case CALL_STATE_DIALING: - pickup = TRUE; - hangup = TRUE; - break; + pickup = TRUE; + hangup = TRUE; + accounts = TRUE; + break; case CALL_STATE_CURRENT: - hangup = TRUE; - hold = TRUE; - break; + hangup = TRUE; + hold = TRUE; + break; case CALL_STATE_BUSY: case CALL_STATE_FAILURE: - hangup = TRUE; - break; - default: - g_warning("Should not happen in show_popup_menu!"); - break; - } + hangup = TRUE; + break; + default: + g_warning("Should not happen in show_popup_menu!"); + break; + } } - + GtkWidget *menu; //GtkWidget *image; int button, event_time; @@ -594,62 +593,92 @@ show_popup_menu (GtkWidget *my_widget, GdkEventButton *event) menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_COPY, get_accel_group()); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect (G_OBJECT (menu_items), "activate", - G_CALLBACK (edit_copy), - NULL); + G_CALLBACK (edit_copy), + NULL); gtk_widget_show (menu_items); } - + menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_PASTE, get_accel_group()); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect (G_OBJECT (menu_items), "activate", - G_CALLBACK (edit_paste), - NULL); + G_CALLBACK (edit_paste), + NULL); gtk_widget_show (menu_items); - + if(pickup || hangup || hold) { menu_items = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); gtk_widget_show (menu_items); } - + if(pickup) { - + menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Pick up")); - //image = gtk_image_new_from_file( ICONS_DIR "/accept.svg"); + //image = gtk_image_new_from_file( ICONS_DIR "/accept.svg"); //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_pick_up), - NULL); + G_CALLBACK (call_pick_up), + NULL); gtk_widget_show (menu_items); } - + if(hangup) { menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Hang up")); - //image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg"); + //image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg"); //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_hang_up), - NULL); + G_CALLBACK (call_hang_up), + NULL); gtk_widget_show (menu_items); } - + if(hold) { menu_items = gtk_check_menu_item_new_with_mnemonic (_("On _Hold")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_items), - (selectedCall->state == CALL_STATE_HOLD ? TRUE : FALSE)); + (selectedCall->state == CALL_STATE_HOLD ? TRUE : FALSE)); g_signal_connect(G_OBJECT (menu_items), "activate", - G_CALLBACK (call_hold), - NULL); + G_CALLBACK (call_hold), + NULL); gtk_widget_show (menu_items); } - + + if(accounts) + { + menu_items = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); + gtk_widget_show (menu_items); + + int i; + account_t* acc; + gchar* alias; + for( i = 0 ; i < account_list_get_size() ; i++ ){ + 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 ){ + alias = g_strconcat( g_hash_table_lookup(acc->properties , ACCOUNT_ALIAS) , " - ",g_hash_table_lookup(acc->properties , ACCOUNT_TYPE), NULL); + menu_items = gtk_check_menu_item_new_with_mnemonic(alias); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); + g_object_set_data( G_OBJECT( menu_items ) , "account" , acc ); + g_free( alias ); + if( account_list_get_current() != NULL ){ + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_items), + (g_strcasecmp( acc->accountID , account_list_get_current()->accountID) == 0)? TRUE : FALSE); + } + g_signal_connect (G_OBJECT (menu_items), "activate", + G_CALLBACK (switch_account), + NULL); + gtk_widget_show (menu_items); + } // fi + } + } + if (event) { button = event->button; @@ -663,6 +692,6 @@ show_popup_menu (GtkWidget *my_widget, GdkEventButton *event) gtk_menu_attach_to_widget (GTK_MENU (menu), my_widget, NULL); gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, - button, event_time); + button, event_time); } diff --git a/sflphone-gtk/src/menus.h b/sflphone-gtk/src/menus.h index 18d7fcb9d675c1d905cef7266a247b020b55aac0..ca6f1499873452a96d03a98b588b35e34dc1b213 100644 --- a/sflphone-gtk/src/menus.h +++ b/sflphone-gtk/src/menus.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -24,8 +24,23 @@ /** @file menus.h * @brief The menus of the main window. */ + +/** + * Build the menus bar + * @return GtkWidget* The menu bar + */ GtkWidget * create_menus(); + +/** + * Update the menu state + */ void update_menus(); + +/** + * Create a menu on right-click + * @param my_widget The widget you click on + * @param event The mouse event + */ void show_popup_menu (GtkWidget *my_widget, GdkEventButton *event); #endif diff --git a/sflphone-gtk/src/screen.c b/sflphone-gtk/src/screen.c deleted file mode 100644 index c4a89c37c1a898886481de26bda677c913566975..0000000000000000000000000000000000000000 --- a/sflphone-gtk/src/screen.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> - * 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. - */ - -#include <dialpad.h> -#include <screen.h> -#include <codeclist.h> - -GtkWidget * label; -GtkWidget * hbox; - -GtkWidget * -create_screen() -{ - GtkWidget * event; - GtkWidget * sw; - GtkWidget *subvbox; - - GdkColor color; - gdk_color_parse ("white", &color); - - subvbox = gtk_vbox_new ( FALSE /*homogeneous*/, 10 /*spacing*/); - - sw = gtk_scrolled_window_new( NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_NONE); - - event = gtk_event_box_new (); - gtk_widget_modify_bg (event, GTK_STATE_NORMAL, &color); - - //label = gtk_label_new ("test"); - label = gtk_label_new(""); - gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); - gtk_misc_set_padding(GTK_MISC(label), 5, 5); - gtk_misc_set_alignment(GTK_MISC(label), 0,0); - gtk_container_add (GTK_CONTAINER (event), label); - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), event); - - gtk_box_pack_start (GTK_BOX (subvbox), sw, FALSE /*expand*/, TRUE /*fill*/, 0 /*padding*/); - - //screen_clear(); - - return subvbox; -} - -void -screen_clear() -{ - gtk_label_set_markup(GTK_LABEL(label), "<b>CALL INFOS</b>\n"); -} - -void -screen_set_call(const call_t * c) -{ - printf("accountID = %s\ncall to = %s\n", c->from, c->to); - gchar * markup = g_strconcat("<b><i>Calling to:</i></b>", "\t", call_get_number(c), - "\n<b><i>Codec:</i></b>", "\t", codec_list_get_nth(0)->name, NULL); - gtk_label_set_markup(GTK_LABEL(label), markup); - g_free(markup); -} diff --git a/sflphone-gtk/src/sflnotify.c b/sflphone-gtk/src/sflnotify.c new file mode 100644 index 0000000000000000000000000000000000000000..14b17ff8af1588d3a0aa611fc29bb5bb1a5d28bb --- /dev/null +++ b/sflphone-gtk/src/sflnotify.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * 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. + */ + +#include <sflnotify.h> + +static NotifyNotification *notification; + + void +notify_incoming_call( call_t* c ) +{ + GdkPixbuf *pixbuf; + gchar* callerid; + gchar* title; + notify_init("sflphone"); + + title = g_markup_printf_escaped(_("%s account: %s") , + (gchar*)g_hash_table_lookup(account_list_get_by_id(c->accountID)->properties , ACCOUNT_TYPE) , + (gchar*)g_hash_table_lookup(account_list_get_by_id(c->accountID)->properties , ACCOUNT_ALIAS) ) ; + callerid = g_markup_printf_escaped(_("<i>From:</i> %s") , c->from); + + + //pixbuf = gdk_pixbuf_new_from_file(ICON_DIR "/sflphone.png", NULL); + pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL); + + notification = notify_notification_new( title, + callerid, + NULL, + NULL); + notify_notification_set_urgency( notification , NOTIFY_URGENCY_CRITICAL ); + notify_notification_set_icon_from_pixbuf (notification, pixbuf); + notify_notification_attach_to_status_icon( notification , get_status_icon() ); + notify_notification_set_timeout( notification , (( g_strcasecmp(__TIMEOUT_MODE, "default") == 0 )? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER )); + g_object_set_data( G_OBJECT( notification ) , "call" , c ); + notify_notification_add_action( notification , "accept" , _("Accept") , (NotifyActionCallback) answer_call_cb , NULL, NULL ); + notify_notification_add_action( notification , "refuse" , _("Refuse") , (NotifyActionCallback) refuse_call_cb , NULL , NULL ); + notify_notification_add_action( notification , "ignore" , _("Ignore") , (NotifyActionCallback) ignore_call_cb , NULL , NULL ); + + if (!notify_notification_show (notification, NULL)) { + g_print("notify(), failed to send notification\n"); + } +} + + void +answer_call_cb( NotifyNotification *notification, gpointer data ) +{ + call_t* c = (call_t*)g_object_get_data( G_OBJECT( notification ) , "call" ); + dbus_accept(c); + if( __POPUP_WINDOW ) + status_icon_unminimize(); + g_object_unref( notification ); +} + + void +refuse_call_cb( NotifyNotification *notification, gpointer data ) +{ + call_t* c = (call_t*)g_object_get_data( G_OBJECT( notification ) , "call" ); + dbus_refuse(c); + g_object_unref( notification ); +} + + void +ignore_call_cb( NotifyNotification *notification, gpointer data ) +{ + g_object_unref( notification ); +} + + void +notify_voice_mails( guint count , account_t* acc ) +{ + // the account is different from NULL + GdkPixbuf *pixbuf; + gchar* title; + gchar* body; + notify_init("sflphone"); + + title = g_markup_printf_escaped(_("%s account: %s") , + (gchar*)g_hash_table_lookup(acc->properties , ACCOUNT_TYPE) , + (gchar*) g_hash_table_lookup(acc->properties , ACCOUNT_ALIAS) ) ; + body = g_markup_printf_escaped(_("%d voice mails"), count); + + pixbuf = gdk_pixbuf_new_from_file(ICON_DIR "/sflphone.png", NULL); + + notification = notify_notification_new( title, + body, + NULL, + NULL); + notify_notification_set_urgency( notification , NOTIFY_URGENCY_LOW ); + notify_notification_set_icon_from_pixbuf (notification, pixbuf); + notify_notification_attach_to_status_icon( notification , get_status_icon() ); + notify_notification_set_timeout( notification , NOTIFY_EXPIRES_DEFAULT ); + notify_notification_add_action( notification , "ignore" , _("Ignore") , (NotifyActionCallback) ignore_call_cb , NULL , NULL ); + + if (!notify_notification_show (notification, NULL)) { + g_print("notify(), failed to send notification\n"); + } +} + + void +notify_current_account( account_t* acc ) +{ + // the account is different from NULL + GdkPixbuf *pixbuf; + gchar* title; + gchar* body=""; + notify_init("sflphone"); + + body = g_markup_printf_escaped(_("Calling with %s account <i>%s</i>") , + (gchar*)g_hash_table_lookup( acc->properties , ACCOUNT_TYPE) , + (gchar*)g_hash_table_lookup( acc->properties , ACCOUNT_ALIAS)); + + title = g_markup_printf_escaped(_("Current account")); + + pixbuf = gdk_pixbuf_new_from_file(ICON_DIR "/sflphone.png", NULL); + + notification = notify_notification_new( title, + body, + NULL, + NULL); + notify_notification_set_urgency( notification , NOTIFY_URGENCY_NORMAL ); + notify_notification_set_icon_from_pixbuf (notification, pixbuf); + notify_notification_attach_to_status_icon( notification , get_status_icon() ); + notify_notification_set_timeout( notification , NOTIFY_EXPIRES_DEFAULT ); + notify_notification_add_action( notification , "ignore" , _("Ignore") , (NotifyActionCallback) ignore_call_cb , NULL , NULL ); + + if (!notify_notification_show (notification, NULL)) { + g_print("notify(), failed to send notification\n"); + } +} + + void +notify_no_accounts( ) +{ + GdkPixbuf *pixbuf; + gchar* title; + gchar* body=""; + notify_init("sflphone"); + + body = g_markup_printf_escaped(_("You haven't setup any accounts")); + + title = g_markup_printf_escaped(_("Error")); + + pixbuf = gdk_pixbuf_new_from_file(ICON_DIR "/sflphone.png", NULL); + + notification = notify_notification_new( title, + body, + NULL, + NULL); + notify_notification_set_urgency( notification , NOTIFY_URGENCY_CRITICAL ); + notify_notification_set_icon_from_pixbuf (notification, pixbuf); + notify_notification_attach_to_status_icon( notification , get_status_icon() ); + notify_notification_set_timeout( notification , NOTIFY_EXPIRES_DEFAULT ); + notify_notification_add_action( notification , "setup" , _("Setup Accounts") , (NotifyActionCallback) setup_accounts_cb , NULL , NULL ); + + if (!notify_notification_show (notification, NULL)) { + g_print("notify(), failed to send notification\n"); + } +} + + void +setup_accounts_cb( NotifyNotification *notification, gpointer data ) +{ + show_accounts_window(); + //g_object_unref( notification ); +} + + void +notify_no_registered_accounts( ) +{ + GdkPixbuf *pixbuf; + gchar* title; + gchar* body=""; + notify_init("sflphone"); + + body = g_markup_printf_escaped(_("You have no registered accounts")); + + title = g_markup_printf_escaped(_("Error")); + + pixbuf = gdk_pixbuf_new_from_file(ICON_DIR "/sflphone.png", NULL); + + notification = notify_notification_new( title, + body, + NULL, + NULL); + notify_notification_set_urgency( notification , NOTIFY_URGENCY_CRITICAL ); + notify_notification_set_icon_from_pixbuf (notification, pixbuf); + notify_notification_attach_to_status_icon( notification , get_status_icon() ); + notify_notification_set_timeout( notification , NOTIFY_EXPIRES_DEFAULT ); + notify_notification_add_action( notification , "setup" , _("Setup Accounts") , (NotifyActionCallback) setup_accounts_cb , NULL , NULL ); + + if (!notify_notification_show (notification, NULL)) { + g_print("notify(), failed to send notification\n"); + } +} diff --git a/sflphone-gtk/src/SFLnotify.h b/sflphone-gtk/src/sflnotify.h similarity index 56% rename from sflphone-gtk/src/SFLnotify.h rename to sflphone-gtk/src/sflnotify.h index 276a62079207444498d166258056461acc9a4cab..5f3bf3130404bc6fc677d037f63f126a8f94e346 100644 --- a/sflphone-gtk/src/SFLnotify.h +++ b/sflphone-gtk/src/sflnotify.h @@ -21,50 +21,80 @@ #ifndef __SFL_NOTIFY_H__ #define __SFL_NOTIFY_H__ -#include <libnotify/notify.h> +/** @file sflnotify.h + * @brief Implements desktop notification for incoming events. + */ +#include <libnotify/notify.h> #include <accountlist.h> #include <calllist.h> #include <dbus.h> #include <actions.h> #include <statusicon.h> +#include <configwindow.h> +#include <sflphone_const.h> -#define __TIMEOUT_MODE "default" -#define __TIMEOUT_TIME 30000 // 30 secondes -#define __POPUP_WINDOW true - - -/* - * Notify an incoming call with the libnotify notification library - * A dialog box appears near the status icon +/** + * Notify an incoming call + * A dialog box is attached to the status icon * @param c The incoming call */ void notify_incoming_call( call_t* c); +/** + * Notify voice mails count + * An info box is attached to the status icon + * @param count The number of voice mails + * @param acc The account that received the notification + */ void notify_voice_mails( guint count , account_t* acc ); -/* +/** + * Notify the current account used to make calls with + * @param acc The current account + */ +void notify_current_account( account_t* acc ); + +/** + * Notify that no accounts have been setup + */ +void notify_no_accounts( ); + +/** + * Notify that there is no registered account + */ +void notify_no_registered_accounts( ); + +/** * Callback when answer button is pressed. - * Action: Pick up the incoming call + * Action associated: Pick up the incoming call * @param notification The pointer on the notification structure * @param data The data associated. Here: call_t* */ -void answer_call_cb( NotifyNotification *notification, gchar *action, gpointer data ); +void answer_call_cb( NotifyNotification *notification, gpointer data ); -/* +/** * Callback when refuse button is pressed - * Action: hang up the incoming call + * Action associated: Hang up the incoming call * @param notification The pointer on the notification structure * @param data The data associated. Here: call_t* */ -void refuse_call_cb( NotifyNotification *notification, gchar *action, gpointer data ); +void refuse_call_cb( NotifyNotification *notification, gpointer data ); -/* +/** * Callback when ignore button is pressed - * Action: nothing - The call continues ringing + * Action associated: Nothing - The call continues ringing * @param notification The pointer on the notification structure * @param data The data associated. Here: call_t* */ -void ignore_call_cb( NotifyNotification *notification, gchar *action, gpointer data ); +void ignore_call_cb( NotifyNotification *notification, gpointer data ); + +/** + * Callback when you try to make a call without accounts setup and 'setup account' button is clicked. + * Action associated: Open the account window + * @param notification The pointer on the notification structure + * @param data The data associated. Here: account_t* + */ +void setup_accounts_cb(NotifyNotification *notification, gpointer data); #endif diff --git a/sflphone-gtk/src/sflphone_const.h b/sflphone-gtk/src/sflphone_const.h new file mode 100644 index 0000000000000000000000000000000000000000..b3b565949daefc444905d63ea3929eee63fa008b --- /dev/null +++ b/sflphone-gtk/src/sflphone_const.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * 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. + */ + +#ifndef __SFLPHONE_CONST_H +#define __SFLPHONE_CONST_H + +#include <libintl.h> +#include "dbus.h" + +/* @file sflphone_const.h + * @brief Contains the global variables for the client code + */ + +/** Locale */ +#define _(STRING) gettext( STRING ) + +/** Account type : SIP / IAX */ +#define ACCOUNT_TYPE "Account.type" +/** Account alias */ +#define ACCOUNT_ALIAS "Account.alias" +/** Tells if account is enabled or not */ +#define ACCOUNT_ENABLED "Account.enable" +/** SIP parameter: full name */ +#define ACCOUNT_SIP_FULL_NAME "SIP.fullName" +/** SIP parameter: host name */ +#define ACCOUNT_SIP_HOST_PART "SIP.hostPart" +/** SIP parameter: user name */ +#define ACCOUNT_SIP_USER_PART "SIP.userPart" +/** SIP parameter: authentification name */ +#define ACCOUNT_SIP_AUTH_NAME "SIP.username" +/** SIP parameter: password */ +#define ACCOUNT_SIP_PASSWORD "SIP.password" +/** SIP parameter: proxy address */ +#define ACCOUNT_SIP_PROXY "SIP.proxy" +/** SIP parameter: stun server address */ +#define ACCOUNT_SIP_STUN_SERVER "STUN.server" +/** SIP parameter: tells if stun is enabled or not */ +#define ACCOUNT_SIP_STUN_ENABLED "STUN.enable" +/** IAX2 parameter: full name */ +#define ACCOUNT_IAX_FULL_NAME "IAX.fullName" +/** IAX2 parameter: host name */ +#define ACCOUNT_IAX_HOST "IAX.host" +/** IAX2 parameter: user name */ +#define ACCOUNT_IAX_USER "IAX.user" +/** IAX2 parameter: password name */ +#define ACCOUNT_IAX_PASS "IAX.pass" + +/** Error while opening capture device */ +#define ALSA_CAPTURE_DEVICE 0x0001 +/** Error while opening playback device */ +#define ALSA_PLAYBACK_DEVICE 0x0010 + +/** Tone to play when no voice mails */ +#define TONE_WITHOUT_MESSAGE 0 +/** 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 +/** Behaviour of the main window on incoming calls */ +#define __POPUP_WINDOW ( dbus_popup_mode() ) + +/** Messages ID for the status bar - Incoming calls */ +#define __MSG_INCOMING_CALL 0 +/** Messages ID for the status bar - Calling */ +#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 */ +#define __MSG_ACCOUNT_DEFAULT 3 + +/** Desktop notifications - Time before to close the notification*/ +#define __TIMEOUT_MODE "default" +/** Desktop notifications - Time before to close the notification*/ +#define __TIMEOUT_TIME 30000 // 30 secondes + +#endif diff --git a/sflphone-gtk/src/sliders.c b/sflphone-gtk/src/sliders.c index bd5ab25b8bf2ef9becffcd24f5a8bc5c63eeef49..1d1c9a54312140989a90590cf9dd5fcb825a85dc 100644 --- a/sflphone-gtk/src/sliders.c +++ b/sflphone-gtk/src/sliders.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -98,12 +98,6 @@ mute_cb( GtkWidget *widget, gchar* device ) update_icons (dev); } -/** This function updates the sliders without sending the value to the server. - * This behavior prevents an infinite loop when receiving an updated volume from - * the server. - * @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 newval) { diff --git a/sflphone-gtk/src/sliders.h b/sflphone-gtk/src/sliders.h index 5a6622a293d90f2e85740c7bdbbf7413c576f66e..1e517cb9763ceace5265519a6e68c3a4b5ac1685 100644 --- a/sflphone-gtk/src/sliders.h +++ b/sflphone-gtk/src/sliders.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -24,10 +24,22 @@ /** @file sliders.h * @brief Volume sliders at the bottom of the main window. */ -GtkWidget * create_mic_slider(); +/** + * Build the sliders widget + * @param device Mic or speaker + * @return GtkWidget* The slider + */ GtkWidget * create_slider(const gchar * device); + +/** + * This function updates the sliders without sending the value to the server. + * This behavior prevents an infinite loop when receiving an updated volume from + * the server. + * @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); #endif diff --git a/sflphone-gtk/src/statusicon.c b/sflphone-gtk/src/statusicon.c index 01b1eb82776de16c5cbb97762508f600a1abae45..b43bfce38be898678b1624e251e791a544e009f9 100644 --- a/sflphone-gtk/src/statusicon.c +++ b/sflphone-gtk/src/statusicon.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/sflphone-gtk/src/statusicon.h b/sflphone-gtk/src/statusicon.h index b3f6ba7d15ad5280e6c57b52d00fb5bbbad12ad1..da0c53426d197e2201f35ccb25add7cb39aaaaf3 100644 --- a/sflphone-gtk/src/statusicon.h +++ b/sflphone-gtk/src/statusicon.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 @@ -20,18 +21,49 @@ #ifndef __STATUSICON_H__ #define __STATUSICON_H__ -#define MINIMIZED TRUE #include <gtk/gtk.h> -/** @file statusicon.h - * @brief The status icon. - */ +#include <sflphone_const.h> +/** + * @file statusicon.h + * @brief The status icon in the system tray. + */ +/** + * Create the status icon + */ void show_status_icon(); + +/** + * Set the menu active + */ void status_icon_unminimize(); + +/** + * Tells if the main window if minimized or not + * @return gboolean TRUE if the main window is minimized + * FALSE otherwise + */ gboolean main_widget_minimized(); + +/** + * Change the menu status + * @param state TRUE if the main window is minimized + * FALSE otherwise + */ void set_minimized( gboolean state ); + +/** + * Make the system tray icon blink on incoming call + * @return active TRUE to make it blink + * FALSE to make it stop + */ void status_tray_icon_blink( gboolean active ); + +/** + * Accessor + * @return GtkStatusIcon* The status icon + */ GtkStatusIcon* get_status_icon( void ); #endif diff --git a/src/Makefile.am b/src/Makefile.am index 98e0a07fb4adc3f2f050e49b39bd65833c8ef386..a64dc124321d666697ed4d339f881096eb82b7db 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,6 +44,7 @@ sflphoned_CXXFLAGS = -DPREFIX=\"$(prefix)\" -DPROGSHAREDIR=\"${datadir}/sflphone sflphoned_LDADD = ./libsflphone.la $(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) $(IAX_LIBS) $(EXOSIP_LIBS) $(ALSAFLAG) AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libs $(libccext2_CFLAGS) $(libccgnu2_CFLAGS) $(IAX_CFLAGS) $(USER_INCLUDES) $(libdbuscpp_CFLAGS) \ -DCODECS_DIR=\""$(sflcodecdir)"\" + -DENABLE_TRACE # libsflphone_la_LDFLAGS= -version-info 0:1:0 diff --git a/src/account.h b/src/account.h index 2f2c5123268e2e35ae0b8422dba592871dba2019..af0a20d7e425d344be641ec49c3b837c03845c73 100644 --- a/src/account.h +++ b/src/account.h @@ -27,38 +27,56 @@ class VoIPLink; +/** + * @file account.h + * @brief Interface to protocol account (SIPAccount, IAXAccount) + * It can be enable on loading or activate after. + * It contains account, configuration, VoIP Link and Calls (inside the VoIPLink) + */ + typedef std::string AccountID; + #define AccountNULL "" +/** Account type: SIP / IAX2 are supported */ #define CONFIG_ACCOUNT_TYPE "Account.type" +/** Tells if account is enable or not */ #define CONFIG_ACCOUNT_ENABLE "Account.enable" -//#define CONFIG_ACCOUNT_AUTO_REGISTER "Account.autoregister" +/** Account alias */ #define CONFIG_ACCOUNT_ALIAS "Account.alias" - +/** IAX paramater : full name */ #define IAX_FULL_NAME "IAX.fullName" +/** IAX paramater : host name */ #define IAX_HOST "IAX.host" +/** IAX paramater : user name */ #define IAX_USER "IAX.user" +/** IAX paramater : password */ #define IAX_PASS "IAX.pass" - +/** SIP parameter : full name */ #define SIP_FULL_NAME "SIP.fullName" +/** SIP parameter : user name */ #define SIP_USER_PART "SIP.userPart" +/** SIP parameter : authorization name */ #define SIP_AUTH_NAME "SIP.username" +/** SIP parameter : password */ #define SIP_PASSWORD "SIP.password" +/** SIP parameter : host name */ #define SIP_HOST_PART "SIP.hostPart" +/** SIP parameter : proxy address */ #define SIP_PROXY "SIP.proxy" +/** SIP parameter : stun server address */ #define SIP_STUN_SERVER "STUN.server" +/** SIP parameter : tells if stun is used or not */ #define SIP_USE_STUN "STUN.enable" +/** SIP parameter : stun port */ #define SIP_STUN_PORT "STUN.port" -/** - * Class account is an interface to protocol account (SIPAccount, IAXAccount) - * It can be enable on loading or activate after. - * It contains account, configuration, VoIP Link and Calls (inside the VoIPLink) - * @author Yan Morin - */ class Account{ public: Account(const AccountID& accountID); - + + /** + * Virtual destructor + */ virtual ~Account(); /** @@ -74,35 +92,32 @@ class Account{ /** * Get the voiplink pointer - * @return the pointer or 0 + * @return VoIPLink* the pointer or 0 */ inline VoIPLink* getVoIPLink() { return _link; } /** * Register the underlying VoIPLink. Launch the event listener. - * * This should update the getRegistrationState() return value. - * - * @return false is an error occurs */ virtual void registerVoIPLink() = 0; /** * Unregister the underlying VoIPLink. Stop the event listener. - * * This should update the getRegistrationState() return value. - * - * @return false is an error occurs */ virtual void unregisterVoIPLink() = 0; /** - * Tell if the account is enable or not. See doc for _enabled. + * Tell if the account is enable or not. + * @return true if enabled + * false otherwise */ bool isEnabled() { return _enabled; } /** - * Return registration state of underlying VoIPLink + * Get the registration state of the specified link + * @return RegistrationState The registration state of underlying VoIPLink */ VoIPLink::RegistrationState getRegistrationState() { return _link->getRegistrationState(); } @@ -136,9 +151,7 @@ protected: /** * Tells if the link is enabled, active. - * * This implies the link will be initialized on startup. - * * Modified by the configuration (key: ENABLED) */ bool _enabled; diff --git a/src/accountcreator.h b/src/accountcreator.h index 01215077c2ec20f9576bcbc42262b6e1f876509a..c91b3f7220567779cffa54505ce38209a19bbce6 100644 --- a/src/accountcreator.h +++ b/src/accountcreator.h @@ -25,8 +25,8 @@ class Account; /** - * AccountCreator create Protocol-specific Account - * @author Yan Morin <yan.morin@gmail.com> + * @file accountcreator.h + * @brief Create protocol-specific account */ class AccountCreator{ public: diff --git a/src/audio/audiodevice.h b/src/audio/audiodevice.h index fb29ebf276f4304556991ffcb21ef384c42c9328..acdfee46368c8f9d187a6d82556600ad4ef8dabb 100644 --- a/src/audio/audiodevice.h +++ b/src/audio/audiodevice.h @@ -26,7 +26,8 @@ #define AUDIODEVICERATE 8000 /** - * Container device for attribute storage + * @file audiodevice.c + * @brief Container device for attribute storage * Have almost only get/set method */ class AudioDevice { diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp index 0b357382001a8bea9b22c903d793430ab0c837ea..ff13e4f9c566082804bbfee7751873cd63f8c4fc 100644 --- a/src/audio/audiolayer.cpp +++ b/src/audio/audiolayer.cpp @@ -313,7 +313,7 @@ AudioLayer::open_device(std::string pcm_p, std::string pcm_c, int flag) _debugAlsa("Opening capture device %s\n", pcm_c.c_str()); if(err = snd_pcm_open(&_CaptureHandle, pcm_c.c_str(), SND_PCM_STREAM_CAPTURE, 0) < 0){ _debugAlsa("Error while opening capture device %s\n", pcm_c.c_str()); - setErrorMessage( ERROR_ALSA_CAPTURE_DEVICE ); + setErrorMessage( ALSA_CAPTURE_DEVICE ); return false; } @@ -343,7 +343,7 @@ AudioLayer::open_device(std::string pcm_p, std::string pcm_c, int flag) _debugAlsa(" Opening playback device %s\n", pcm_p.c_str()); if(err = snd_pcm_open(&_PlaybackHandle, pcm_p.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) < 0){ _debugAlsa("Error while opening playback device %s\n", pcm_c.c_str()); - setErrorMessage( ERROR_ALSA_PLAYBACK_DEVICE ); + setErrorMessage( ALSA_PLAYBACK_DEVICE ); return false; } if( err = snd_pcm_hw_params_malloc( &hwParams ) < 0 ) { diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h index 97b1ff83107a347edb9a9115fe5a3171aa240f02..18426aa57af21daf3008ee15b9f0bea541fdc8b6 100644 --- a/src/audio/audiolayer.h +++ b/src/audio/audiolayer.h @@ -48,7 +48,7 @@ class AudioLayer { AudioLayer(ManagerImpl* manager); ~AudioLayer(void); - /* + /** * Check if no devices are opened, otherwise close them. * Then open the specified devices by calling the private functions open_device * @param indexIn The number of the card choosen for capture @@ -63,49 +63,49 @@ class AudioLayer { */ bool openDevice(int, int, int, int, int, std::string); - /* + /** * Start the capture stream and prepare the playback stream. * The playback starts accordingly to its threshold * ALSA Library API */ void startStream(void); - /* + /** * Stop the playback and capture streams. * Drops the pending frames and put the capture and playback handles to PREPARED state * ALSA Library API */ void stopStream(void); - /* + /** * Check if the playback is running * @return true if the state of the playback handle equals SND_PCM_STATE_RUNNING * false otherwise */ bool isPlaybackActive( void ); - /* + /** * Check if the capture is running * @return true if the state of the capture handle equals SND_PCM_STATE_RUNNING * false otherwise */ bool isCaptureActive( void ); - /* + /** * Check if both capture and playback are running * @return true if capture and playback are running * false otherwise */ bool isStreamActive(void); - /* + /** * Check if both capture and playback are stopped * @return true if capture and playback are stopped * false otherwise */ bool isStreamStopped(void); - /* + /** * Send samples to the audio device. * @params buffer The buffer containing the data to be played ( voice and DTMF ) * @params toCopy The number of samples, in bytes @@ -113,7 +113,7 @@ class AudioLayer { */ int playSamples(void* buffer, int toCopy, bool isTalking); - /* + /** * Send a chunk of data to the hardware buffer to start the playback * Copy data in the urgent buffer. * @params buffer The buffer containing the data to be played ( ringtones ) @@ -122,13 +122,13 @@ class AudioLayer { */ int putUrgent(void* buffer, int toCopy); - /* + /** * Query the capture device for number of bytes available in the hardware ring buffer * @return int The number of bytes available */ int canGetMic(); - /* + /** * Get data from the capture device * @param buffer The buffer for data * @param toCopy The number of bytes to get @@ -136,7 +136,7 @@ class AudioLayer { */ int getMic(void * buffer, int toCopy); - /* + /** * Concatenate two strings. Used to build a valid pcm device name. * @param plugin the alsa PCM name * @param card the sound card number @@ -145,7 +145,7 @@ class AudioLayer { */ std::string buildDeviceTopo( std::string plugin, int card, int subdevice ); - /* + /** * Scan the sound card available on the system * @param flag To indicate whether we are looking for capture devices or playback devices * SFL_PCM_CAPTURE @@ -160,41 +160,41 @@ class AudioLayer { void setErrorMessage(const int& error) { _errorMessage = error; } int getErrorMessage() { return _errorMessage; } - /* + /** * Get the index of the audio card for capture * @return _indexIn The index of the card used for capture * 0 for the first available card on the system, 1 ... */ int getIndexIn() { return _indexIn; } - /* + /** * Get the index of the audio card for playback * @return _indexOut The index of the card used for playback * 0 for the first available card on the system, 1 ... */ int getIndexOut() { return _indexOut; } - /* + /** * Get the sample rate of the audio layer * @return unsigned int The sample rate * default: 44100 HZ */ unsigned int getSampleRate() { return _sampleRate; } - /* + /** * Get the frame size of the audio layer * @return unsigned int The frame size * default: 20 ms */ unsigned int getFrameSize() { return _frameSize; } - /* + /** * Get the current audio plugin. * @return std::string The name of the audio plugin */ std::string getAudioPlugin( void ) { return _audioPlugin; } std::ofstream _fstream; - /* + /** * Get the current state. Conversation or not * @return bool true if playSamples has been called * false otherwise @@ -211,36 +211,36 @@ class AudioLayer { private: - /* + /** * Drop the pending frames and close the capture device * ALSA Library API */ void closeCaptureStream( void ); - /* + /** * Drop the pending frames and close the playback device * ALSA Library API */ void closePlaybackStream( void ); - /* + /** * Fill the alsa internal ring buffer with chunks of data */ void fillHWBuffer( void) ; - /* + /** * Callback used for asynchronous playback. * Called when a certain amount of data is written ot the device */ static void AlsaCallBack( snd_async_handler_t* ); - /* + /** * Callback used for asynchronous playback. * Write tones buffer to the alsa internal ring buffer. */ void playTones( void ); - /* + /** * Open the specified device. * ALSA Library API * @param pcm_p The string name for the playback device @@ -254,7 +254,7 @@ class AudioLayer { */ bool open_device( std::string pcm_p, std::string pcm_c, int flag); - /* + /** * Copy a data buffer in the internal ring buffer * ALSA Library API * @param buffer The data to be copied @@ -263,7 +263,7 @@ class AudioLayer { */ int write( void* buffer, int length); - /* + /** * Read data from the internal ring buffer * ALSA Library API * @param buffer The buffer to stock the read data @@ -272,7 +272,7 @@ class AudioLayer { */ int read( void* buffer, int toCopy); - /* + /** * Recover from XRUN state for capture * ALSA Library API */ @@ -281,7 +281,7 @@ class AudioLayer { ManagerImpl* _manager; // augment coupling, reduce indirect access - /* + /** * Handles to manipulate capture and playback streams * ALSA Library API */ @@ -289,26 +289,26 @@ class AudioLayer { snd_pcm_t* _CaptureHandle; snd_pcm_uframes_t _periodSize; - /* + /** * Handle on asynchronous event */ snd_async_handler_t *_AsyncHandler; - /* + /** * Urgent ring buffer used for ringtones */ RingBuffer _urgentBuffer; void * adjustVolume( void * , int , int); - /* + /** * Determine if both endpoints hang up. * true if conversation is running * false otherwise */ bool _talk; - /* + /** * Enable to determine if the devices are opened or not * true if the devices are closed * false otherwise @@ -333,7 +333,7 @@ class AudioLayer { */ unsigned int _frameSize; - /* + /** * name of the alsa audio plugin used */ std::string _audioPlugin; diff --git a/src/audio/codecDescriptor.h b/src/audio/codecDescriptor.h index 8a8be6eddc3d3a5f86649ea4d9a020bfa81f5f24..fd5775fa8d52fb7392b60ca5753b4bfa2a9d009a 100644 --- a/src/audio/codecDescriptor.h +++ b/src/audio/codecDescriptor.h @@ -57,9 +57,9 @@ typedef enum { #include "codecs/audiocodec.h" -/* A codec is identified by its payload. A payload is associated with a name. */ +/** A codec is identified by its payload. A payload is associated with a name. */ typedef std::map<AudioCodecType, std::string> CodecMap; -/* The struct to reflect the order the user wants to use the codecs */ +/** The struct to reflect the order the user wants to use the codecs */ typedef std::vector<AudioCodecType> CodecOrder; typedef std::pair<AudioCodec* , void*> CodecHandlePointer; @@ -73,7 +73,7 @@ public: CodecDescriptor(); ~CodecDescriptor(); - /* + /** * Accessor to data structures */ CodecsMap& getCodecsMap() { return _CodecsMap; } @@ -87,7 +87,7 @@ public: */ std::string getCodecName(AudioCodecType payload); - /* + /** * Get the codec object associated with the payload * @param payload The payload looked for * @return AudioCodec* A pointer on a AudioCodec object @@ -148,7 +148,7 @@ public: */ int getSampleRate(AudioCodecType payload); - /* + /** * Get the number of channels * @param payload The payload of the codec * @return int Number of channels @@ -163,17 +163,17 @@ public: std::string getDescription( std::string ); - /* + /** * Get the number of codecs loaded in dynamic memory */ int getCodecsNumber( void ) { return _nbCodecs; } - /* + /** * Unreferences the codecs loaded in memory */ void deleteHandlePointer( void ); - /* + /** * Get the first element of the CodecsMap struct. * i.e the one with the lowest payload * @return AudioCodec The pointer on the codec object @@ -182,27 +182,27 @@ public: private: - /* + /** * Scan the installation directory ( --prefix configure option ) * And load the dynamic library * @return std::vector<AudioCodec*> The list of the codec object successfully loaded in memory */ std::vector<AudioCodec *> scanCodecDirectory( void ); - /* + /** * Load a codec * @param std::string The path of the shared ( dynamic ) library. * @return AudioCodec* the pointer of the object loaded. */ AudioCodec* loadCodec( std::string ); - /* + /** * Unload a codec * @param CodecHandlePointer The map containing the pointer on the object and the pointer on the handle function */ void unloadCodec( CodecHandlePointer ); - /* + /** * Check if the files found in searched directories seems valid * @param std::string The name of the file * @return true if the file name begins with libcodec_ and ends with .so @@ -210,7 +210,7 @@ private: */ bool seemsValid( std::string ); - /* + /** * Check if the codecs shared library has already been scanned during the session * Useful not to load twice the same codec saved in the different directory * @param std::string The complete name of the shared directory ( without the path ) @@ -219,7 +219,7 @@ private: */ bool alreadyInCache( std::string ); - /* + /** * Check if the audiocodec object has been successfully created * @param payload The payload of the codec * @return true if the audiocodec has been created @@ -227,27 +227,27 @@ private: */ bool isCodecLoaded( int payload ); - /* + /** * Map the payload of a codec and the object associated ( AudioCodec * ) */ CodecsMap _CodecsMap; - /* + /** * Vector containing the order of the codecs */ CodecOrder _codecOrder; - /* + /** * Vector containing the complete name of the codec shared library scanned */ std::vector<std::string> _Cache; - /* + /** * Number of codecs loaded */ int _nbCodecs; - /* + /** * Vector containing pairs * Pair between pointer on function handle and pointer on audiocodec object */ diff --git a/src/audio/codecs/audiocodec.h b/src/audio/codecs/audiocodec.h index 5604efe64ff94d204e8f159eeec43178a66aa7cb..378e52a5e757b353fd70d717b23fd26205055692 100644 --- a/src/audio/codecs/audiocodec.h +++ b/src/audio/codecs/audiocodec.h @@ -16,7 +16,9 @@ protected: /** Number of channel 1 = mono, 2 = stereo */ unsigned int _channel; + /** Bitrate */ double _bitrate; + /** Bandwidth */ double _bandwidth; private: @@ -38,9 +40,15 @@ public: virtual ~AudioCodec() { } /** + * Decode an input buffer and fill the output buffer with the decoded data * @return the number of bytes decoded */ virtual int codecDecode(short *, unsigned char *, unsigned int) = 0; + + /** + * Encode an input buffer and fill the output buffer with the encoded data + * @return the number of bytes encoded + */ virtual int codecEncode(unsigned char *, short *, unsigned int) = 0; diff --git a/src/call.h b/src/call.h index 0b3b7c9b5dbbdb8d771d85ef5bd1d1336348288c..63b2de4443d93d6a89350e1e7768f597dc1c6380 100644 --- a/src/call.h +++ b/src/call.h @@ -24,35 +24,35 @@ #include <cc++/thread.h> // for mutex #include "audio/codecDescriptor.h" +/* + * @file call.h + * @brief A call is the base class for protocol-based calls + */ + typedef std::string CallID; -/** - * A call is the base class for protocol-based calls - * - * @author Yan Morin <yan.morin@gmail.com> - */ class Call{ -public: - /** - * This determines if the call originated from the local user (Outgoing) - * or from some remote peer (Incoming). - */ - enum CallType {Incoming, Outgoing}; - - /** - * Tell where we're at with the call. The call gets Connected when we know - * from the other end what happened with out call. A call can be 'Connected' - * even if the call state is Busy, Refused, or Error. - * - * Audio should be transmitted when ConnectionState = Connected AND - * CallState = Active. - */ - enum ConnectionState {Disconnected, Trying, Progressing, Ringing, Connected}; - - /** - * The Call State. - */ - enum CallState {Inactive, Active, Hold, Busy, Refused, Error}; + public: + /** + * This determines if the call originated from the local user (Outgoing) + * or from some remote peer (Incoming). + */ + enum CallType {Incoming, Outgoing}; + + /** + * Tell where we're at with the call. The call gets Connected when we know + * from the other end what happened with out call. A call can be 'Connected' + * even if the call state is Busy, Refused, or Error. + * + * Audio should be transmitted when ConnectionState = Connected AND + * CallState = Active. + */ + enum ConnectionState {Disconnected, Trying, Progressing, Ringing, Connected}; + + /** + * The Call State. + */ + enum CallState {Inactive, Active, Hold, Busy, Refused, Error}; /** * Constructor of a call @@ -74,103 +74,166 @@ public: * @param number peer number */ void setPeerNumber(const std::string& number) { _peerNumber = number; } + + /** + * Get the peer number (destination on outgoing) + * not protected by mutex (when created) + * @return std::string The peer number + */ const std::string& getPeerNumber() { return _peerNumber; } /** * Set the peer name (caller in ingoing) * not protected by mutex (when created) - * @param number peer number + * @param name The peer name */ void setPeerName(const std::string& name) { _peerName = name; } + + /** + * Get the peer name (caller in ingoing) + * not protected by mutex (when created) + * @return std::string The peer name + */ const std::string& getPeerName() { return _peerName; } /** * Tell if the call is incoming + * @return true if yes + * false otherwise */ bool isIncoming() { return (_type == Incoming) ? true : false; } /** * Set the connection state of the call (protected by mutex) + * @param state The connection state */ void setConnectionState(ConnectionState state); + /** - * get the connection state of the call (protected by mutex) + * Get the connection state of the call (protected by mutex) + * @return ConnectionState The connection state */ ConnectionState getConnectionState(); /** * Set the state of the call (protected by mutex) + * @param state The call state */ void setState(CallState state); + /** - * get the call state of the call (protected by mutex) + * Get the call state of the call (protected by mutex) + * @return CallState The call state */ CallState getState(); /** * Set the audio start boolean (protected by mutex) * @param start true if we start the audio + * false otherwise */ void setAudioStart(bool start); /** * Tell if the audio is started (protected by mutex) * @return true if it's already started + * false otherwise */ bool isAudioStarted(); // AUDIO - /** Set internal codec Map: initialization only, not protected */ + /** + * Set internal codec Map: initialization only, not protected + * @param map The codec map + */ void setCodecMap(const CodecDescriptor& map) { _codecMap = map; } + + /** + * Get internal codec Map: initialization only, not protected + * @return CodecDescriptor The codec map + */ CodecDescriptor& getCodecMap(); - /** Set my IP [not protected] */ + /** + * Set my IP [not protected] + * @param ip The local IP address + */ void setLocalIp(const std::string& ip) { _localIPAddress = ip; } - /** Set local audio port, as seen by me [not protected] */ + /** + * Set local audio port, as seen by me [not protected] + * @param port The local audio port + */ void setLocalAudioPort(unsigned int port) { _localAudioPort = port;} - /** Set the audio port that remote will see. */ + /** + * Set the audio port that remote will see. + * @param port The external audio port + */ void setLocalExternAudioPort(unsigned int port) { _localExternalAudioPort = port; } - /** Return the audio port seen by the remote side. */ + /** + * Return the audio port seen by the remote side. + * @return unsigned int The external audio port + */ unsigned int getLocalExternAudioPort() { return _localExternalAudioPort; } - /** Return my IP [mutex protected] */ + /** + * Return my IP [mutex protected] + * @return std::string The local IP + */ const std::string& getLocalIp(); - - /** Return port used locally (for my machine) [mutex protected] */ + + /** + * Return port used locally (for my machine) [mutex protected] + * @return unsigned int The local audio port + */ unsigned int getLocalAudioPort(); - - /** Return audio port at destination [mutex protected] */ + + /** + * Return audio port at destination [mutex protected] + * @return unsigned int The remote audio port + */ unsigned int getRemoteAudioPort(); - /** Return IP of destination [mutex protected] */ + /** + * Return IP of destination [mutex protected] + * @return const std:string The remote IP address + */ const std::string& getRemoteIp(); - /** Return audio codec [mutex protected] */ + /** + * Return audio codec [mutex protected] + * @return AudioCodecType The payload of the codec + */ AudioCodecType getAudioCodec(); - - -protected: + protected: /** Protect every attribute that can be changed by two threads */ ost::Mutex _callMutex; - /** Set remote's IP addr. [not protected] */ + /** + * Set remote's IP addr. [not protected] + * @param ip The remote IP address + */ void setRemoteIP(const std::string& ip) { _remoteIPAddress = ip; } - /** Set remote's audio port. [not protected] */ + /** + * Set remote's audio port. [not protected] + * @param port The remote audio port + */ void setRemoteAudioPort(unsigned int port) { _remoteAudioPort = port; } - /** Set the audio codec used. [not protected] */ + /** + * Set the audio codec used. [not protected] + * @param audioCodec The payload of the codec + */ void setAudioCodec(AudioCodecType audioCodec) { _audioCodec = audioCodec; } /** Codec Map */ CodecDescriptor _codecMap; /** Codec pointer */ - //AudioCodec* _audioCodec; AudioCodecType _audioCodec; bool _audioStarted; @@ -193,7 +256,7 @@ protected: unsigned int _remoteAudioPort; -private: + private: /** Unique ID of the call */ CallID _id; diff --git a/src/dbus/callmanager.cpp b/src/dbus/callmanager.cpp index 064f87f400cc2b4a1afcc8994a5e68f8c0ca0c1d..9152b558ab016533ec4238704ac299d2c4283325 100644 --- a/src/dbus/callmanager.cpp +++ b/src/dbus/callmanager.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify diff --git a/src/dbus/callmanager.h b/src/dbus/callmanager.h index ccabd95f6793236fddf7d5310edc81d49a2c76fd..ae74f857a356c507164d92a8529ddbbbcab60282 100644 --- a/src/dbus/callmanager.h +++ b/src/dbus/callmanager.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/src/dbus/configurationmanager-glue.h b/src/dbus/configurationmanager-glue.h index 8d555ec660f82f989169982f8da6d249ce97f895..a038f85c4a9702ccfe444ec35e497fffb35bdd53 100644 --- a/src/dbus/configurationmanager-glue.h +++ b/src/dbus/configurationmanager-glue.h @@ -25,8 +25,7 @@ public: register_method(ConfigurationManager, addAccount, _addAccount_stub); register_method(ConfigurationManager, removeAccount, _removeAccount_stub); register_method(ConfigurationManager, getAccountList, _getAccountList_stub); - register_method(ConfigurationManager, getDefaultAccount, _getDefaultAccount_stub); - register_method(ConfigurationManager, setDefaultAccount, _setDefaultAccount_stub); + register_method(ConfigurationManager, sendRegister, _sendRegister_stub); register_method(ConfigurationManager, getToneLocaleList, _getToneLocaleList_stub); register_method(ConfigurationManager, getVersion, _getVersion_stub); register_method(ConfigurationManager, getRingtoneList, _getRingtoneList_stub); @@ -52,6 +51,12 @@ public: register_method(ConfigurationManager, getAudioDeviceIndex, _getAudioDeviceIndex_stub); register_method(ConfigurationManager, getCurrentAudioOutputPlugin, _getCurrentAudioOutputPlugin_stub); register_method(ConfigurationManager, isIax2Enabled, _isIax2Enabled_stub); + register_method(ConfigurationManager, getDialpad, _getDialpad_stub); + register_method(ConfigurationManager, setDialpad, _setDialpad_stub); + register_method(ConfigurationManager, startHidden, _startHidden_stub); + register_method(ConfigurationManager, isStartHidden, _isStartHidden_stub); + register_method(ConfigurationManager, popupMode, _popupMode_stub); + register_method(ConfigurationManager, switchPopupMode, _switchPopupMode_stub); } ::DBus::IntrospectedInterface* const introspect() const @@ -83,14 +88,10 @@ public: { "list", "as", false }, { 0, 0, 0 } }; - static ::DBus::IntrospectedArgument getDefaultAccount_args[] = - { - { "accountID", "s", false }, - { 0, 0, 0 } - }; - static ::DBus::IntrospectedArgument setDefaultAccount_args[] = + static ::DBus::IntrospectedArgument sendRegister_args[] = { { "accountID", "s", true }, + { "expire", "i", true }, { 0, 0, 0 } }; static ::DBus::IntrospectedArgument getToneLocaleList_args[] = @@ -219,6 +220,33 @@ public: { "res", "i", false }, { 0, 0, 0 } }; + static ::DBus::IntrospectedArgument getDialpad_args[] = + { + { "state", "i", false }, + { 0, 0, 0 } + }; + static ::DBus::IntrospectedArgument setDialpad_args[] = + { + { 0, 0, 0 } + }; + static ::DBus::IntrospectedArgument startHidden_args[] = + { + { 0, 0, 0 } + }; + static ::DBus::IntrospectedArgument isStartHidden_args[] = + { + { "state", "i", false }, + { 0, 0, 0 } + }; + static ::DBus::IntrospectedArgument popupMode_args[] = + { + { "state", "i", false }, + { 0, 0, 0 } + }; + static ::DBus::IntrospectedArgument switchPopupMode_args[] = + { + { 0, 0, 0 } + }; static ::DBus::IntrospectedArgument parametersChanged_args[] = { { "list", "a{ss}", false }, @@ -240,8 +268,7 @@ public: { "addAccount", addAccount_args }, { "removeAccount", removeAccount_args }, { "getAccountList", getAccountList_args }, - { "getDefaultAccount", getDefaultAccount_args }, - { "setDefaultAccount", setDefaultAccount_args }, + { "sendRegister", sendRegister_args }, { "getToneLocaleList", getToneLocaleList_args }, { "getVersion", getVersion_args }, { "getRingtoneList", getRingtoneList_args }, @@ -267,6 +294,12 @@ public: { "getAudioDeviceIndex", getAudioDeviceIndex_args }, { "getCurrentAudioOutputPlugin", getCurrentAudioOutputPlugin_args }, { "isIax2Enabled", isIax2Enabled_args }, + { "getDialpad", getDialpad_args }, + { "setDialpad", setDialpad_args }, + { "startHidden", startHidden_args }, + { "isStartHidden", isStartHidden_args }, + { "popupMode", popupMode_args }, + { "switchPopupMode", switchPopupMode_args }, { 0, 0 } }; static ::DBus::IntrospectedMethod ConfigurationManager_signals[] = @@ -306,8 +339,7 @@ public: virtual void addAccount( const std::map< ::DBus::String, ::DBus::String >& details ) = 0; virtual void removeAccount( const ::DBus::String& accoundID ) = 0; virtual std::vector< ::DBus::String > getAccountList( ) = 0; - virtual ::DBus::String getDefaultAccount( ) = 0; - virtual void setDefaultAccount( const ::DBus::String& accountID ) = 0; + virtual void sendRegister( const ::DBus::String& accountID, const ::DBus::Int32& expire ) = 0; virtual std::vector< ::DBus::String > getToneLocaleList( ) = 0; virtual ::DBus::String getVersion( ) = 0; virtual std::vector< ::DBus::String > getRingtoneList( ) = 0; @@ -333,6 +365,12 @@ public: virtual ::DBus::Int32 getAudioDeviceIndex( const ::DBus::String& name ) = 0; virtual ::DBus::String getCurrentAudioOutputPlugin( ) = 0; virtual ::DBus::Int32 isIax2Enabled( ) = 0; + virtual ::DBus::Int32 getDialpad( ) = 0; + virtual void setDialpad( ) = 0; + virtual void startHidden( ) = 0; + virtual ::DBus::Int32 isStartHidden( ) = 0; + virtual ::DBus::Int32 popupMode( ) = 0; + virtual void switchPopupMode( ) = 0; public: @@ -411,22 +449,13 @@ private: wi << argout1; return reply; } - ::DBus::Message _getDefaultAccount_stub( const ::DBus::CallMessage& call ) - { - ::DBus::MessageIter ri = call.reader(); - - ::DBus::String argout1 = getDefaultAccount(); - ::DBus::ReturnMessage reply(call); - ::DBus::MessageIter wi = reply.writer(); - wi << argout1; - return reply; - } - ::DBus::Message _setDefaultAccount_stub( const ::DBus::CallMessage& call ) + ::DBus::Message _sendRegister_stub( const ::DBus::CallMessage& call ) { ::DBus::MessageIter ri = call.reader(); ::DBus::String argin1; ri >> argin1; - setDefaultAccount(argin1); + ::DBus::Int32 argin2; ri >> argin2; + sendRegister(argin1, argin2); ::DBus::ReturnMessage reply(call); return reply; } @@ -674,6 +703,60 @@ private: wi << argout1; return reply; } + ::DBus::Message _getDialpad_stub( const ::DBus::CallMessage& call ) + { + ::DBus::MessageIter ri = call.reader(); + + ::DBus::Int32 argout1 = getDialpad(); + ::DBus::ReturnMessage reply(call); + ::DBus::MessageIter wi = reply.writer(); + wi << argout1; + return reply; + } + ::DBus::Message _setDialpad_stub( const ::DBus::CallMessage& call ) + { + ::DBus::MessageIter ri = call.reader(); + + setDialpad(); + ::DBus::ReturnMessage reply(call); + return reply; + } + ::DBus::Message _startHidden_stub( const ::DBus::CallMessage& call ) + { + ::DBus::MessageIter ri = call.reader(); + + startHidden(); + ::DBus::ReturnMessage reply(call); + return reply; + } + ::DBus::Message _isStartHidden_stub( const ::DBus::CallMessage& call ) + { + ::DBus::MessageIter ri = call.reader(); + + ::DBus::Int32 argout1 = isStartHidden(); + ::DBus::ReturnMessage reply(call); + ::DBus::MessageIter wi = reply.writer(); + wi << argout1; + return reply; + } + ::DBus::Message _popupMode_stub( const ::DBus::CallMessage& call ) + { + ::DBus::MessageIter ri = call.reader(); + + ::DBus::Int32 argout1 = popupMode(); + ::DBus::ReturnMessage reply(call); + ::DBus::MessageIter wi = reply.writer(); + wi << argout1; + return reply; + } + ::DBus::Message _switchPopupMode_stub( const ::DBus::CallMessage& call ) + { + ::DBus::MessageIter ri = call.reader(); + + switchPopupMode(); + ::DBus::ReturnMessage reply(call); + return reply; + } }; } } } diff --git a/src/dbus/configurationmanager-introspec.xml b/src/dbus/configurationmanager-introspec.xml index 17102cd009076e7ca318959a203e053c75fa440c..6ebaef5a3494ac99c2803d66dfa1ad9135b6a75c 100644 --- a/src/dbus/configurationmanager-introspec.xml +++ b/src/dbus/configurationmanager-introspec.xml @@ -25,14 +25,11 @@ <arg type="as" name="list" direction="out"/> </method> - <method name="getDefaultAccount"> - <arg type="s" name="accountID" direction="out"/> - </method> - - <method name="setDefaultAccount"> + <method name="sendRegister"> <arg type="s" name="accountID" direction="in"/> + <arg type="i" name="expire" direction="in"/> </method> - + <!-- /////////////////////// --> <!-- Various audio-related methods --> @@ -141,6 +138,27 @@ <arg type="i" name="res" direction="out"/> </method> + <method name="getDialpad"> + <arg type="i" name="state" direction="out"/> + </method> + + <method name="setDialpad"> + </method> + + <method name="startHidden"> + </method> + + <method name="isStartHidden"> + <arg type="i" name="state" direction="out"/> + </method> + + <method name="popupMode"> + <arg type="i" name="state" direction="out"/> + </method> + + <method name="switchPopupMode"> + </method> + <!-- ///////////////////////////// --> <signal name="parametersChanged"> <arg type="a{ss}" name="list" direction="out"/> diff --git a/src/dbus/configurationmanager.cpp b/src/dbus/configurationmanager.cpp index b974f9b84d6280924c03fdb9308d8d1e2c335024..d5bb6c5ef2fce4f7bd4b287870b4d35a7e0b34d4 100644 --- a/src/dbus/configurationmanager.cpp +++ b/src/dbus/configurationmanager.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@savoirfairelinux.com> * @@ -48,6 +48,12 @@ ConfigurationManager::setAccountDetails( const ::DBus::String& accountID, Manager::instance().setAccountDetails(accountID, details); } + void +ConfigurationManager::sendRegister( const ::DBus::String& accountID, const ::DBus::Int32& expire ) +{ + Manager::instance().sendRegister(accountID, expire); +} + void ConfigurationManager::addAccount( const std::map< ::DBus::String, ::DBus::String >& details ) { @@ -211,24 +217,6 @@ ConfigurationManager::getRecordDeviceList( ) { _debug("ConfigurationManager::getRecordDeviceList received\n"); -} - - ::DBus::String -ConfigurationManager::getDefaultAccount( ) -{ - _debug("ConfigurationManager::getDefaultAccount received\n"); - return Manager::instance().getDefaultAccount(); -} - -/* - * used to set a default account - */ - void -ConfigurationManager::setDefaultAccount( const ::DBus::String& accountID ) -{ - _debug("ConfigurationManager::setDefaultAccount received\n"); - Manager::instance().setDefaultAccount(accountID); - } ::DBus::Int32 @@ -261,3 +249,41 @@ ConfigurationManager::setRingtoneChoice( const ::DBus::String& tone ) Manager::instance().setRingtoneChoice( tone ); } +::DBus::Int32 +ConfigurationManager::getDialpad( void ) +{ + return Manager::instance().getDialpad( ); +} + +void +ConfigurationManager::setDialpad( void ) +{ + Manager::instance().setDialpad( ); +} + +void +ConfigurationManager::startHidden( void ) +{ + Manager::instance().startHidden( ); +} + +::DBus::Int32 +ConfigurationManager::isStartHidden( void ) +{ + return Manager::instance().isStartHidden( ); +} + +void +ConfigurationManager::switchPopupMode( void ) +{ + Manager::instance().switchPopupMode( ); +} + +::DBus::Int32 +ConfigurationManager::popupMode( void ) +{ + return Manager::instance().popupMode( ); +} + + + diff --git a/src/dbus/configurationmanager.h b/src/dbus/configurationmanager.h index 5cba2dcfbc049aa540e609b682b66589c76665a4..212374bfc50c6fa84dd7c48e52ce45622d44e1c9 100644 --- a/src/dbus/configurationmanager.h +++ b/src/dbus/configurationmanager.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com> * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@savoirfairelinux.com> @@ -44,8 +44,7 @@ public: void addAccount( const std::map< ::DBus::String, ::DBus::String >& details ); void removeAccount( const ::DBus::String& accoundID ); std::vector< ::DBus::String > getAccountList( ); - ::DBus::String getDefaultAccount( ); - void setDefaultAccount( const ::DBus::String& accountID ); + void sendRegister( const ::DBus::String& accoundID , const ::DBus::Int32& expire ); std::vector< ::DBus::String > getCodecList( ); std::vector< ::DBus::String > getCodecDetails( const ::DBus::Int32& payload ); @@ -76,6 +75,13 @@ public: void ringtoneEnabled( void ); ::DBus::String getRingtoneChoice( void ); void setRingtoneChoice( const ::DBus::String& tone ); + ::DBus::Int32 getDialpad( void ); + void setDialpad( void ); + ::DBus::Int32 isStartHidden( void ); + void startHidden( void ); + ::DBus::Int32 popupMode( void ); + void switchPopupMode( void ); + }; diff --git a/src/dbus/dbusmanager.h b/src/dbus/dbusmanager.h index d1f4f411c4ca241695ef045efbd61fc84cf68d5a..e8beb6cebf623256d2a33ffaacf4539e0ea87be8 100644 --- a/src/dbus/dbusmanager.h +++ b/src/dbus/dbusmanager.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/src/dbus/dbusmanagerimpl.cpp b/src/dbus/dbusmanagerimpl.cpp index f829d89aca739d2b9f7a91dc67ad89207a682b4b..6972e8faa627070e320f3bfc4bec3e4b28dac55d 100644 --- a/src/dbus/dbusmanagerimpl.cpp +++ b/src/dbus/dbusmanagerimpl.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/src/dbus/dbusmanagerimpl.h b/src/dbus/dbusmanagerimpl.h index 37aa35e73b5fd4251e6117353dca02adfb7d8720..9addfeb32b7b2c9cb8d4f2766c33f5e2d8d292b9 100644 --- a/src/dbus/dbusmanagerimpl.h +++ b/src/dbus/dbusmanagerimpl.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/src/dbus/instance.cpp b/src/dbus/instance.cpp index c075cc04f8b3f4bc68cfdb975a2503fb16ec69b4..c573817129bb40d1e80f5caf3240c23911782ce7 100644 --- a/src/dbus/instance.cpp +++ b/src/dbus/instance.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/src/dbus/instance.h b/src/dbus/instance.h index 8339308f263a369c00d2d399c4f7e77b2d216930..d11ba3a045f385f52b21b28ad5b610a9ef6bd842 100644 --- a/src/dbus/instance.h +++ b/src/dbus/instance.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Savoir-Faire Linux inc. - * Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info> + * Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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 diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 05ba81bdda9ae208a927f7a2a713681ced8baa26..aabdd755bad9d6b1452e806ff0f86c297dbc8f4a 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -25,6 +25,7 @@ EventThread::EventThread (VoIPLink* link) : Thread () { _linkthread = link; setCancel(cancelDeferred); + stopIt = false; } EventThread::~EventThread (void) @@ -38,9 +39,27 @@ EventThread::~EventThread (void) void EventThread::run (void) { + //stopIt = false; while(!testCancel()) { _linkthread->getEvent(); } } +void +EventThread::stop( void ) +{ + stopIt = true; +} +void +EventThread::startLoop( void ) +{ + stopIt = false; + //start(); +} + +bool +EventThread::isStopped( void ) +{ + return stopIt; +} diff --git a/src/eventthread.h b/src/eventthread.h index cb812b2c3123948aea9aa7f82ec0145ffcce2ca2..21f43a897ac87fc9c639d7c9089acd98bff49a93 100644 --- a/src/eventthread.h +++ b/src/eventthread.h @@ -24,9 +24,12 @@ #include <cc++/thread.h> class VoIPLink; + /** - * General thread to listen events continuously + * @file eventthread.h + * @brief General thread to listen events continuously */ + class EventThread : public ost::Thread { public: /** @@ -36,10 +39,14 @@ public: ~EventThread (void); virtual void run (); + virtual void stop(); + virtual void startLoop(); + bool isStopped(); private: /** VoIPLink is the object being called by getEvents() method */ VoIPLink* _linkthread; + bool stopIt; }; #endif // __EVENT_THREAD_H__ diff --git a/src/global.h b/src/global.h index 3e6a9103575ce28cf43086e793ecc9b2bded37e6..4fe6ded002f067f7a10b8ca91888c56b412b0a58 100644 --- a/src/global.h +++ b/src/global.h @@ -61,59 +61,61 @@ typedef short int16; #define _debugAlsa(...) #endif -#define SFLPHONED_VERSION "0.8.2" +#define SFLPHONED_VERSION "0.8.2" /** Version number */ #define SFLPHONED_VERSIONNUM 0x000802 -#define PROGNAME "sflphoned" -#define PROGNAME_GLOBAL "sflphone" -#define PROGDIR "sflphone" -#define RINGDIR "ringtones" -#define CODECDIR "codecs" +#define PROGNAME "sflphoned" /** Binary name */ +#define PROGNAME_GLOBAL "sflphone" /** Program name */ +#define PROGDIR "sflphone" /** Program directory */ +#define RINGDIR "ringtones" /** Ringtones directory */ +#define CODECDIR "codecs" /** Codecs directory */ #define _(arg) arg #define MONO 1 #define CHANNELS 2 #define SIZEBUF 1024*1024 -#define ALSA_DFT_CARD_ID 0 - -#define PCM_HW "hw" -#define PCM_PLUGHW "plughw" -#define PCM_PULSE "pulse" -#define PCM_FRONT "plug:front" -#define PCM_DEFAULT "default" -#define PCM_DMIX "plug:dmix" -#define PCM_SURROUND40 "plug:surround40" -#define PCM_SURROUND41 "plug:surround41" -#define PCM_SURROUND50 "plug:surround50" -#define PCM_SURROUND51 "plug:surround51" -#define PCM_SURROUND71 "plug:surround71" -#define PCM_IEC958 "plug:iec958" - -#define SFL_CODEC_VALID_PREFIX "libcodec_" -#define SFL_CODEC_VALID_EXTEN ".so" -#define CURRENT_DIR "." -#define PARENT_DIR ".." - -#define SFL_PCM_BOTH 0x0021 -#define SFL_PCM_PLAYBACK 0x0022 -#define SFL_PCM_CAPTURE 0x0023 +#define ALSA_DFT_CARD_ID 0 /** Index of the default soundcard */ + +#define PCM_HW "hw" /** Alsa plugin hardware */ +#define PCM_PLUGHW "plughw" /** Alsa plugin */ +#define PCM_PULSE "pulse" /** Alsa plugin for pulse audio */ +#define PCM_FRONT "plug:front" /** Alsa plugin: front PCM */ +#define PCM_DEFAULT "default" /** Default ALSA plugin */ +#define PCM_DMIX "plug:dmix" /** Alsa plugin for software mixing */ +#define PCM_SURROUND40 "plug:surround40" /** Alsa plugin: surround40 */ +#define PCM_SURROUND41 "plug:surround41" /** Alsa plugin: surround41 */ +#define PCM_SURROUND50 "plug:surround50" /** Alsa plugin: surround50 */ +#define PCM_SURROUND51 "plug:surround51" /** Alsa plugin: surround51 */ +#define PCM_SURROUND71 "plug:surround71" /** Alsa plugin: surround71 */ + +#define SFL_CODEC_VALID_PREFIX "libcodec_" /** Valid prefix for codecs shared library */ +#define SFL_CODEC_VALID_EXTEN ".so" /** Valid extension for codecs shared library */ +#define CURRENT_DIR "." /** Current directory */ +#define PARENT_DIR ".." /** Parent directory */ + +#define SFL_PCM_BOTH 0x0021 /** To open both playback and capture devices */ +#define SFL_PCM_PLAYBACK 0x0022 /** To open playback device only */ +#define SFL_PCM_CAPTURE 0x0023 /** To open capture device only */ #ifdef USE_IAX -#define IAX2_ENABLED true +#define IAX2_ENABLED true /** IAX2 support */ #else -#define IAX2_ENABLED false +#define IAX2_ENABLED false /** IAX2 support */ #endif -#define GSM_STRING_DESCRIPTION "gsm" -#define SPEEX_STRING_DESCRIPTION "speex" -#define ILBC_STRING_DESCRIPTION "ilbc" -#define RINGTONE_ENABLED 1 - -#define ERROR_ALSA_CAPTURE_DEVICE 0 -#define ERROR_ALSA_PLAYBACK_DEVICE 1 -//#define ERROR_ALSA_OPENING_CAPTURE_DEVICE 0 -//#define ERROR_ALSA_OPENING_CAPTURE_DEVICE 0 -//#define ERROR_ALSA_OPENING_CAPTURE_DEVICE 0 +#define GSM_STRING_DESCRIPTION "gsm" /** GSM codec string description */ +#define SPEEX_STRING_DESCRIPTION "speex" /** SPEEX codec string description */ +#define ILBC_STRING_DESCRIPTION "ilbc" /** Ilbc codec string description */ +#define RINGTONE_ENABLED 1 /** Custom ringtone enable or not */ +#define DISPLAY_DIALPAD 1 /** Display dialpad or not */ +#define START_HIDDEN 1 /** SFlphone starts hidden at start-up or not */ +#define WINDOW_POPUP 1 /** Popup mode */ + +// Error codes for error handling +#define NO_ERROR 0x0000 /** No error - Everything alright */ +#define ALSA_CAPTURE_DEVICE 0x0001 /** Error while opening capture device */ +#define ALSA_PLAYBACK_DEVICE 0x0010 /** Error while opening playback device */ +#define NETWORK_UNREACHABLE 0x0011 /** Network unreachable */ #endif // __GLOBAL_H__ diff --git a/src/iaxaccount.h b/src/iaxaccount.h index 6e6472395ebb8e49942f9556fd569a3fe8b7699f..2cdfb6232ad0dc338cdb708d69bfdbb7ed34b7f2 100644 --- a/src/iaxaccount.h +++ b/src/iaxaccount.h @@ -24,8 +24,8 @@ /** - * An IAX Account specify IAX specific functions and objects (IAXCall/IAXVoIPLink) - * @author Yan Morin <yan.morin@gmail.com> + * @file: iaxaccount.h + * @brief: an IAX Account specify IAX specific functions and objects (IAXCall/IAXVoIPLink) */ class IAXAccount : public Account { @@ -34,9 +34,19 @@ public: ~IAXAccount(); - /** Actually unuseful, since config loading is done in init() */ + /** + * Actually unuseful, since config loading is done in init() + */ void loadConfig(); + + /** + * Register an account + */ void registerVoIPLink(); + + /** + * Unregister an account + */ void unregisterVoIPLink(); private: diff --git a/src/iaxcall.h b/src/iaxcall.h index 2c6d612d867d8bfc6409e4a4b6108d90197a9089..ccfe8c41d5dd3e69b9ba9ef1089cf52c0b225a8f 100644 --- a/src/iaxcall.h +++ b/src/iaxcall.h @@ -25,42 +25,53 @@ #include <iax/frame.h> /** - * IAXCall are IAX implementation of a normal Call - * @author Yan Morin <yan.morin@gmail.com> + * @file: iaxcall.h + * @brief: IAXCall are IAX implementation of a normal Call */ + class IAXCall : public Call { public: + /** + * Constructor + * @param id The unique ID of the call + * @param type The type of the call + */ IAXCall(const CallID& id, Call::CallType type); + /** + * Destructor + */ ~IAXCall(); - /** Get the session pointer or NULL */ + /** + * @return iax_session* The session pointer or NULL + */ struct iax_session* getSession() { return _session; } - /** Set the session pointer + /** + * Set the session pointer * @param session the session pointer to assign */ void setSession(struct iax_session* session) { _session = session; } /** - * Set format (one single bit - * + * Set format (one single bit) * This function sets the _audioCodec variable with the correct * codec. + * @param format The format representing the codec */ void setFormat(int format); /** * Get format for the voice codec used - * - * Bitmask for codecs defined in iax/frame.h + * @return int Bitmask for codecs defined in iax/frame.h */ int getFormat() { return _format; } /** - * Get the bitwise list of supported formats + * @return int The bitwise list of supported formats */ int getSupportedFormat(); @@ -75,7 +86,7 @@ public: * in this call context. * * @param needles The format(s) (bitwise) you are looking for to match - * @return The matching format, thus 0 if none matches + * @return int The matching format, thus 0 if none matches */ int getFirstMatchingFormat(int needles); diff --git a/src/iaxvoiplink.cpp b/src/iaxvoiplink.cpp index f28a33bc41ca707dc6ebc19f21a2c453b1b39ade..510ba7642f75e2b19daadb9a2376078d5ef5fefe 100644 --- a/src/iaxvoiplink.cpp +++ b/src/iaxvoiplink.cpp @@ -363,11 +363,9 @@ IAXVoIPLink::sendRegister() bool result = false; if (_host.empty()) { - Manager::instance().displayConfigError("Fill host field for IAX Account"); return false; } if (_user.empty()) { - Manager::instance().displayConfigError("Fill user field for IAX Account"); return false; } @@ -430,6 +428,7 @@ IAXVoIPLink::sendUnregister() _nextRefreshStamp = 0; + _debug("IAX2 send unregister\n"); setRegistrationState(Unregistered); return false; @@ -655,7 +654,6 @@ IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall* call) } call->setConnectionState(Call::Connected); call->setState(Call::Error); - Manager::instance().displayErrorText(id, "Failure"); Manager::instance().callFailure(id); removeCall(id); break; @@ -689,7 +687,6 @@ IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall* call) case IAX_EVENT_BUSY: call->setConnectionState(Call::Connected); call->setState(Call::Busy); - Manager::instance().displayErrorText(id, "Busy"); Manager::instance().callBusy(id); removeCall(id); break; @@ -817,7 +814,6 @@ IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, IAXCall* call) } - /** * Handle the registration process */ @@ -830,10 +826,7 @@ IAXVoIPLink::iaxHandleRegReply(iax_event* event) iax_destroy(_regSession); _mutexIAX.leaveMutex(); _regSession = NULL; - - setRegistrationState(Error, "Registration failed"); - //Manager::instance().registrationFailed(getAccountID()); - + setRegistrationState(ErrorAuth); } else if (event->etype == IAX_EVENT_REGACK) { /* Authentication succeeded */ @@ -845,14 +838,10 @@ IAXVoIPLink::iaxHandleRegReply(iax_event* event) // I mean, save the timestamp, so that we re-register again in the REFRESH time. // Defaults to 60, as per draft-guy-iax-03. _nextRefreshStamp = time(NULL) + (event->ies.refresh ? event->ies.refresh : 60); - setRegistrationState(Registered); - //Manager::instance().registrationSucceed(getAccountID()); } } - - void IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event) { diff --git a/src/iaxvoiplink.h b/src/iaxvoiplink.h index 05f1a08735d3fe9350bd0a426f63f98db690ede2..9e2acd6c8d4948ee1533ef217ecfe22c3b3a736c 100644 --- a/src/iaxvoiplink.h +++ b/src/iaxvoiplink.h @@ -2,6 +2,7 @@ * Copyright (C) 2006-2007 Savoir-Faire Linux inc. * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> * Author: Yan Morin <yan.morin@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 @@ -27,189 +28,285 @@ #include "audio/codecDescriptor.h" -/** @todo Remove this fstream/iostream stuff */ -#include <fstream> // fstream + iostream for _fstream debugging... -#include <iostream> - - class EventThread; class IAXCall; class AudioCodec; class AudioLayer; - /** - * VoIPLink contains a thread that listen to external events + * @file iaxvoiplink.h + * @brief VoIPLink contains a thread that listen to external events * and contains IAX Call related functions - * @author Yan Morin <yan.morin@gmail.com> */ + class IAXVoIPLink : public VoIPLink { -public: + public: + + /** + * Constructor + * @param accountID The account containing the voip link + */ IAXVoIPLink(const AccountID& accountID); + /** + * Destructor + */ ~IAXVoIPLink(); - void getEvent(void); - bool init (void); - bool checkNetwork (void) { return false; } - void terminate (void); - - /** - * Send out registration - * - * @return The new registration state (are we registered ?) - */ - bool sendRegister (void); - - /** - * Destroy registration session - * - * @todo Send an IAX_COMMAND_REGREL to force unregistration upstream. - * Urgency: low - * - * @return bool If we're registered upstream - */ - bool sendUnregister (void); - - Call* newOutgoingCall(const CallID& id, const std::string& toUrl); - bool answer(const CallID& id); - - bool hangup(const CallID& id); - bool cancel(const CallID& id) { return false; } - bool onhold(const CallID& id); - bool offhold(const CallID& id); - bool transfer(const CallID& id, const std::string& to); - bool refuse (const CallID& id); - bool carryingDTMFdigits(const CallID& id, char code); - bool sendMessage(const std::string& to, const std::string& body) { return false; } - bool isContactPresenceSupported() { return false; } - -public: // iaxvoiplink only - void setHost(const std::string& host) { _host = host; } - void setUser(const std::string& user) { _user = user; } - void setPass(const std::string& pass) { _pass = pass; } - -private: - /** - * Get IAX Call from an id - * @param id CallId - * @return IAXCall pointer or 0 - */ - IAXCall* getIAXCall(const CallID& id); - - /** - * Delete every call - */ - void terminateIAXCall(); - - /** - * Find a iaxcall by iax session number - * @param session an iax_session valid pointer - * @return iaxcall or 0 if not found - */ - IAXCall* iaxFindCallBySession(struct iax_session* session); - - /** - * Handle IAX Event for a call - * @param event An iax_event pointer - * @param call An IAXCall pointer - */ - void iaxHandleCallEvent(iax_event* event, IAXCall* call); - - /** - * Handle the VOICE events specifically - * @param event The iax_event containing the IAX_EVENT_VOICE - * @param call The associated IAXCall - */ - void iaxHandleVoiceEvent(iax_event* event, IAXCall* call); - - /** - * Handle IAX Registration Reply event - * @param event An iax_event pointer - */ - void iaxHandleRegReply(iax_event* event); - - /** - * Handle IAX pre-call setup-related events - * @param event An iax_event pointer - */ - void iaxHandlePrecallEvent(iax_event* event); - - /** - * Work out the audio data from Microphone to IAX2 channel - */ - void sendAudioFromMic(void); - - /** - * Send an outgoing call invite to iax - * @param call An IAXCall pointer - */ - bool iaxOutgoingInvite(IAXCall* call); - - - /** - * Convert CodecMap to IAX format using IAX constants - * @return `format` ready to go into iax_* calls - */ - int iaxCodecMapToFormat(IAXCall* call); - - /** Threading object */ - EventThread* _evThread; - - /** registration session : 0 if not register */ - struct iax_session* _regSession; - - /** IAX Host */ - std::string _host; - - /** IAX User */ - std::string _user; - - /** IAX Password */ - std::string _pass; - - /** IAX full name */ - std::string _fullName; - - /** Timestamp of when we should refresh the registration up with - * the registrar. Values can be: EPOCH timestamp, 0 if we want no registration, 1 - * to force a registration. */ - int _nextRefreshStamp; - - /** Mutex for iax_ calls, since we're the only one dealing with the incorporated - * iax_stuff inside this class. */ - ost::Mutex _mutexIAX; - - /** Connection to audio card/device */ - AudioLayer* audiolayer; - - /** When we receive data, we decode it inside this buffer */ - int16* _receiveDataDecoded; - /** When we send data, we encode it inside this buffer*/ - unsigned char* _sendDataEncoded; - - /** After that we send the data inside this buffer if there is a format conversion or rate conversion. */ - /* Also use for getting mic-ringbuffer data */ - SFLDataFormat* _dataAudioLayer; - - /** Buffer for 8000hz samples in conversion */ - float32* _floatBuffer8000; - /** Buffer for 48000hz samples in conversion */ - float32* _floatBuffer48000; - - /** Buffer for 8000hz samples for mic conversion */ - int16* _intBuffer8000; - - /** libsamplerate converter for incoming voice */ - SRC_STATE* _src_state_spkr; - - /** libsamplerate converter for outgoing voice */ - SRC_STATE* _src_state_mic; - - /** libsamplerate error */ - int _src_err; + /** + * Listen to events sent by the call manager ( asterisk, etc .. ) + */ + void getEvent(void); + + /** + * Init the voip link + * @return true if successful + * false otherwise + */ + bool init (void); + + /** + * Check if a local IP can be found + * @return true if pingable + * false otherwise + */ + bool checkNetwork (void) { return false; } + + /** + * Terminate a voip link by clearing the call list + */ + void terminate (void); + + /** + * Send out registration + * @return bool The new registration state (are we registered ?) + */ + bool sendRegister (void); + + /** + * Destroy registration session + * @todo Send an IAX_COMMAND_REGREL to force unregistration upstream. + * Urgency: low + * @return bool true if we're registered upstream + * false otherwise + */ + bool sendUnregister (void); + + /** + * Create a new outgoing call + * @param id The ID of the call + * @param toUrl The address to call + * @return Call* A pointer on the call + */ + Call* newOutgoingCall(const CallID& id, const std::string& toUrl); + + /** + * Answer a call + * @param id The ID of the call + * @return bool true on success + * false otherwise + */ + bool answer(const CallID& id); + + /** + * Hangup a call + * @param id The ID of the call + * @return bool true on success + * false otherwise + */ + bool hangup(const CallID& id); + + /** + * Cancel a call + * @param id The ID of the call + * @return bool true on success + * false otherwise + */ + bool cancel(const CallID& id) { return false; } + + /** + * Put a call on hold + * @param id The ID of the call + * @return bool true on success + * false otherwise + */ + bool onhold(const CallID& id); + + /** + * Put a call off hold + * @param id The ID of the call + * @return bool true on success + * false otherwise + */ + bool offhold(const CallID& id); + + /** + * Transfer a call + * @param id The ID of the call + * @param to The recipient of the transfer + * @return bool true on success + * false otherwise + */ + bool transfer(const CallID& id, const std::string& to); + + /** + * Refuse a call + * @param id The ID of the call + * @return bool true on success + * false otherwise + */ + bool refuse (const CallID& id); + + /** + * Send DTMF + * @param id The ID of the call + * @param code The code of the DTMF + * @return bool true on success + * false otherwise + */ + bool carryingDTMFdigits(const CallID& id, char code); + + bool sendMessage(const std::string& to, const std::string& body) { return false; } + + bool isContactPresenceSupported() { return false; } + + public: // iaxvoiplink only + /** + * @param host Set the host name + */ + void setHost(const std::string& host) { _host = host; } + + /** + * @param user Set the user name + */ + void setUser(const std::string& user) { _user = user; } + + /** + * @param pass Set the password + */ + void setPass(const std::string& pass) { _pass = pass; } + + private: + /** + * Get IAX Call from an id + * @param id CallId + * @return IAXCall pointer or 0 + */ + IAXCall* getIAXCall(const CallID& id); + + /** + * Delete every call + */ + void terminateIAXCall(); + + /** + * Find a iaxcall by iax session number + * @param session an iax_session valid pointer + * @return iaxcall or 0 if not found + */ + IAXCall* iaxFindCallBySession(struct iax_session* session); + + /** + * Handle IAX Event for a call + * @param event An iax_event pointer + * @param call An IAXCall pointer + */ + void iaxHandleCallEvent(iax_event* event, IAXCall* call); + + /** + * Handle the VOICE events specifically + * @param event The iax_event containing the IAX_EVENT_VOICE + * @param call The associated IAXCall + */ + void iaxHandleVoiceEvent(iax_event* event, IAXCall* call); + + /** + * Handle IAX Registration Reply event + * @param event An iax_event pointer + */ + void iaxHandleRegReply(iax_event* event); + + /** + * Handle IAX pre-call setup-related events + * @param event An iax_event pointer + */ + void iaxHandlePrecallEvent(iax_event* event); + + /** + * Work out the audio data from Microphone to IAX2 channel + */ + void sendAudioFromMic(void); + + /** + * Send an outgoing call invite to iax + * @param call An IAXCall pointer + */ + bool iaxOutgoingInvite(IAXCall* call); + + + /** + * Convert CodecMap to IAX format using IAX constants + * @return `format` ready to go into iax_* calls + */ + int iaxCodecMapToFormat(IAXCall* call); + + /** Threading object */ + EventThread* _evThread; + + /** registration session : 0 if not register */ + struct iax_session* _regSession; + + /** IAX Host */ + std::string _host; + + /** IAX User */ + std::string _user; + + /** IAX Password */ + std::string _pass; + + /** IAX full name */ + std::string _fullName; + + /** Timestamp of when we should refresh the registration up with + * the registrar. Values can be: EPOCH timestamp, 0 if we want no registration, 1 + * to force a registration. */ + int _nextRefreshStamp; + + /** Mutex for iax_ calls, since we're the only one dealing with the incorporated + * iax_stuff inside this class. */ + ost::Mutex _mutexIAX; + + /** Connection to audio card/device */ + AudioLayer* audiolayer; + + /** When we receive data, we decode it inside this buffer */ + int16* _receiveDataDecoded; + /** When we send data, we encode it inside this buffer*/ + unsigned char* _sendDataEncoded; + + /** After that we send the data inside this buffer if there is a format conversion or rate conversion. */ + /* Also use for getting mic-ringbuffer data */ + SFLDataFormat* _dataAudioLayer; + + /** Buffer for 8000hz samples in conversion */ + float32* _floatBuffer8000; + /** Buffer for 48000hz samples in conversion */ + float32* _floatBuffer48000; + + /** Buffer for 8000hz samples for mic conversion */ + int16* _intBuffer8000; + + /** libsamplerate converter for incoming voice */ + SRC_STATE* _src_state_spkr; + + /** libsamplerate converter for outgoing voice */ + SRC_STATE* _src_state_mic; + + /** libsamplerate error */ + int _src_err; }; diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp index c587538cf891d7601334ca402b2a648ec6de3c9a..a112f240c90061c638cd23a32ee1b02d2824d779 100644 --- a/src/managerimpl.cpp +++ b/src/managerimpl.cpp @@ -77,7 +77,6 @@ ManagerImpl::ManagerImpl (void) _dtmfKey = 0; _spkr_volume = 0; // Initialize after by init() -> initVolume() _mic_volume = 0; // Initialize after by init() -> initVolume() - _mic_volume_before_mute = 0; // Call _nbIncomingWaitingCall=0; @@ -229,10 +228,6 @@ ManagerImpl::outgoingCall(const std::string& accountid, const CallID& id, const ManagerImpl::answerCall(const CallID& id) { stopTone(false); - /*if (hasCurrentCall()) - { - onHoldCall(getCurrentCallId()); - }*/ AccountID accountid = getAccountFromCall( id ); if (accountid == AccountNULL) { _debug("Answering Call: Call doesn't exists\n"); @@ -245,9 +240,6 @@ ManagerImpl::answerCall(const CallID& id) return false; } - //Place current call on hold if it isn't - - // if it was waiting, it's waiting no more if (_dbus) _dbus->getCallManager()->callStateChanged(id, "CURRENT"); removeWaitingCall(id); @@ -283,7 +275,6 @@ ManagerImpl::hangupCall(const CallID& id) removeCallAccount(id); switchCall(""); - return returnValue; } @@ -351,13 +342,7 @@ ManagerImpl::offHoldCall(const CallID& id) bool returnValue = getAccountLink(accountid)->offhold(id); if (_dbus) _dbus->getCallManager()->callStateChanged(id, "UNHOLD"); switchCall(id); - if (returnValue) { - try { - //getAudioDriver()->startStream(); - } catch(...) { - _debugException("! Manager Off hold could not start audio stream"); - } - } + return returnValue; } @@ -376,26 +361,9 @@ ManagerImpl::transferCall(const CallID& id, const std::string& to) removeCallAccount(id); if (_dbus) _dbus->getCallManager()->callStateChanged(id, "HUNGUP"); switchCall(""); - - return returnValue; } -//THREAD=Main -void -ManagerImpl::mute() { - _mic_volume_before_mute = _mic_volume; - setMicVolume(0); -} - -//THREAD=Main -void -ManagerImpl::unmute() { - if ( _mic_volume == 0 ) { - setMicVolume(_mic_volume_before_mute); - } -} - //THREAD=Main : Call:Incoming bool ManagerImpl::refuseCall (const CallID& id) @@ -455,46 +423,6 @@ ManagerImpl::initRegisterAccounts() return true; } -//THREAD=Main -// Currently unused - bool -ManagerImpl::registerAccount(const AccountID& accountId) -{ - _debug("Register one VoIP Link\n"); - - // right now, we don't support two SIP account - // so we close everything before registring a new account - Account* account = getAccount(accountId); - if (account != 0) { - AccountMap::iterator iter = _accountMap.begin(); - while ( iter != _accountMap.end() ) { - if ( iter->second ) { - iter->second->unregisterVoIPLink(); - } - iter++; - } - // NOW - account->registerVoIPLink(); - account->loadContacts(); - account->publishPresence(PRESENCE_ONLINE); - account->subscribeContactsPresence(); - } - return true; -} - -//THREAD=Main -// Currently unused - bool -ManagerImpl::unregisterAccount(const AccountID& accountId) -{ - _debug("Unregister one VoIP Link\n"); - - if (accountExists( accountId ) ) { - getAccount(accountId)->unregisterVoIPLink(); - } - return true; -} - //THREAD=Main bool ManagerImpl::sendDtmf(const CallID& id, char code) @@ -567,15 +495,6 @@ ManagerImpl::playDtmf(char code, bool isTalking) // put the size in bytes... // so size * 1 channel (mono) * sizeof (bytes for the data) audiolayer->playSamples(_buf, size * sizeof(SFLDataFormat), isTalking); - //audiolayer->putUrgent(_buf, size * sizeof(SFLDataFormat)); - - // We activate the stream if it's not active yet. - //if (!audiolayer->isStreamActive()) { - //audiolayer->startStream(); - //} else { - //_debugAlsa("send dtmf - sleep\n"); - //audiolayer->sleep(pulselen); // in milliseconds - //} } returnValue = true; @@ -617,8 +536,6 @@ ManagerImpl::isWaitingCall(const CallID& id) { return true; } - - /////////////////////////////////////////////////////////////////////////////// // Management of event peer IP-phone //////////////////////////////////////////////////////////////////////////////// @@ -731,84 +648,49 @@ ManagerImpl::callFailure(const CallID& id) } //THREAD=VoIP - void -ManagerImpl::displayTextMessage(const CallID& id, const std::string& message) -{ - /*if(_gui) { - _gui->displayTextMessage(id, message); - }*/ -} - -//THREAD=VoIP - void -ManagerImpl::displayErrorText(const CallID& id, const std::string& message) -{ - /*if(_gui) { - _gui->displayErrorText(id, message); - } else { - std::cerr << message << std::endl; - }*/ -} - -//THREAD=VoIP - void -ManagerImpl::displayError (const std::string& error) + void +ManagerImpl::startVoiceMessageNotification(const AccountID& accountId, const std::string& nb_msg) { - /*if(_gui) { - _gui->displayError(error); - }*/ + if (_dbus) _dbus->getCallManager()->voiceMailNotify(accountId, atoi(nb_msg.c_str()) ); } //THREAD=VoIP void -ManagerImpl::displayStatus(const std::string& status) +ManagerImpl::registrationSucceed(const AccountID& accountid) { - /*if(_gui) { - _gui->displayStatus(status); - }*/ + Account* acc = getAccount(accountid); + if ( acc ) { + _debug("REGISTRATION SUCCEED\n"); + if (_dbus) _dbus->getConfigurationManager()->accountsChanged(); + } } //THREAD=VoIP void -ManagerImpl::displayConfigError (const std::string& message) -{ - /*if(_gui) { - _gui->displayConfigError(message); - }*/ -} - -//THREAD=VoIP - void -ManagerImpl::startVoiceMessageNotification(const AccountID& accountId, const std::string& nb_msg) +ManagerImpl::unregistrationSucceed(const AccountID& accountid) { - if (_dbus) _dbus->getCallManager()->voiceMailNotify(accountId, atoi(nb_msg.c_str()) ); + _debug("UNREGISTRATION SUCCEED\n"); + if (_dbus) _dbus->getConfigurationManager()->accountsChanged(); } -//THREAD=VoIP - void -ManagerImpl::stopVoiceMessageNotification(const AccountID& accountId) -{ - if (_dbus) _dbus->getCallManager()->voiceMailNotify(accountId, 0 ); -} - //THREAD=VoIP void -ManagerImpl::registrationSucceed(const AccountID& accountid) +ManagerImpl::registrationFailed(const AccountID& accountid) { Account* acc = getAccount(accountid); if ( acc ) { - //acc->setState(true); + _debug("REGISTRATION FAILED\n"); if (_dbus) _dbus->getConfigurationManager()->accountsChanged(); } } //THREAD=VoIP void -ManagerImpl::registrationFailed(const AccountID& accountid) +ManagerImpl::registrationTrying(const AccountID& accountid) { Account* acc = getAccount(accountid); if ( acc ) { - //acc->setState(false); + _debug("REGISTRATION TRYING\n"); if (_dbus) _dbus->getConfigurationManager()->accountsChanged(); } } @@ -904,7 +786,6 @@ ManagerImpl::ringback () { void ManagerImpl::ringtone() { - // int hasToPlayTone = getConfigInt(SIGNALISATION, PLAY_TONES); if( isRingtoneEnabled() ) { std::string ringchoice = getConfigString(AUDIO, RING_CHOICE); @@ -963,11 +844,6 @@ ManagerImpl::getTelephoneFile() } } - -/** - * Use Urgent Buffer - * By AudioRTP thread - */ void ManagerImpl::notificationIncomingCall(void) { @@ -1098,6 +974,9 @@ ManagerImpl::initConfigFile (void) fill_config_str(VOICEMAIL_NUM, DFT_VOICEMAIL); fill_config_int(CONFIG_ZEROCONF, CONFIG_ZEROCONF_DEFAULT_STR); fill_config_int(CONFIG_RINGTONE, YES_STR); + fill_config_int(CONFIG_DIALPAD, YES_STR); + fill_config_int(CONFIG_START, NO_STR); + fill_config_int(CONFIG_POPUP, YES_STR); // Loads config from ~/.sflphone/sflphonedrc or so.. if (createSettingsPath() == 1) { @@ -1146,7 +1025,7 @@ ManagerImpl::retrieveActiveCodecs() } void -ManagerImpl::setActiveCodecList(const std::vector<std::string>& list) +ManagerImpl::setActiveCodecList(const std::vector< ::DBus::String >& list) { _debug("Set active codecs list\n"); _codecDescriptorMap.saveActiveCodecs(list); @@ -1430,8 +1309,45 @@ ManagerImpl::setRingtoneChoice( const std::string& tone ) setConfig( AUDIO , RING_CHOICE , tone ); } +int +ManagerImpl::getDialpad( void ) +{ + return getConfigInt( PREFERENCES , CONFIG_DIALPAD ); +} + void -ManagerImpl::notifyErrClient( const int& errCode ) +ManagerImpl::setDialpad( void ) +{ + ( getConfigInt( PREFERENCES , CONFIG_DIALPAD ) == DISPLAY_DIALPAD )? setConfig(PREFERENCES , CONFIG_DIALPAD , NO_STR ) : setConfig( PREFERENCES , CONFIG_DIALPAD , YES_STR ); + +} + +void +ManagerImpl::startHidden( void ) +{ + ( getConfigInt( PREFERENCES , CONFIG_START ) == START_HIDDEN)? setConfig(PREFERENCES , CONFIG_START , NO_STR ) : setConfig( PREFERENCES , CONFIG_START , YES_STR ); +} + +int +ManagerImpl::isStartHidden( void ) +{ + return getConfigInt( PREFERENCES , CONFIG_START ); +} + +void +ManagerImpl::switchPopupMode( void ) +{ + ( getConfigInt( PREFERENCES , CONFIG_POPUP ) == WINDOW_POPUP)? setConfig(PREFERENCES , CONFIG_POPUP , NO_STR ) : setConfig( PREFERENCES , CONFIG_POPUP , YES_STR ); +} + +int +ManagerImpl::popupMode( void ) +{ + return getConfigInt( PREFERENCES , CONFIG_POPUP ); +} + +void +ManagerImpl::notifyErrClient( const ::DBus::Int32& errCode ) { if( _dbus ){ _debug("NOTIFY ERR NUMBER %i\n" , errCode); @@ -1620,20 +1536,6 @@ ManagerImpl::detachZeroconfEvents(Pattern::Observer& observer) return returnValue; } -/** - * Main Thread - * - * @todo When is this called ? Why this name 'getEvents' ? - */ -/** - * DEPRECATED - bool - ManagerImpl::getEvents() { - initRegisterAccounts(); - return true; - } - */ - // TODO: rewrite this /** * Main Thread @@ -1686,7 +1588,6 @@ ManagerImpl::getCallStatus(const std::string& sequenceId) tk.push_back(iter->second); tk.push_back(destination); tk.push_back(status); - //_gui->sendCallMessage(code, sequenceId, iter->first, tk); tk.clear(); iter++; @@ -1695,24 +1596,6 @@ ManagerImpl::getCallStatus(const std::string& sequenceId) return true; } -//THREAD=Main -/* Unused, Deprecated */ - bool -ManagerImpl::getConfigAll(const std::string& sequenceId) -{ - bool returnValue = false; - Conf::ConfigTreeIterator iter = _config.createIterator(); - TokenList tk = iter.begin(); - if (tk.size()) { - returnValue = true; - } - while (tk.size()) { - //_gui->sendMessage("100", sequenceId, tk); - tk = iter.next(); - } - return returnValue; -} - //THREAD=Main bool ManagerImpl::getConfig(const std::string& section, const std::string& name, TokenList& arg) @@ -1762,99 +1645,6 @@ ManagerImpl::setConfig(const std::string& section, const std::string& name, int return _config.setConfigTreeItem(section, name, valueStream.str()); } -//THREAD=Main - bool -ManagerImpl::getAudioDeviceList(const std::string& sequenceId, int ioDeviceMask) -{ - AudioLayer* audiolayer = getAudioDriver(); - if (audiolayer == 0) { return false; } - - bool returnValue = false; - - // TODO: test when there is an error on initializing... - TokenList tk; - AudioDevice* device = 0; - int nbDevice = audiolayer->getDeviceCount(); - /* - for (int index = 0; index < nbDevice; index++ ) { - device = audiolayer->getAudioDeviceInfo(index, ioDeviceMask); - if (device != 0) { - tk.clear(); - std::ostringstream str; str << index; tk.push_back(str.str()); - tk.push_back(device->getName()); - tk.push_back(device->getApiName()); - std::ostringstream rate; rate << (int)(device->getRate()); tk.push_back(rate.str()); - //_gui->sendMessage("100", sequenceId, tk); - - // don't forget to delete it after - delete device; device = 0; - } - }*/ - returnValue = true; - - std::ostringstream rate; - rate << "VARIABLE"; - tk.clear(); - tk.push_back(rate.str()); - //_gui->sendMessage("101", sequenceId, tk); - - return returnValue; -} - -//THREAD=Main - bool -ManagerImpl::getCountryTones(const std::string& sequenceId) -{ - // see ToneGenerator for the list... - sendCountryTone(sequenceId, 1, "North America"); - sendCountryTone(sequenceId, 2, "France"); - sendCountryTone(sequenceId, 3, "Australia"); - sendCountryTone(sequenceId, 4, "United Kingdom"); - sendCountryTone(sequenceId, 5, "Spain"); - sendCountryTone(sequenceId, 6, "Italy"); - sendCountryTone(sequenceId, 7, "Japan"); - - return true; -} - -//THREAD=Main -void -ManagerImpl::sendCountryTone(const std::string& sequenceId, int index, const std::string& name) { - TokenList tk; - std::ostringstream str; str << index; tk.push_back(str.str()); - tk.push_back(name); - //_gui->sendMessage("100", sequenceId, tk); -} - -//THREAD=Main -bool -ManagerImpl::getDirListing(const std::string& sequenceId, const std::string& path, int *nbFile) { - TokenList tk; - try { - ost::Dir dir(path.c_str()); - const char *cFileName = 0; - std::string fileName; - std::string filePathName; - while ( (cFileName=dir++) != 0 ) { - fileName = cFileName; - filePathName = path + DIR_SEPARATOR_STR + cFileName; - if (fileName.length() && fileName[0]!='.' && !ost::isDir(filePathName.c_str())) { - tk.clear(); - std::ostringstream str; - str << (*nbFile); - tk.push_back(str.str()); - tk.push_back(filePathName); - //_gui->sendMessage("100", sequenceId, tk); - (*nbFile)++; - } - } - return true; - } catch (...) { - // error to open file dir - return false; - } -} - std::vector< std::string > ManagerImpl::getAccountList() { @@ -1873,8 +1663,6 @@ ManagerImpl::getAccountList() return v; } - - std::map< std::string, std::string > ManagerImpl::getAccountDetails(const AccountID& accountID) { @@ -1890,12 +1678,6 @@ ManagerImpl::getAccountDetails(const AccountID& accountID) getConfigString(accountID, CONFIG_ACCOUNT_ALIAS) ) ); - /*a.insert( - std::pair<std::string, std::string>( - CONFIG_ACCOUNT_AUTO_REGISTER, - getConfigString(accountID, CONFIG_ACCOUNT_AUTO_REGISTER)== "1" ? "TRUE": "FALSE" - ) - );*/ a.insert( std::pair<std::string, std::string>( CONFIG_ACCOUNT_ENABLE, @@ -1906,9 +1688,12 @@ ManagerImpl::getAccountDetails(const AccountID& accountID) std::pair<std::string, std::string>( "Status", (state == VoIPLink::Registered ? "REGISTERED": - (state == VoIPLink::Unregistered ? "UNREGISTERED": - (state == VoIPLink::Trying ? "TRYING": - (state == VoIPLink::Error ? "ERROR": "ERROR")))) + (state == VoIPLink::Unregistered ? "UNREGISTERED": + (state == VoIPLink::Trying ? "TRYING": + (state == VoIPLink::ErrorAuth ? "ERROR_AUTH": + (state == VoIPLink::ErrorNetwork ? "ERROR_NETWORK": + (state == VoIPLink::ErrorHost ? "ERROR_HOST": + (state == VoIPLink::Error ? "ERROR": "ERROR"))))))) ) ); a.insert( @@ -2005,6 +1790,7 @@ ManagerImpl::getAccountDetails(const AccountID& accountID) ManagerImpl::setAccountDetails( const ::DBus::String& accountID, const std::map< ::DBus::String, ::DBus::String >& details ) { + std::string accountType = (*details.find(CONFIG_ACCOUNT_TYPE)).second; setConfig(accountID, CONFIG_ACCOUNT_ALIAS, (*details.find(CONFIG_ACCOUNT_ALIAS)).second); @@ -2035,31 +1821,39 @@ ManagerImpl::setAccountDetails( const ::DBus::String& accountID, } saveConfig(); - - /* - * register if it was just enabled, and we hadn't registered - * unregister if it was enabled/registered, and we want it closed - */ + Account* acc = getAccount(accountID); + acc->loadConfig(); + if (acc->isEnabled()){ + acc->unregisterVoIPLink(); + acc->registerVoIPLink();} + else + acc->unregisterVoIPLink(); + + // Update account details + if (_dbus) _dbus->getConfigurationManager()->accountsChanged(); +} +void +ManagerImpl::sendRegister( const ::DBus::String& accountID , bool expire ) +{ + // Update the active field + setConfig( accountID, CONFIG_ACCOUNT_ENABLE, expire ); + + Account* acc = getAccount(accountID); acc->loadConfig(); - if (acc->isEnabled()) { + // Test on the value freshly updated + if ( acc->isEnabled() ) { // Verify we aren't already registered, then register - if (acc->getRegistrationState() == VoIPLink::Unregistered) { + _debug("Send register for account %s\n" , accountID.c_str()); acc->registerVoIPLink(); - } } else { // Verify we are already registered, then unregister - if (acc->getRegistrationState() == VoIPLink::Registered) { + _debug("Send unregister for account %s\n" , accountID.c_str()); acc->unregisterVoIPLink(); - } } - - /** @todo Make the daemon use the new settings */ - if (_dbus) _dbus->getConfigurationManager()->accountsChanged(); } - void ManagerImpl::addAccount(const std::map< ::DBus::String, ::DBus::String >& details) { @@ -2106,93 +1900,10 @@ ManagerImpl::removeAccount(const AccountID& accountID) saveConfig(); + _debug("REMOVE ACCOUNT\n"); if (_dbus) _dbus->getConfigurationManager()->accountsChanged(); } - std::string -ManagerImpl::getDefaultAccount() -{ - - std::string id; - id = getConfigString(PREFERENCES, "DefaultAccount"); - _debug("Default Account = %s\n",id.c_str()); - return id; -} - - void -ManagerImpl::setDefaultAccount(const AccountID& accountID) -{ - // we write into the Preferences section the field Default - setConfig("Preferences", "DefaultAccount", accountID); -} - - - - -//THREAD=Main -/* - * Experimental... - */ -bool -ManagerImpl::setSwitch(const std::string& switchName, std::string& message) { - AudioLayer* audiolayer = 0; - if (switchName == "audiodriver" ) { - // hangup all call here - audiolayer = getAudioDriver(); - - int oldSampleRate = 0; - if (audiolayer) { oldSampleRate = audiolayer->getSampleRate(); } - - selectAudioDriver(); - audiolayer = getAudioDriver(); - - if (audiolayer) { - int error = audiolayer->getErrorMessage(); - int newSampleRate = audiolayer->getSampleRate(); - - if (error == -1) { - message = error; - return false; - } - - if (newSampleRate != oldSampleRate) { - _toneMutex.enterMutex(); - - _debug("Unload Telephone Tone\n"); - delete _telephoneTone; _telephoneTone = NULL; - _debug("Unload DTMF Key\n"); - delete _dtmfKey; _dtmfKey = NULL; - - _debug("Load Telephone Tone\n"); - std::string country = getConfigString(PREFERENCES, ZONE_TONE); - _telephoneTone = new TelephoneTone(country, newSampleRate); - - _debugInit("Loading DTMF key"); - _dtmfKey = new DTMF(newSampleRate); - - _toneMutex.leaveMutex(); - } - - message = _("Change with success"); - playDtmf('9', true); - //getAudioDriver()->sleep(300); // in milliseconds - playDtmf('1', true); - //getAudioDriver()->sleep(300); // in milliseconds - playDtmf('1', true); - return true; - } - } else if ( switchName == "echo" ) { - audiolayer = getAudioDriver(); - if (audiolayer) { - audiolayer->toggleEchoTesting(); - return true; - } - } - - - return false; -} - // ACCOUNT handling bool ManagerImpl::associateCallToAccount(const CallID& callID, const AccountID& accountID) @@ -2257,7 +1968,6 @@ ManagerImpl::loadAccountMap() std::string accountType; Account* tmpAccount; - // iter = std::string TokenList::iterator iter = sections.begin(); while(iter != sections.end()) { // Check if it starts with "Account:" (SIP and IAX pour le moment) @@ -2288,37 +1998,6 @@ ManagerImpl::loadAccountMap() iter++; } - - /* - // SIP Loading X account... - short nbAccountSIP = ACCOUNT_SIP_COUNT_DEFAULT; - for (short iAccountSIP = 0; iAccountSIP<nbAccountSIP; iAccountSIP++) { - std::ostringstream accountName; - accountName << "SIP" << iAccountSIP; - - tmpAccount = AccountCreator::createAccount(AccountCreator::SIP_ACCOUNT, accountName.str()); - if (tmpAccount!=0) { - _debugMid(" %s", accountName.str().data()); - _accountMap[accountName.str()] = tmpAccount; - nbAccount++; - } - } - - // IAX Loading X account... - short nbAccountIAX = ACCOUNT_IAX_COUNT_DEFAULT; - for (short iAccountIAX = 0; iAccountIAX<nbAccountIAX; iAccountIAX++) { - std::ostringstream accountName; - accountName << "IAX" << iAccountIAX; - tmpAccount = AccountCreator::createAccount(AccountCreator::IAX_ACCOUNT, accountName.str()); - if (tmpAccount!=0) { - _debugMid(" %s", accountName.str().data()); - _accountMap[accountName.str()] = tmpAccount; - nbAccount++; - } - } - _debugEnd("\n"); - */ - return nbAccount; } diff --git a/src/managerimpl.h b/src/managerimpl.h index 02936e96c6c34c7c9b01833ac81fda02fd3e9897..d2c2bb84b451a8bf80501d20e07622c2137f21c5 100644 --- a/src/managerimpl.h +++ b/src/managerimpl.h @@ -23,8 +23,6 @@ #ifndef __MANAGER_H__ #define __MANAGER_H__ -//#define TEST - #include <string> #include <vector> #include <set> @@ -44,8 +42,6 @@ #include "audio/dtmf.h" #include "audio/codecDescriptor.h" - - class AudioLayer; class CodecDescriptor; class GuiFramework; @@ -56,661 +52,893 @@ class VoIPLink; class DNSService; #endif -/** - * Define a type for a AccountMap container - */ +/** Define a type for a AccountMap container */ typedef std::map<AccountID, Account*> AccountMap; - -/** - * Define a type for a CallID to AccountID Map inside ManagerImpl - */ + +/** Define a type for a CallID to AccountID Map inside ManagerImpl */ typedef std::map<CallID, AccountID> CallAccountMap; -/** - * Define a type for CallID vector (waiting list, incoming not answered) - */ +/** Define a type for CallID vector (waiting list, incoming not answered) */ typedef std::set<CallID> CallIDSet; -/** - * To send multiple string - */ +/** To send multiple string */ typedef std::list<std::string> TokenList; -/** - * Manager (controller) of sflphone daemon - */ +/** Manager (controller) of sflphone daemon */ class ManagerImpl { -public: - ManagerImpl (void); - ~ManagerImpl (void); - - /** - * Initialisation of thread (sound) and map. - * - * Init a new VoIPLink, audio codec and audio driver - */ - void init (void); - - /** - * Terminate all thread (sound, link) and unload AccountMap - */ - void terminate (void); - - /** - * Set user interface manaager. - * @param man The DBUS interface implementation - */ - void setDBusManager (DBusManagerImpl* man) { _dbus = man; } - - /** - * Accessor to audiodriver. - * - * it's multi-thread and use mutex internally - */ - AudioLayer* getAudioDriver(void) const { return _audiodriver; } - - /** - * Get a descriptor map of codec available - */ - CodecDescriptor& getCodecDescriptorMap(void) {return _codecDescriptorMap;} - - /** - * Functions which occur with a user's action - */ - bool outgoingCall(const AccountID& accountId, const CallID& id, const std::string& to); - bool answerCall(const CallID& id); - bool hangupCall(const CallID& id); - bool cancelCall(const CallID& id); - bool onHoldCall(const CallID& id); - bool offHoldCall(const CallID& id); - bool transferCall(const CallID& id, const std::string& to); - void mute(); - void unmute(); - bool refuseCall(const CallID& id); - - /** Save config to file */ - bool saveConfig (void); - - /** - * Send registration information (shake hands) for a specific AccountID - * - * @param accountId Account to register - * @return true if sendRegister was called without failure, else return false - */ - bool registerAccount(const AccountID& accountId); - - /** - * Send unregistration for a specific account. If the protocol - * doesn't need to send anything, then the state of the account - * will be set to 'Unregistered', and related objects destroyed. - * - * @param accountId Account to unregister - * @return true if the unregister method is send correctly - */ - bool unregisterAccount(const AccountID& accountId); - - /** - * Send registration to all enabled accounts - * - * @return false if exosip or the network checking fails - */ - bool initRegisterAccounts(); - - /** - * True if we tried to register Once - */ - bool _hasTriedToRegister; - - - /** - * Undocumented - */ - bool sendTextMessage(const AccountID& accountId, const std::string& to, const std::string& message); - - /* - * Handle choice of the DTMF-send-way - * - * @param id: callid of the line. - * @param code: pressed key. - */ - bool sendDtmf(const CallID& id, char code); - bool playDtmf(char code, bool isTalking); - bool playTone (); - bool playToneWithMessage (); - void stopTone(bool stopAudio/*=true*/); - - // From links - /** - * When receiving a new incoming call, add it to the callaccount map - * and notify user - * @param call A call pointer - * @param accountid an account id - * @return true if the call was added correctly - */ - bool incomingCall(Call* call, const AccountID& accountId); - void peerAnsweredCall(const CallID& id); - void peerRingingCall(const CallID& id); - void peerHungupCall(const CallID& id); - void incomingMessage(const AccountID& accountId, const std::string& message); - - void displayTextMessage (const CallID& id, const std::string& message); - void displayErrorText (const CallID& id, const std::string& message); - void displayError(const std::string& error); - void displayStatus(const std::string& status); - void displayConfigError(const std::string& message); - - void startVoiceMessageNotification(const AccountID& accountId, const std::string& nb_msg); - void stopVoiceMessageNotification(const AccountID& accountId); - - /** Notify the user that registration succeeded */ - void registrationSucceed(const AccountID& accountId); - /** Notify the user that registration succeeded */ - void registrationFailed(const AccountID& accountId); - - // configuration function requests - - /** - * Start events thread. This function actually only calls the private - * initRegisterVoIPLink(). - * - * This function should definitively be renamed! - * - * @todo Receive account name (???) - * - * DEPRECATED - */ - //bool getEvents(); - - // - bool getZeroconf(const std::string& sequenceId); - bool attachZeroconfEvents(const std::string& sequenceId, Pattern::Observer& observer); - bool detachZeroconfEvents(Pattern::Observer& observer); - bool getCallStatus(const std::string& sequenceId); - - /** - * Get account list - * @return A list of accoundIDs - */ - std::vector< std::string > getAccountList(); - - /** - * Retrieve details about a given account - */ - std::map< std::string, std::string > getAccountDetails(const AccountID& accountID); - - /** - * Save the details of an existing account, given the account ID - * - * This will load the configuration map with the given data. - * It will also register/unregister links where the 'Enabled' switched. - */ - void setAccountDetails( const ::DBus::String& accountID, - const std::map< ::DBus::String, ::DBus::String >& details ); - - /** - * Add a new account, and give it a new account ID automatically - */ - void addAccount(const std::map< ::DBus::String, ::DBus::String >& details); - - /** - * Delete an existing account, unregister VoIPLink associated, and - * purge from configuration. - */ - void removeAccount(const AccountID& accountID); - - /* - * Get the default account - * @return The default account - */ - std::string getDefaultAccount(); - - - /** - * Get the list of codecs we supports, not ordered - * @return The list of the codecs - */ - std::vector< ::DBus::String > getCodecList( void ); - /** - * Get the info about one codec - * Name / CLock rate / bitrate / bandwidth - * @param payload The payload of the codec - * @return The information - */ - std::vector< ::DBus::String > getCodecDetails( const ::DBus::Int32& payload); - - /** - * Get a list of supported input audio plugin - * @return List of names - */ - std::vector< std::string> getInputAudioPluginList(void); - - /** - * Get a list of supported output audio plugin - * @return List of names - */ - std::vector< std::string> getOutputAudioPluginList(void); - - /** - * Set input audio plugin - */ - void setInputAudioPlugin(const std::string& audioPlugin); - - /** - * Set output audio plugin - */ - void setOutputAudioPlugin(const std::string& audioPlugin); - - /** - * Get list of supported audio output device - */ - std::vector<std::string> getAudioOutputDeviceList(void); - - /** - * Set audio output device - */ - void setAudioOutputDevice(const int index); - - /** - * Get list of supported audio input device - */ - std::vector<std::string> getAudioInputDeviceList(void); - - /** - * Set audio input device - */ - void setAudioInputDevice(const int index); - - /** - * Get string array representing integer indexes of output and input device - */ - std::vector<std::string> getCurrentAudioDevicesIndex(); - - /** - * Get index of an audio device - */ - int getAudioDeviceIndex( const std::string name ); - - /* - * Get current alsa plugin - */ - std::string getCurrentAudioOutputPlugin( void ); - - /** - * Convert a list of payload in a special format, readable by the server. - * Required format: payloads separated with one slash. - * @return std::string The serializabled string - */ - std::string serialize(std::vector<std::string> v); - - int isIax2Enabled( void ); - int isRingtoneEnabled( void ); - void ringtoneEnabled( void ); - std::string getRingtoneChoice( void ); - void setRingtoneChoice( const std::string& ); - /** - * Inverse of serialize - */ - std::vector<std::string> retrieveActiveCodecs( void ); - - /** - * Get and set the list of the active codecs - */ - std::vector< ::DBus::String > getActiveCodecList( void ); - void setActiveCodecList( const std::vector< ::DBus::String >& list); - - /* - * Set an account as default - * @param The ID of the account we want to set as default - */ - void setDefaultAccount(const AccountID& accountID); - - /* - * Notify the client that an error occured - * @param errMsg The error message that should popup on the client side - */ - void notifyErrClient( const ::DBus::Int32& errCode ); - - bool getConfigAll(const std::string& sequenceId); - bool getConfig(const std::string& section, const std::string& name, TokenList& arg); - bool setConfig(const std::string& section, const std::string& name, const std::string& value); - bool setConfig(const std::string& section, const std::string& name, int value); - bool getConfigList(const std::string& sequenceId, const std::string& name); - void selectAudioDriver(void); - - /** - * Set Audio Driver with switchName == audiodriver - * @param sflphoned internal parameter to change - * @param message to return to the user - * @return true if everything is ok - */ - bool setSwitch(const std::string& switchName, std::string& message); - - // configuration function for extern - // throw an Conf::ConfigTreeItemException if not found - /** Get a int from the config tree */ - int getConfigInt(const std::string& section, const std::string& name); - /** Get a string from the config tree */ - std::string getConfigString(const std::string& section, const std::string& name); - - /** - * Handle audio sounds heard by a caller while they wait for their - * connection to a called party to be completed. - */ - void ringback (); - - /** - * Handle played music when an incoming call occurs - */ - void ringtone (); - void congestion (); - void callBusy(const CallID& id); - void callFailure(const CallID& id); - - /** @return 0 if no tone (init before calling this function) */ - AudioLoop* getTelephoneTone(); - /** @return 0 if the wav is stopped */ - AudioLoop* getTelephoneFile(); - - /** - * @return true is there is one or many incoming call waiting - * new call, not anwsered or refused - */ - bool incomingCallWaiting(void); - /** - * Notification of incoming call when you are already busy - */ - void notificationIncomingCall(void); - - - /* - * Inline functions to manage volume control - * Read by main thread and AudioLayer thread - * Write by main thread only - */ - unsigned short getSpkrVolume(void) { return _spkr_volume; } - void setSpkrVolume(unsigned short spkr_vol) { _spkr_volume = spkr_vol; } - unsigned short getMicVolume(void) { return _mic_volume; } - void setMicVolume(unsigned short mic_vol) { _mic_volume = mic_vol; } - - // Manage information about firewall - /* - * Get information about firewall - * @param stunSvrAddr: stun server - * @param port port number to open to test the connection - * @return true if the connection is successful - */ - bool getStunInfo(StunAddress4& stunSvrAddr, int port); - - inline int getFirewallPort(void) { return _firewallPort; } - inline void setFirewallPort(int port) { _firewallPort = port; } - inline std::string getFirewallAddress (void) { return _firewallAddr; } - - /** - * If you are behind a NAT, you have to use STUN server, specified in - * STUN configuration(you can change this one by default) to give you an - * public IP address and assign a port number. - * Note: Set firewall port/address retreive - * @param svr : serveur on which to send request - * @param port : on which port we want to listen to - * - * Return true if we are behind a NAT (without error) - */ - bool behindNat(const std::string& svr, int port); - - /** - * Init default values for the different fields in the config file. - * Fills the local _config (Conf::ConfigTree) with the default contents. - * - * Called in main.cpp, just before Manager::init(). - */ - void initConfigFile (void); - - /** - * Tell if the setup was already loaded - */ - bool hasLoadedSetup() { return _setupLoaded; } - - /** Return a new random callid that is not present in the list - * @return a brand new callid - */ - CallID getNewCallID(); - - /** - * Get the current call id - * @return the call id or "" - */ - const CallID& getCurrentCallId(); - - /** - * Check if a call is the current one - * @param id the new callid - * @return if the id is the current call - */ - bool isCurrentCall(const CallID& callId); - -private: - /** - * Create .PROGNAME directory in home user and create - * configuration tree from the settings file if this file exists. - * - * @return 0 if creating file failed - * 1 if config-file exists - * 2 if file doesn't exist yet. - */ - int createSettingsPath (void); - - /* - * Initialize audiocodec with config setting - */ - void initAudioCodec(void); - - /* - * Initialize audiodriver - */ - void initAudioDriver(void); - - /* - * Initialize zeroconf module and scanning - */ - void initZeroconf(void); - - /* - * Init the Gui interface (after setting it) inside setGui - */ - void initGui(); - - /* - * Init the volume for speakers/micro from 0 to 100 value - */ - void initVolume(); - - /** - * Configuration - */ - bool getDirListing(const std::string& sequenceId, const std::string& path, int *nbFile); - bool getAudioDeviceList(const std::string& sequenceId, int ioDeviceMask); - Conf::ConfigTree _config; - bool getCountryTones(const std::string& sequenceId); - void sendCountryTone(const std::string& sequenceId, int index, const std::string& name); - - - - /** - * Tell if there is a current call processed - * @return true if there is a current call - */ - bool hasCurrentCall(); - - /** - * Switch of current call id - * @param id the new callid - */ - void switchCall(const CallID& id); - - /** Current Call ID */ - CallID _currentCallId2; - - /** Protected current call access */ - ost::Mutex _currentCallMutex; - - - /* - * Play one tone - * @return false if the driver is uninitialize - */ - bool playATone(Tone::TONEID toneId); - - // - // Multithread variable with extern accessor and change only inside the main thread - // - /** Vector of CodecDescriptor */ - CodecDescriptor* _codecBuilder; - - // - // Sound variable - // - AudioLayer* _audiodriver; - - // Main thread - DTMF* _dtmfKey; - - // map of codec (for configlist request) - CodecDescriptor _codecDescriptorMap; - - ///////////////////// - // Protected by Mutex - ///////////////////// - ost::Mutex _toneMutex; - TelephoneTone* _telephoneTone; - AudioFile _audiofile; - - // To handle volume control - short _spkr_volume; - short _mic_volume; - short _mic_volume_before_mute; - // End of sound variable - - - // Multithread variable (protected by _mutex) - // - /** Mutex to protect access to code section */ - ost::Mutex _mutex; - - // - // Multithread variable (non protected) - // - DBusManagerImpl * _dbus; - - /** Waiting Call Vectors */ - CallIDSet _waitingCall; - /** Protect waiting call list, access by many voip/audio threads */ - ost::Mutex _waitingCallMutex; - /** Number of waiting call, synchronize with waitingcall callidvector */ - unsigned int _nbIncomingWaitingCall; - /** - * Add incoming callid to the waiting list - * @param id CallID to add - */ - void addWaitingCall(const CallID& id); - /** - * Remove incoming callid to the waiting list - * @param id CallID to remove - */ - void removeWaitingCall(const CallID& id); - /** - * Tell if a call is waiting and should be remove - * @param id CallID to test - * @return true if the call is waiting - */ - bool isWaitingCall(const CallID& id); - - /** - * Path of the ConfigFile - */ - std::string _path; - int _exist; - int _setupLoaded; - - // To handle firewall - int _firewallPort; - std::string _firewallAddr; - - // tell if we have zeroconf is enabled - int _hasZeroconf; + public: + ManagerImpl (void); + ~ManagerImpl (void); + + /** + * Initialisation of thread (sound) and map. + * Init a new VoIPLink, audio codec and audio driver + */ + void init (void); + + /** + * Terminate all thread (sound, link) and unload AccountMap + */ + void terminate (void); + + /** + * Set user interface manager. + * @param man The DBUS interface implementation + */ + void setDBusManager (DBusManagerImpl* man) { _dbus = man; } + + /** + * Accessor to audiodriver. + * it's multi-thread and use mutex internally + * @return AudioLayer* The audio layer object + */ + AudioLayer* getAudioDriver(void) const { return _audiodriver; } + + /** + * Get a descriptor map of codec available + * @return CodecDescriptor The internal codec map + */ + CodecDescriptor& getCodecDescriptorMap(void) {return _codecDescriptorMap;} + + /** + * Functions which occur with a user's action + * Place a new call + * @param accountId The account to make tha call with + * @param id The call identifier + * @param to The recipient of the call + * @return bool true on success + * false otherwise + */ + bool outgoingCall(const AccountID& accountId, const CallID& id, const std::string& to); + + /** + * Functions which occur with a user's action + * Answer the call + * @param id The call identifier + */ + bool answerCall(const CallID& id); + + /** + * Functions which occur with a user's action + * Hangup the call + * @param id The call identifier + */ + bool hangupCall(const CallID& id); + + /** + * Functions which occur with a user's action + * Cancel the call + * @param id The call identifier + */ + bool cancelCall(const CallID& id); + + /** + * Functions which occur with a user's action + * Put the call on hold + * @param id The call identifier + */ + bool onHoldCall(const CallID& id); + + /** + * Functions which occur with a user's action + * Put the call off hold + * @param id The call identifier + */ + bool offHoldCall(const CallID& id); + + /** + * Functions which occur with a user's action + * Transfer the call + * @param id The call identifier + * @param to The recipient of the transfer + */ + bool transferCall(const CallID& id, const std::string& to); + + /** + * Functions which occur with a user's action + * Refuse the call + * @param id The call identifier + */ + bool refuseCall(const CallID& id); + + /** + * Save config to file + * @return true on success + * false otherwise + */ + bool saveConfig (void); + + /** + * Send registration to all enabled accounts + * @return false if exosip or the network checking fails + */ + bool initRegisterAccounts(); + + /** + * @return true if we tried to register once + */ + bool _hasTriedToRegister; + + /** + * Undocumented + */ + bool sendTextMessage(const AccountID& accountId, const std::string& to, const std::string& message); + + /** + * Handle choice of the DTMF-send-way + * @param id: callid of the line. + * @param code: pressed key. + */ + bool sendDtmf(const CallID& id, char code); + + /** + * Play the dtmf-associated sound + * @param code The pressed key + * @param isTalking In conversation or not. Useful to know whether or not the sound streams are started + */ + bool playDtmf(char code, bool isTalking); + + /** + * Play a ringtone + * @return bool True on success + * false otherwise + */ + bool playTone (); + + /** + * Play a special ringtone ( BUSY ) if there's at least one message on the voice mail + * @return bool True on success + * false otherwise + */ + bool playToneWithMessage (); + + /** + * Acts on the audio streams and audio files + * @param stopAudio Tells whether or not to stop the streams + */ + void stopTone(bool stopAudio); + + /** + * When receiving a new incoming call, add it to the callaccount map + * and notify user + * @param call A call pointer + * @param accountId an account id + * @return bool True if the call was added correctly + */ + bool incomingCall(Call* call, const AccountID& accountId); + + /** + * Notify the user that the recipient of the call has answered and the put the + * call in Current state + * @param id The call identifier + */ + void peerAnsweredCall(const CallID& id); + + /** + * Rings back because the outgoing call is ringing and the put the + * call in Ringing state + * @param id The call identifier + */ + void peerRingingCall(const CallID& id); + + /** + * Put the call in Hungup state, remove the call from the list + * @param id The call identifier + */ + void peerHungupCall(const CallID& id); + + /** + * Notify the client with an incoming message + * @param accountId The account identifier + * @param message The content of the message + */ + void incomingMessage(const AccountID& accountId, const std::string& message); + + /** + * Notify the user he has voice mails + * @param accountId The account identifier + * @param nb_msg The number of messages + */ + void startVoiceMessageNotification(const AccountID& accountId, const std::string& nb_msg); + + /** + * Notify the user that registration succeeded + * @param accountId The account identifier + */ + void registrationSucceed(const AccountID& accountId); + + /** + * Notify the user that unregistration succeeded + * @param accountId The account identifier + */ + void unregistrationSucceed(const AccountID& accountId); + + /** + * Notify the user that registration failed + * @param accountId The account identifier + */ + void registrationFailed(const AccountID& accountId); + + /** + * Notify the user that registration is trying + * @param accountId The account identifier + */ + void registrationTrying(const AccountID& accountId); + + /** + * ConfigurationManager - Send registration request + * @param accountId The account to register/unregister + * @param expire The flag for the type of registration + * 0 for unregistration request + * 1 for registration request + */ + void sendRegister( const ::DBus::String& accountId , bool expire ); + + bool getZeroconf(const std::string& sequenceId); + bool attachZeroconfEvents(const std::string& sequenceId, Pattern::Observer& observer); + bool detachZeroconfEvents(Pattern::Observer& observer); + bool getCallStatus(const std::string& sequenceId); + + /** + * Get account list + * @return std::vector<std::string> A list of accoundIDs + */ + std::vector< std::string > getAccountList(); + + /** + * Retrieve details about a given account + * @param accountID The account identifier + * @return std::map< std::string, std::string > The account details + */ + std::map< std::string, std::string > getAccountDetails(const AccountID& accountID); + + /** + * Save the details of an existing account, given the account ID + * This will load the configuration map with the given data. + * It will also register/unregister links where the 'Enabled' switched. + * @param accountID The account identifier + * @param details The account parameters + */ + void setAccountDetails( const ::DBus::String& accountID, + const std::map< ::DBus::String, ::DBus::String >& details ); + + /** + * Add a new account, and give it a new account ID automatically + * @param details The new account parameters + */ + void addAccount(const std::map< ::DBus::String, ::DBus::String >& details); + + /** + * Delete an existing account, unregister VoIPLink associated, and + * purge from configuration. + * @param accountID The account unique ID + */ + void removeAccount(const AccountID& accountID); + + /** + * Get the list of codecs we supports, not ordered + * @return The list of the codecs + */ + std::vector< ::DBus::String > getCodecList( void ); + + /** + * Get the info about one codec + * Name / Clock rate / bitrate / bandwidth + * @param payload The payload of the codec + * @return std::vector<::DBus::string> The information + */ + std::vector< ::DBus::String > getCodecDetails( const ::DBus::Int32& payload); + + /** + * Get a list of supported input audio plugin + * @return std::vector<std::string> List of names + */ + std::vector< std::string> getInputAudioPluginList(void); + + /** + * Get a list of supported output audio plugin + * @return std::vector<std::string> List of names + */ + std::vector< std::string> getOutputAudioPluginList(void); + + /** + * Set input audio plugin + * @param audioPlugin The audio plugin + */ + void setInputAudioPlugin(const std::string& audioPlugin); + + /** + * Set output audio plugin + * @param audioPlugin The audio plugin + */ + void setOutputAudioPlugin(const std::string& audioPlugin); + + /** + * Get list of supported audio output device + * @return std::vector<std::string> A list of the audio devices supporting playback + */ + std::vector<std::string> getAudioOutputDeviceList(void); + + /** + * Set audio output device + * @param index The index of the soundcard + */ + void setAudioOutputDevice(const int index); + + /** + * Get list of supported audio input device + * @return std::vector<std::string> A list of the audio devices supporting capture + */ + std::vector<std::string> getAudioInputDeviceList(void); + + /** + * Set audio input device + * @param index The index of the soundcard + */ + void setAudioInputDevice(const int index); + + /** + * Get string array representing integer indexes of output and input device + * @return std::vector<std::string> A list of the current audio devices + */ + std::vector<std::string> getCurrentAudioDevicesIndex(); + + /** + * Get index of an audio device + * @param name The string description of an audio device + * @return int His index + */ + int getAudioDeviceIndex( const std::string name ); + + /* + * Get current alsa plugin + * @return std::string The Alsa plugin + */ + std::string getCurrentAudioOutputPlugin( void ); + + /** + * Convert a list of payload in a special format, readable by the server. + * Required format: payloads separated with one slash. + * @return std::string The serializabled string + */ + std::string serialize(std::vector<std::string> v); + + /** + * Tells if IAX2 support is enabled + * @return int 1 if IAX2 is enabled + * 0 otherwise + */ + int isIax2Enabled( void ); + + /** + * Ringtone option. + * If ringtone is enabled, ringtone on incoming call use custom choice. If not, only standart tone. + * @return int 1 if enabled + * 0 otherwise + */ + int isRingtoneEnabled( void ); + + /** + * Set the ringtone option + * Inverse current value + */ + void ringtoneEnabled( void ); + + /** + * Get the ringtone + * @return gchar* The file name selected as a ringtone + */ + std::string getRingtoneChoice( void ); + + /** + * Set a ringtone + * @param tone The file name of the ringtone + */ + void setRingtoneChoice( const std::string& ); + + /** + * Tells if the user wants to display the dialpad or not + * @return int 1 if dialpad has to be displayed + * 0 otherwise + */ + int getDialpad( void ); + + /** + * Set the dialpad visible or not + */ + void setDialpad( void ); + + /** + * Configure the start-up option + * @return int 1 if SFLphone should start in the system tray + * 0 otherwise + */ + int isStartHidden( void ); + + /** + * Configure the start-up option + * At startup, SFLphone can be displayed or start hidden in the system tray + */ + void startHidden( void ); + + /** + * Configure the popup behaviour + * @return int 1 if it should popup on incoming calls + * 0 if it should never popups + */ + int popupMode( void ); + + /** + * Configure the popup behaviour + * When SFLphone is in the system tray, you can configure when it popups + * Never or only on incoming calls + */ + void switchPopupMode( void ); + + /** + * Retrieve the formatted list of codecs payload in the user config file and + * load in the active list of codecs + * @return std::vector<std::string> The vector containing the active codecs + */ + std::vector<std::string> retrieveActiveCodecs( void ); + + /** + * Get the list of the active codecs + * @return std::vector< ::DBus::String > The list of active codecs + */ + std::vector< ::DBus::String > getActiveCodecList( void ); + + /** + * Set the list of the active codecs + * @param list The new list of active codecs + */ + void setActiveCodecList( const std::vector< ::DBus::String >& list); + + /* + * Notify the client that an error occured + * @param errCode The error code. Could be: ALSA_CAPTURE_ERROR + * ALSA_PLAYBACK_ERROR + */ + void notifyErrClient( const ::DBus::Int32& errCode ); + + /** + * 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); + + /** + * Change a specific value in the configuration tree. + * This value will then be saved in the user config file sflphonedrc + * @param section The section name + * @param name The parameter name + * @param value The new string value + * @return bool true on success + * false otherwise + */ + bool setConfig(const std::string& section, const std::string& name, const std::string& value); + + /** + * Change a specific value in the configuration tree. + * This value will then be saved in the user config file sflphonedrc + * @param section The section name + * @param name The parameter name + * @param value The new int value + * @return bool true on success + * false otherwise + */ + bool 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); + + /** + * Get a string 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 sdt::string The string value + */ + std::string getConfigString(const std::string& section, const std::string& name); + + /** + * Retrieve the soundcards index in the user config file and try to open audio devices + * with a specific alsa plugin. + * Set the audio layer sample rate + */ + void selectAudioDriver(void); + + /** + * Handle audio sounds heard by a caller while they wait for their + * connection to a called party to be completed. + */ + void ringback (); + + /** + * Handle played music when an incoming call occurs + */ + void ringtone (); + + /** + * Handle played music when a congestion occurs + */ + void congestion (); + + /** + * Handle played sound when a call can not be conpleted because of a busy recipient + */ + void callBusy(const CallID& id); + + /** + * Handle played sound when a failure occurs + */ + void callFailure(const CallID& id); + + /** + * Retrieve the current telephone tone + * @return AudioLoop* The audio tone or 0 if no tone (init before calling this function) + */ + AudioLoop* getTelephoneTone(); + + /** + * Retrieve the current telephone file + * @return AudioLoop* The audio file or 0 if the wav is stopped + */ + AudioLoop* getTelephoneFile(); + + /** + * @return true is there is one or many incoming call waiting + * new call, not anwsered or refused + */ + bool incomingCallWaiting(void); + + /** + * Notification of incoming call when you are already busy + */ + void notificationIncomingCall(void); + + /* + * 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(void) { return _spkr_volume; } + + /* + * 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) { _spkr_volume = 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(void) { return _mic_volume; } + + /* + * 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) { _mic_volume = mic_vol; } + + // Manage information about firewall + + /* + * Get information about firewall + * @param stunSvrAddr: stun server + * @param port port number to open to test the connection + * @return true if the connection is successful + */ + bool getStunInfo(StunAddress4& stunSvrAddr, int port); + + /* + * Inline functions to manage firewall settings + * @return int The firewall port + */ + inline int getFirewallPort(void) { return _firewallPort; } + + /* + * Inline functions to manage firewall settings + * @param port The firewall port + */ + inline void setFirewallPort(int port) { _firewallPort = port; } + + /* + * Inline functions to manage firewall settings + * @return std::string The firewall address + */ + inline std::string getFirewallAddress (void) { return _firewallAddr; } + + /** + * If you are behind a NAT, you have to use STUN server, specified in + * STUN configuration(you can change this one by default) to give you an + * public IP address and assign a port number. + * Note: Set firewall port/address retreive + * @param svr Server on which to send request + * @param port On which port we want to listen to + * @return true if we are behind a NAT (without error) + */ + bool behindNat(const std::string& svr, int port); + + /** + * Init default values for the different fields in the config file. + * Fills the local _config (Conf::ConfigTree) with the default contents. + * Called in main.cpp, just before Manager::init(). + */ + void initConfigFile (void); + + /** + * Tell if the setup was already loaded + * @return bool True if yes + * false otherwise + */ + bool hasLoadedSetup() { return _setupLoaded; } + + /** + * Return a new random callid that is not present in the list + * @return CallID A brand new callid + */ + CallID getNewCallID(); + + /** + * Get the current call id + * @return CallID The call id or "" + */ + const CallID& getCurrentCallId(); + + /** + * Check if a call is the current one + * @param callId the new callid + * @return bool True if the id is the current call + */ + bool isCurrentCall(const CallID& callId); + + private: + /** + * Create .PROGNAME directory in home user and create + * configuration tree from the settings file if this file exists. + * + * @return 0 if creating file failed + * 1 if config-file exists + * 2 if file doesn't exist yet. + */ + int createSettingsPath (void); + + /* + * Initialize audiocodec with config setting + */ + void initAudioCodec(void); + + /* + * Initialize audiodriver + */ + void initAudioDriver(void); + + /* + * Initialize zeroconf module and scanning + */ + void initZeroconf(void); + + /* + * Init the volume for speakers/micro from 0 to 100 value + */ + void initVolume(); + + /** + * Tell if there is a current call processed + * @return bool True if there is a current call + */ + bool hasCurrentCall(); + + /** + * Switch of current call id + * @param id The new callid + */ + void switchCall(const CallID& id); + + /* + * Play one tone + * @return false if the driver is uninitialize + */ + bool playATone(Tone::TONEID toneId); + + /** The configuration tree. It contains accounts parameters, general user settings ,audio settings, ... */ + Conf::ConfigTree _config; + + /** Current Call ID */ + CallID _currentCallId2; + + /** Protected current call access */ + ost::Mutex _currentCallMutex; + + /** Vector of CodecDescriptor */ + CodecDescriptor* _codecBuilder; + + /** Audio layer */ + AudioLayer* _audiodriver; + + // Main thread + + DTMF* _dtmfKey; + + // map of codec (for configlist request) + CodecDescriptor _codecDescriptorMap; + + ///////////////////// + // Protected by Mutex + ///////////////////// + ost::Mutex _toneMutex; + TelephoneTone* _telephoneTone; + AudioFile _audiofile; + + // To handle volume control + short _spkr_volume; + short _mic_volume; + // End of sound variable + + + // Multithread variable (protected by _mutex) + // + /** Mutex to protect access to code section */ + ost::Mutex _mutex; + + // Multithread variable (non protected) + DBusManagerImpl * _dbus; + + /** Waiting Call Vectors */ + CallIDSet _waitingCall; + + /** Protect waiting call list, access by many voip/audio threads */ + ost::Mutex _waitingCallMutex; + + /** Number of waiting call, synchronize with waitingcall callidvector */ + unsigned int _nbIncomingWaitingCall; + + /** + * Add incoming callid to the waiting list + * @param id CallID to add + */ + void addWaitingCall(const CallID& id); + + /** + * Remove incoming callid to the waiting list + * @param id CallID to remove + */ + void removeWaitingCall(const CallID& id); + + /** + * Tell if a call is waiting and should be remove + * @param id CallID to test + * @return bool True if the call is waiting + */ + bool isWaitingCall(const CallID& id); + + /** + * Path of the ConfigFile + */ + std::string _path; + int _exist; + int _setupLoaded; + + // To handle firewall + int _firewallPort; + std::string _firewallAddr; + + // tell if we have zeroconf is enabled + int _hasZeroconf; #ifdef USE_ZEROCONF - // DNSService contain every zeroconf services - // configuration detected on the network - DNSService *_DNSService; + // DNSService contain every zeroconf services + // configuration detected on the network + DNSService *_DNSService; #endif - /** Map to associate a CallID to the good account */ - CallAccountMap _callAccountMap; - /** Mutex to lock the call account map (main thread + voiplink thread) */ - ost::Mutex _callAccountMapMutex; - - /** Associate a new CallID to a AccountID - * Protected by mutex - * @param callID the new CallID not in the list yet - * @param accountID the known accountID present in accountMap - * @return true if the new association is create - */ - bool associateCallToAccount(const CallID& callID, const AccountID& accountID); - - /** Return the AccountID from a CallID - * Protected by mutex - * @param callID the CallID in the list - * @return the accountID associated or "" if the callID is not found - */ - AccountID getAccountFromCall(const CallID& callID); - - /** Remove a CallID/AccountID association - * Protected by mutex - * @param callID the CallID to remove - * @return true if association is removed - */ - bool removeCallAccount(const CallID& callID); - - /** Contains a list of account (sip, aix, etc) and their respective voiplink/calls */ - AccountMap _accountMap; - - /** - * Load the account from configuration - * @return number of account - */ - short loadAccountMap(); - - /** - * Unload the account (delete them) - */ - void unloadAccountMap(); - - /** - * Tell if an account exists - * @param accountID account ID check - */ - bool accountExists(const AccountID& accountID); - - /** - * Get an account pointer - * @param accountID account ID to get - * @param the account pointer or 0 - */ - Account* getAccount(const AccountID& accountID); - - /** - * Get the voip link from the account pointer - * @param accountID account ID to get - * @param the voip link from the account pointer or 0 - */ - VoIPLink* getAccountLink(const AccountID& accountID); - - - - #ifdef TEST - bool testCallAccountMap(); - bool testAccountMap(); - #endif + /** Map to associate a CallID to the good account */ + CallAccountMap _callAccountMap; + + /** Mutex to lock the call account map (main thread + voiplink thread) */ + ost::Mutex _callAccountMapMutex; + + /** Associate a new CallID to a AccountID + * 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 CallID& callID, const AccountID& accountID); + + /** Return the AccountID from a CallID + * Protected by mutex + * @param callID the CallID in the list + * @return AccountID The accountID associated or "" if the callID is not found + */ + AccountID getAccountFromCall(const CallID& callID); + + /** Remove a CallID/AccountID association + * Protected by mutex + * @param callID the CallID to remove + * @return bool True if association is removed + */ + bool removeCallAccount(const CallID& callID); + + /** Contains a list of account (sip, aix, etc) and their respective voiplink/calls */ + AccountMap _accountMap; + + /** + * Load the account from configuration + * @return short Number of account + */ + short loadAccountMap(); + + /** + * Unload the account (delete them) + */ + void unloadAccountMap(); + + /** + * Tell if an account exists + * @param accountID account ID check + * @return bool True if the account exists + * false otherwise + */ + bool accountExists(const AccountID& accountID); + + /** + * Get an account pointer + * @param accountID account ID to get + * @return Account* The account pointer or 0 + */ + Account* getAccount(const AccountID& accountID); + + /** + * Get the voip link from the account pointer + * @param accountID Account ID to get + * @return VoIPLink* The voip link from the account pointer or 0 + */ + VoIPLink* getAccountLink(const AccountID& accountID); + +#ifdef TEST + bool testCallAccountMap(); + bool testAccountMap(); +#endif }; diff --git a/src/sipaccount.cpp b/src/sipaccount.cpp index 19076f5386dded38bd4f26849243257aa6748697..1adcd5dbdd0f53460eae11cd2f644c755f43c953 100644 --- a/src/sipaccount.cpp +++ b/src/sipaccount.cpp @@ -38,6 +38,7 @@ SIPAccount::~SIPAccount() void SIPAccount::registerVoIPLink() { + _debug("SIPAccount: register account %s\n" , getAccountID().c_str()); _link->setFullName(Manager::instance().getConfigString(_accountID,SIP_FULL_NAME)); _link->setHostName(Manager::instance().getConfigString(_accountID,SIP_HOST_PART)); int useStun = Manager::instance().getConfigInt(_accountID,SIP_USE_STUN); @@ -47,20 +48,20 @@ SIPAccount::registerVoIPLink() thislink->setUseStun( useStun!=0 ? true : false); _link->init(); - // Stuff needed for SIP registration. thislink->setProxy (Manager::instance().getConfigString(_accountID,SIP_PROXY)); thislink->setUserPart(Manager::instance().getConfigString(_accountID,SIP_USER_PART)); thislink->setAuthName(Manager::instance().getConfigString(_accountID,SIP_AUTH_NAME)); thislink->setPassword(Manager::instance().getConfigString(_accountID,SIP_PASSWORD)); - _debug("sipaccount --> sendRegister\n"); _link->sendRegister(); } void SIPAccount::unregisterVoIPLink() { + _debug("SIPAccount: unregister account %s\n" , getAccountID().c_str()); _link->sendUnregister(); + _debug("Terminate SIP account\n"); _link->terminate(); } diff --git a/src/sipaccount.h b/src/sipaccount.h index 23c2fc3f529f09821820f238c9faa3e626d261dd..e542032b02cd4ede155d3548d120aaf4e9c5cb6d 100644 --- a/src/sipaccount.h +++ b/src/sipaccount.h @@ -24,19 +24,37 @@ /** - * A SIP Account specify SIP specific functions and object (SIPCall/SIPVoIPLink) - * @author Yan Morin <yan.morin@gmail.com> + * @file sipaccount.h + * @brief A SIP Account specify SIP specific functions and object (SIPCall/SIPVoIPLink) */ + class SIPAccount : public Account { public: + /** + * Constructor + * @param accountID The account identifier + */ SIPAccount(const AccountID& accountID); + /** + * Virtual destructor + */ virtual ~SIPAccount(); - /** Actually unuseful, since config loading is done in init() */ + /** + * Actually unuseful, since config loading is done in init() + */ void loadConfig(); + + /** + * Initialize the SIP voip link with the account parameters and send registration + */ void registerVoIPLink(); + + /** + * Send unregistration and clean all related stuff ( calls , thread ) + */ void unregisterVoIPLink(); private: diff --git a/src/sipcall.h b/src/sipcall.h index 3883380e3f69cc60e93d0cb0f80a263333893bcc..a74885500707958e326a034690f66c20d119a52c 100644 --- a/src/sipcall.h +++ b/src/sipcall.h @@ -28,112 +28,147 @@ class AudioCodec; /** - * SIPCall are SIP implementation of a normal Call - * @author Yan Morin <yan.morin@gmail.com> + * @file sipcall.h + * @brief SIPCall are SIP implementation of a normal Call */ class SIPCall : public Call { -public: + public: + + /** + * Constructor + * @param id The call identifier + * @param type The type of the call. Could be Incoming + * Outgoing + */ SIPCall(const CallID& id, Call::CallType type); + /** + * Destructor + */ ~SIPCall(); - /** @return SIP call id : protected by eXosip lock */ - int getCid() { return _cid; } - /** @param cid SIP call id : protected by eXosip lock */ - void setCid(int cid) { _cid = cid ; } - /** @return SIP domain id : protected by eXosip lock */ - int getDid() { return _did; } - /** @param did SIP domain id : protected by eXosip lock */ - void setDid(int did) { _did = did; } - /** @return SIP transaction id : protected by eXosip lock */ - int getTid() { return _tid; } - /** @param did SIP transaction id : protected by eXosip lock */ - void setTid(int tid) { _tid = tid; } - - /** - * Setup incoming call, and verify for errors, before ringing the user. - * @param event eXosip Event - */ - bool SIPCallInvite(eXosip_event_t *event); - - /** - * newReinviteCall is called when the IP-Phone user receives a change in the call - * it's almost an newIncomingCall but we send a 200 OK - * See: 3.7. Session with re-INVITE (IP Address Change) - * @param event eXosip Event - * @return true if ok - */ - bool SIPCallReinvite(eXosip_event_t *event); - - /** - * Peer answered to a call (on hold or not) - * @param event eXosip Event - * @return true if ok - */ - bool SIPCallAnswered(eXosip_event_t *event); - - /** - * We retreive final SDP info if they changed - * @param event eXosip Event - * @return true if ok (change / no change) or false on error - */ - bool SIPCallAnsweredWithoutHold(eXosip_event_t *event); - - //TODO: humm? - int sdp_complete_message(sdp_message_t * remote_sdp, osip_message_t * msg); - - -private: - - // TODO: hum??? - int sdp_analyse_attribute (sdp_message_t * sdp, sdp_media_t * med); - /** - * Set peer name and number with event->request->from - * @param event eXosip event - * @return false the event is invalid - */ - - bool setPeerInfoFromRequest(eXosip_event_t *event); - /** - * Get a valid remote SDP or return a 400 bad request response if invalid - * - * @param event eXosip event - * @return valid remote_sdp or 0 - */ - sdp_message_t* getRemoteSDPFromRequest(eXosip_event_t *event); - - /** - * Get a valid remote media or return a 415 unsupported media type - * - * @param tid transaction id - * @param remote_sdp Remote SDP pointer - * @return valid sdp_media_t or 0 - */ - sdp_media_t* getRemoteMedia(int tid, sdp_message_t* remote_sdp); - - /** - * Set Audio Port and Audio IP from Remote SDP Info - * @param remote_med Remote Media info - * @param remote_sdp Remote SDP pointer - * @return true if everything is set correctly - */ - bool setRemoteAudioFromSDP(sdp_media_t* remote_med, sdp_message_t* remote_sdp); - - /** - * Set Audio Codec with the remote choice - * @param remote_med Remote Media info - * @return true if everything is set correctly - */ - bool setAudioCodecFromSDP(sdp_media_t* remote_med, int tid); - - - /** SIP call id */ - int _cid; - /** SIP domain id */ - int _did; - /** SIP transaction id */ - int _tid; + /** + * Call Identifier + * @return int SIP call id : protected by eXosip lock + */ + int getCid() { return _cid; } + + /** + * Call Identifier + * @param cid SIP call id : protected by eXosip lock + */ + void setCid(int cid) { _cid = cid ; } + + /** + * Domain identifier + * @return int SIP domain id : protected by eXosip lock + */ + int getDid() { return _did; } + + /** + * Domain identifier + * @param did SIP domain id : protected by eXosip lock + */ + void setDid(int did) { _did = did; } + + /** + * Transaction identifier + * @return int SIP transaction id : protected by eXosip lock + */ + int getTid() { return _tid; } + + /** + * Transaction identifier + * @param tid SIP transaction id : protected by eXosip lock + */ + void setTid(int tid) { _tid = tid; } + + /** + * Setup incoming call, and verify for errors, before ringing the user. + * @param event eXosip Event + * @return bool True on success + * false otherwise + */ + bool SIPCallInvite(eXosip_event_t *event); + + /** + * newReinviteCall is called when the IP-Phone user receives a change in the call + * it's almost an newIncomingCall but we send a 200 OK + * See: 3.7. Session with re-INVITE (IP Address Change) + * @param event eXosip Event + * @return bool True if ok + */ + bool SIPCallReinvite(eXosip_event_t *event); + + /** + * Peer answered to a call (on hold or not) + * @param event eXosip Event + * @return bool True if ok + */ + bool SIPCallAnswered(eXosip_event_t *event); + + /** + * We retreive final SDP info if they changed + * @param event eXosip Event + * @return bool True if ok (change / no change) or false on error + */ + bool SIPCallAnsweredWithoutHold(eXosip_event_t *event); + + //TODO: humm? + int sdp_complete_message(sdp_message_t * remote_sdp, osip_message_t * msg); + + + private: + + // TODO: hum??? + int sdp_analyse_attribute (sdp_message_t * sdp, sdp_media_t * med); + + /** + * Set peer name and number with event->request->from + * @param event eXosip event + * @return bool False if the event is invalid + */ + bool setPeerInfoFromRequest(eXosip_event_t *event); + + /** + * Get a valid remote SDP or return a 400 bad request response if invalid + * @param event eXosip event + * @return sdp_message_t* A valid remote_sdp or 0 + */ + sdp_message_t* getRemoteSDPFromRequest(eXosip_event_t *event); + + /** + * Get a valid remote media or return a 415 unsupported media type + * @param tid transaction id + * @param remote_sdp Remote SDP pointer + * @return sdp_media_t* A valid sdp_media_t or 0 + */ + sdp_media_t* getRemoteMedia(int tid, sdp_message_t* remote_sdp); + + /** + * Set Audio Port and Audio IP from Remote SDP Info + * @param remote_med Remote Media info + * @param remote_sdp Remote SDP pointer + * @return bool True if everything is set correctly + */ + bool setRemoteAudioFromSDP(sdp_media_t* remote_med, sdp_message_t* remote_sdp); + + /** + * Set Audio Codec with the remote choice + * @param remote_med Remote Media info + * @return bool True if everything is set correctly + */ + bool setAudioCodecFromSDP(sdp_media_t* remote_med, int tid); + + /** SIP call id */ + int _cid; + + /** SIP domain id */ + int _did; + + /** SIP transaction id */ + int _tid; }; diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp index d2cd1aea7ccadc49da616f0a7b3bee05c0b28601..47320dce08b5c1f05ace808242036f79b4c9d7d5 100644 --- a/src/sipvoiplink.cpp +++ b/src/sipvoiplink.cpp @@ -24,6 +24,7 @@ #include "eventthread.h" #include "sipcall.h" #include <sstream> // for ostringstream +#include "sipaccount.h" #include "manager.h" #include "user_cfg.h" // SIGNALISATION / PULSE #define @@ -53,10 +54,11 @@ SIPVoIPLink::SIPVoIPLink(const AccountID& accountID) - : VoIPLink(accountID), _localExternAddress("") + : VoIPLink(accountID), _localExternAddress("") , eXosip_running( false ) { _evThread = new EventThread(this); + _nMsgVoicemail = 0; _eXosipRegID = EXOSIP_ERROR_STD; @@ -76,6 +78,13 @@ SIPVoIPLink::~SIPVoIPLink() bool SIPVoIPLink::init() { + if( eXosip_running ){ + delete _evThread; + _evThread=0; + _evThread= new EventThread( this ); + eXosip_quit(); + } + if (!_initDone) { if (0 != eXosip_init()) { _debug("! SIP Failure: Could not initialize eXosip\n"); @@ -85,7 +94,6 @@ SIPVoIPLink::init() // Pour éviter qu'on refasse l'init sans avoir considéré l'erreur, // s'il y en a une ? _initDone = true; - // check networking capabilities if ( !checkNetwork() ) { _debug("! SIP FAILURE: Unable to determine network capabilities\n"); @@ -144,30 +152,26 @@ SIPVoIPLink::init() } _initDone = true; - + eXosip_running = true; // Useless return true; } - - void SIPVoIPLink::terminate() { terminateSIPCall(); - if (_initDone) { // TODO The next line makes the daemon crash on // account delete if at least one account is registered. // It should called only when the last account // is deleted/unregistered. - //eXosip_quit(); _initDone = false; - } } void SIPVoIPLink::terminateSIPCall() { + ost::MutexLock m(_callMapMutex); CallMap::iterator iter = _callMap.begin(); SIPCall *call; @@ -199,6 +203,8 @@ SIPVoIPLink::loadSIPLocalIP() if (_localIPAddress == "127.0.0.1") { char* myIPAddress = new char[65]; if (eXosip_guess_localip(AF_INET, myIPAddress, 64) == EXOSIP_ERROR_STD) { + // Update the registration state if no network capabilities found + setRegistrationState( ErrorNetwork ); returnValue = false; } else { _localIPAddress = std::string(myIPAddress); @@ -217,33 +223,38 @@ SIPVoIPLink::getEvent() eXosip_lock(); eXosip_automatic_action(); eXosip_unlock(); - - if (event == NULL) { + + if ( event == NULL ) { return; } - - _debugMid("> SIP Event: [cdt=%4d:%4d:%4d] type=#%03d %s = ", event->cid, event->did, event->tid, event->type, event->textinfo); + + _debug("> SIP Event: [cdt=%4d:%4d:%4d] type=#%03d %s \n", event->cid, event->did, event->tid, event->type, event->textinfo); switch (event->type) { - /* REGISTER related events */ case EXOSIP_REGISTRATION_NEW: /** 00 < announce new registration. */ _debugMid(" !EXOSIP_REGISTRATION_NEW event is not implemented\n"); break; case EXOSIP_REGISTRATION_SUCCESS: /** 01 < user is successfully registred. */ - setRegistrationState(Registered); - _debugMid(" !EXOSIP_REGISTRATION_SUCCES\n"); - //Manager::instance().registrationSucceed(getAccountID()); + _debugMid(" !EXOSIP_REGISTRATION_SUCCESS ---> %s\n" , getAccountID().c_str()); + if(_eXosipRegID == EXOSIP_ERROR_STD){ + _debug("Successfully Unregister account ID = %s\n" , getAccountID().c_str()); + setRegistrationState(Unregistered); + } + else{ + _debug("Successfully Register account ID = %s\n" , getAccountID().c_str()); + setRegistrationState(Registered); + } break; case EXOSIP_REGISTRATION_FAILURE: /** 02 < user is not registred. */ - setRegistrationState(Error, "SIP registration failure."); + SIPRegistrationFailure( event ); _debugMid(" !EXOSIP_REGISTRATION_FAILURE\n"); - //Manager::instance().registrationFailed(getAccountID()); break; case EXOSIP_REGISTRATION_REFRESHED: /** 03 < registration has been refreshed. */ _debugMid(" !EXOSIP_REGISTRATION_REFRESHED event is not implemented\n"); break; case EXOSIP_REGISTRATION_TERMINATED: /** 04 < UA is not registred any more. */ - setRegistrationState(Unregistered, "Registration terminated by remote host"); + //setRegistrationState(Unregistered, "Registration terminated by remote host"); + setRegistrationState(Unregistered); _debugMid(" !EXOSIP_REGISTRATION_TERMINATED event is not implemented\n"); break; @@ -296,7 +307,6 @@ SIPVoIPLink::getEvent() break; case EXOSIP_CALL_TIMEOUT: /** 17 < announce that call has failed */ _debugMid(" !EXOSIP_CALL_TIMEOUT\n"); - Manager::instance().displayError(" !EXOSIP Call Error not implemented yet"); break; /* Request related events within calls (except INVITE) */ @@ -322,7 +332,6 @@ SIPVoIPLink::getEvent() break; case EXOSIP_CALL_MESSAGE_GLOBALFAILURE: /** 24 < announce a failure. */ _debugMid(" !EXOSIP_CALL_MESSAGE_GLOBALFAILURE\n"); - Manager::instance().displayError(" !EXOSIP Call Message not implemented yet"); break; case EXOSIP_CALL_CLOSED: /** 25 < a BYE was received for this call */ @@ -350,23 +359,18 @@ SIPVoIPLink::getEvent() break; case EXOSIP_MESSAGE_REDIRECTED: /** 30 < announce a failure. */ _debugMid(" !EXOSIP_MESSAGE_REDIRECTED\n"); - Manager::instance().displayError(" !EXOSIP Message not implemented yet"); break; case EXOSIP_MESSAGE_REQUESTFAILURE: /** 31 < announce a failure. */ _debugMid(" !EXOSIP_MESSAGE_REQUESTFAILURE\n"); - if (event->response !=0 && event->response->status_code == SIP_METHOD_NOT_ALLOWED) { + if (event->response !=0 && event->response->status_code == SIP_METHOD_NOT_ALLOWED) Manager::instance().incomingMessage(getAccountID(), "Message are not allowed"); - } else { - Manager::instance().displayError(" !EXOSIP_MESSAGE_REQUESTFAILURE not implemented yet"); - } break; case EXOSIP_MESSAGE_SERVERFAILURE: /** 32 < announce a failure. */ _debugMid(" !EXOSIP_MESSAGE_SERVERFAILURE\n"); break; case EXOSIP_MESSAGE_GLOBALFAILURE: /** 33 < announce a failure. */ _debugMid(" !EXOSIP_MESSAGE_GLOBALFAILURE\n"); - Manager::instance().displayError(" !EXOSIP Message not implemented yet"); break; /* Presence and Instant Messaging */ @@ -375,7 +379,6 @@ SIPVoIPLink::getEvent() break; case EXOSIP_SUBSCRIPTION_CLOSED: /** 35 < announce end of subscription. */ _debugMid(" !EXOSIP_SUBSCRIPTION_CLOSED\n"); - Manager::instance().displayError(" !EXOSIP Subscription not implemented yet"); break; case EXOSIP_SUBSCRIPTION_NOANSWER: /** 37 < announce no answer */ @@ -383,7 +386,6 @@ SIPVoIPLink::getEvent() break; case EXOSIP_SUBSCRIPTION_PROCEEDING: /** 38 < announce a 1xx */ _debugMid(" !EXOSIP_SUBSCRIPTION_PROCEEDING\n"); - Manager::instance().displayError(" !EXOSIP Subscription response not implemented yet"); break; case EXOSIP_SUBSCRIPTION_ANSWERED: /** 39 < announce a 200ok */ _debugMid(" !EXOSIP_SUBSCRIPTION_ANSWERED\n"); @@ -418,7 +420,6 @@ SIPVoIPLink::getEvent() break; case EXOSIP_SUBSCRIPTION_RELEASED: /** 45 < call context is cleared. */ _debugMid(" !EXOSIP_SUBSCRIPTION_RELEASED\n"); - Manager::instance().displayError(" !EXOSIP Subscription response not implemented yet."); break; case EXOSIP_IN_SUBSCRIPTION_NEW: /** 46 < announce new incoming SUBSCRIBE.*/ @@ -426,7 +427,6 @@ SIPVoIPLink::getEvent() break; case EXOSIP_IN_SUBSCRIPTION_RELEASED: /** 47 < announce end of subscription. */ _debugMid(" !EXOSIP_IN_SUBSCRIPTION_RELEASED\n"); - Manager::instance().displayError(" !EXOSIP Subscription not implemented yet"); break; case EXOSIP_EVENT_COUNT: /** 48 < MAX number of events */ @@ -442,19 +442,17 @@ SIPVoIPLink::getEvent() bool SIPVoIPLink::sendRegister() { + if (_eXosipRegID != EXOSIP_ERROR_STD) { - Manager::instance().displayError("! SIP Error: Registration already sent. Try to unregister"); return false; } std::string hostname = getHostName(); if (hostname.empty()) { - Manager::instance().displayConfigError("Fill host part field"); return false; } if (_userpart.empty()) { - Manager::instance().displayConfigError("Fill user part field"); return false; } @@ -499,9 +497,9 @@ SIPVoIPLink::sendRegister() eXosip_unlock(); return false; } - eXosip_unlock(); setRegistrationState(Trying); + eXosip_unlock(); return true; } @@ -521,12 +519,10 @@ SIPVoIPLink::sendSIPAuthentification() } if (login.empty()) { /** @todo Ajouter ici un call à setRegistrationState(Error, "Fill balh") ? */ - Manager::instance().displayConfigError("Fill authentification name"); return false; } if (_password.empty()) { /** @todo Même chose ici ? */ - Manager::instance().displayConfigError("Fill password field"); return false; } eXosip_lock(); @@ -539,6 +535,7 @@ SIPVoIPLink::sendSIPAuthentification() bool SIPVoIPLink::sendUnregister() { + _debug("SEND UNREGISTER for account %s\n" , getAccountID().c_str()); if ( _eXosipRegID == EXOSIP_ERROR_STD) return false; int eXosipErr = EXOSIP_ERROR_NO; osip_message_t *reg = NULL; @@ -563,8 +560,8 @@ SIPVoIPLink::sendUnregister() if (eXosipErr == EXOSIP_ERROR_STD) { _debug("! SIP Failure: Unable to send registration (unregister)\n"); } - eXosip_unlock(); _eXosipRegID = EXOSIP_ERROR_STD; + eXosip_unlock(); return true; } @@ -916,11 +913,9 @@ SIPVoIPLink::sendMessage(const std::string& to, const std::string& body) std::string sipRoute = getSipRoute(); if (!SIPCheckUrl(sipFrom)) { - Manager::instance().displayConfigError("Error in source address"); return returnValue; } if (!SIPCheckUrl(sipTo)) { - Manager::instance().displayError("Error in destination address"); return returnValue; } @@ -1059,11 +1054,9 @@ SIPVoIPLink::SIPStartCall(SIPCall* call, const std::string& subject) if (!SIPCheckUrl(from)) { _debug("! SIP Error: Source address is invalid %s\n", from.data()); - Manager::instance().displayConfigError("Error in source address"); return false; } if (!SIPCheckUrl(to)) { - Manager::instance().displayErrorText(call->getCallId(), "Error in destination address"); return false; } @@ -1151,9 +1144,6 @@ SIPVoIPLink::SIPStartCall(SIPCall* call, const std::string& subject) return true; } -/** - * Get the Sip FROM url (add sip:, add @host, etc...) - */ std::string SIPVoIPLink::getSipFrom() { @@ -1165,9 +1155,6 @@ SIPVoIPLink::getSipFrom() { return SIPFromHeader(_userpart, host); } -/** - * Get the Sip TO url (add sip:, add @host, etc...) - */ std::string SIPVoIPLink::getSipTo(const std::string& to_url) { // Form the From header field basis on configuration panel @@ -1183,10 +1170,6 @@ SIPVoIPLink::getSipTo(const std::string& to_url) { return SIPToHeader(to_url); } -/** - * Get the sip proxy (add sip: if there is one) - * @return empty string or <sip:proxy;lr> url - */ std::string SIPVoIPLink::getSipRoute() { std::string proxy = _proxy; @@ -1383,7 +1366,6 @@ SIPVoIPLink::SIPCallRequestFailure(eXosip_event_t *event) CallID& id = call->getCallId(); call->setConnectionState(Call::Connected); call->setState(Call::Busy); - Manager::instance().displayErrorText(id, event->response->reason_phrase); Manager::instance().callBusy(id); removeCall(id); } @@ -1409,7 +1391,6 @@ SIPVoIPLink::SIPCallRequestFailure(eXosip_event_t *event) CallID& id = call->getCallId(); call->setConnectionState(Call::Connected); call->setState(Call::Error); - Manager::instance().displayErrorText(id, event->response->reason_phrase); Manager::instance().callFailure(id); removeCall(id); } @@ -1435,6 +1416,28 @@ SIPVoIPLink::SIPCallServerFailure(eXosip_event_t *event) } } +void +SIPVoIPLink::SIPRegistrationFailure( eXosip_event_t* event ) +{ + if(!event->response){ + setRegistrationState(ErrorHost); + return ; + } + + switch( event->response->status_code ) { + case SIP_FORBIDDEN: + _debug("SIP forbidden\n"); + setRegistrationState(ErrorAuth); + break; + case SIP_UNAUTHORIZED: + _debug("SIP unauthorized\n"); + setRegistrationState(Error); + break; + default: + _debug("Unknown error: %s\n" , event->response->status_code); + } +} + void SIPVoIPLink::SIPCallAck(eXosip_event_t *event) { @@ -1508,6 +1511,7 @@ SIPVoIPLink::SIPCallReleased(eXosip_event_t *event) if (!call) { return; } // if we are here.. something when wrong before... + _debug("SIP call release\n"); CallID id = call->getCallId(); Manager::instance().callFailure(id); removeCall(id); @@ -1526,7 +1530,6 @@ SIPVoIPLink::SIPMessageNew(eXosip_event_t *event) } // Voice message else if (MSG_IS_NOTIFY(event->request)){ - _debug(" > NOTIFY Voice message\n"); int ii; osip_body_t *body = NULL; // Get the message body @@ -1556,15 +1559,12 @@ SIPVoIPLink::SIPMessageNew(eXosip_event_t *event) // Set the number of voice-message int msgVoicemail = atoi(nb_msg.data()); + _debug(" > NOTIFY -> %i voice message for account %s\n" , msgVoicemail , getAccountID().c_str()); if (msgVoicemail != 0) { // If there is at least one voice-message, start notification Manager::instance().startVoiceMessageNotification(getAccountID(), nb_msg); - } else { - // Stop notification when there is 0 voice message - Manager::instance().stopVoiceMessageNotification(getAccountID()); } - // http://www.jdrosen.net/papers/draft-ietf-simple-im-session-00.txt } else if (MSG_IS_MESSAGE(event->request)) { _debug("> MESSAGE received\n"); @@ -1647,10 +1647,6 @@ SIPVoIPLink::getSIPCall(const CallID& id) return NULL; } -/** - * Handle an INFO with application/dtmf-relay content-type - * @param event eXosip Event - */ bool SIPVoIPLink::handleDtmfRelay(eXosip_event_t* event) { diff --git a/src/sipvoiplink.h b/src/sipvoiplink.h index d25553c7db128c8e63b19fd09b3d2ce1eeb4c7eb..a62aa7b9297c7ec7a35d9a472ddba88b8d2a3a60 100644 --- a/src/sipvoiplink.h +++ b/src/sipvoiplink.h @@ -1,7 +1,8 @@ /* - * Copyright (C) 2004-2006 Savoir-Faire Linux inc. + * Copyright (C) 2004-2008 Savoir-Faire Linux inc. * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@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 @@ -24,266 +25,419 @@ #include <string> #include <eXosip2/eXosip.h> #include "audio/audiortp.h" +#include <osip2/osip_mt.h> class EventThread; class SIPCall; /** - * Specific VoIPLink for SIP (SIP core for incoming and outgoing events) - * @author Yan Morin <yan.morin@gmail.com> + * @file sipvoiplink.h + * @brief Specific VoIPLink for SIP (SIP core for incoming and outgoing events) */ class SIPVoIPLink : public VoIPLink { -public: - SIPVoIPLink(const AccountID& accountID); - - ~SIPVoIPLink(); - - /** try to initiate the eXosip engine/thread and set config */ - bool init(void); - void terminate(void); - bool checkNetwork(void); - void getEvent(void); - - bool sendRegister(void); - bool sendUnregister(void); - - Call* newOutgoingCall(const CallID& id, const std::string& toUrl); - bool answer(const CallID& id); - - bool hangup(const CallID& id); - bool cancel(const CallID& id); - bool onhold(const CallID& id); - bool offhold(const CallID& id); - bool transfer(const CallID& id, const std::string& to); - bool refuse (const CallID& id); - bool carryingDTMFdigits(const CallID& id, char code); - bool sendMessage(const std::string& to, const std::string& body); - bool isContactPresenceSupported(); - void subscribePresenceForContact(Contact* contact); - void publishPresenceStatus(std::string status); - - // TODO Not used yet - void sendMessageToContact(const CallID& id, const std::string& message); - - // SIP Specific - - /** If set to true, we check for a firewall - * @param use true if we use STUN - */ - void setUseStun(bool use) { _useStun = use; } - - /** The name of the STUN server - * @param server Server FQDN/IP - */ - void setStunServer(const std::string& server) { _stunServer = server; } - - /** Set the SIP proxy - * @param proxy Proxy FQDN/IP - */ - void setProxy(const std::string& proxy) { _proxy = proxy; } - void setUserPart(const std::string& userpart) { _userpart = userpart; } - void setAuthName(const std::string& authname) { _authname = authname; } - void setPassword(const std::string& password) { _password = password; } - - -private: - /** Terminate every call not hangup | brutal | Protected by mutex */ - void terminateSIPCall(); - - /** - * Get the local Ip by eXosip - * only if the local ip address is to his default value: 127.0.0.1 - * setLocalIpAdress - * @return false if not found - */ - bool loadSIPLocalIP(); - - /** - * send SIP authentification - * @return true if sending succeed - */ - bool sendSIPAuthentification(); - - /** - * Get a SIP From header ("fullname" <sip:userpart@hostpart>) - * @param userpart - * @param hostpart - * @return SIP URI for from Header - */ - std::string SIPFromHeader(const std::string& userpart, const std::string& hostpart); - - /** - * Build a sip address with the number that you want to call - * Example: sip:124@domain.com - * @return result as a string - */ - std::string SIPToHeader(const std::string& to); - - /** - * Check if an url is sip-valid - * @return true if osip tell that is valid - */ - bool SIPCheckUrl(const std::string& url); - - - /** - * SIPOutgoingInvite do SIPStartCall - * @return true if all is correct - */ - bool SIPOutgoingInvite(SIPCall* call); - - /** - * Start a SIP Call - * @return true if all is correct - */ - bool SIPStartCall(SIPCall* call, const std::string& subject); - std::string getSipFrom(); - std::string getSipRoute(); - std::string getSipTo(const std::string& to_url); - - /** - * Set audio (SDP) configuration for a call - * localport, localip, localexternalport - * @param call a SIPCall valid pointer - * @return true - */ - bool setCallAudioLocal(SIPCall* call); - - /** - * Create a new call and send a incoming call notification to the user - * @param event eXosip Event - */ - void SIPCallInvite(eXosip_event_t *event); - - /** - * Use a exisiting call to restart the audio - * @param event eXosip Event - */ - void SIPCallReinvite(eXosip_event_t *event); - - /** - * Tell the user that the call is ringing - * @param event eXosip Event - */ - void SIPCallRinging(eXosip_event_t *event); - - /** - * Tell the user that the call was answered - * @param event eXosip Event - */ - void SIPCallAnswered(eXosip_event_t *event); - - /** - * Handling 4XX error - * @param event eXosip Event - */ - void SIPCallRequestFailure(eXosip_event_t *event); - - /** - * Handling 5XX/6XX error - * @param event eXosip Event - */ - void SIPCallServerFailure(eXosip_event_t *event); - - /** - * Handling ack (restart audio if reinvite) - * @param event eXosip Event - */ - void SIPCallAck(eXosip_event_t *event); - - /** - * Handling message inside a call (like dtmf) - * @param event eXosip Event - */ - void SIPCallMessageNew(eXosip_event_t *event); - bool handleDtmfRelay(eXosip_event_t *event); - - /** - * Peer close the connection - * @param event eXosip Event - */ - void SIPCallClosed(eXosip_event_t *event); - - /** - * The call pointer was released - * If the call was not cleared before, report an error - * @param event eXosip Event - */ - void SIPCallReleased(eXosip_event_t *event); - - /** - * Receive a new Message request - * Option/Notify/Message - * @param event eXosip Event - */ - void SIPMessageNew(eXosip_event_t *event); - - /** - * Find a SIPCall with cid from eXosip Event - * Explication there is no DID when the dialog is not establish... - * @param cid call ID - * @return 0 or SIPCall pointer - */ - SIPCall* findSIPCallWithCid(int cid); - - /** - * Find a SIPCall with cid and did from eXosip Event - * @param cid call ID - * @param did domain ID - * @return 0 or SIPCall pointer - */ - SIPCall* findSIPCallWithCidDid(int cid, int did); - SIPCall* getSIPCall(const CallID& id); - - /** To build sdp when call is on-hold */ - int sdp_hold_call (sdp_message_t * sdp); - /** To build sdp when call is off-hold */ - int sdp_off_hold_call (sdp_message_t * sdp); - - - - /** EventThread get every incoming events */ - EventThread* _evThread; - /** Tell if eXosip was stared (eXosip_init) */ - bool _initDone; - - /** Registration identifier, needed by unregister to build message */ - int _eXosipRegID; - - /** Number of voicemail */ - int _nMsgVoicemail; - - /** when we init the listener, how many times we try to bind a port? */ - int _nbTryListenAddr; - - /** Do we use stun? */ - bool _useStun; - - /** What is the stun server? */ - std::string _stunServer; - - /** Local Extern Address is the IP address seen by peers for SIP listener */ - std::string _localExternAddress; - - /** Local Extern Port is the port seen by peers for SIP listener */ - unsigned int _localExternPort; - - /** SIP Proxy URL */ - std::string _proxy; - - /** SIP UserPart */ - std::string _userpart; - - /** SIP Authenfication name */ - std::string _authname; - - /** SIP Authenfication password */ - std::string _password; - - /** Starting sound */ - AudioRtp _audiortp; + public: + + /** + * Constructor + * @param accountID The account identifier + */ + SIPVoIPLink(const AccountID& accountID); + + /** + * Destructor + */ + ~SIPVoIPLink(); + + int eXosip_running; + + /** + * Try to initiate the eXosip engine/thread and set config + * @return bool True if OK + */ + bool init(void); + + /** + * Delete link-related stuuf like calls + */ + void terminate(void); + + /** + * Check if a local IP can be found + * @return bool True if network is reachable + */ + bool checkNetwork(void); + + /** + * Event listener. Each event send by the call manager is received and handled from here + */ + void getEvent(void); + + /** + * Build and send SIP registration request + * @return bool True on success + * false otherwise + */ + bool sendRegister(void); + + /** + * Build and send SIP unregistration request + * @return bool True on success + * false otherwise + */ + bool sendUnregister(void); + + /** + * Place a new call + * @param id The call identifier + * @param toUrl The Sip address of the recipient of the call + * @return Call* The current call + */ + Call* newOutgoingCall(const CallID& id, const std::string& toUrl); + + /** + * Answer the call + * @param id The call identifier + * @return bool True on success + */ + bool answer(const CallID& id); + + /** + * Hang up the call + * @param id The call identifier + * @return bool True on success + */ + bool hangup(const CallID& id); + + /** + * Cancel the call + * @param id The call identifier + * @return bool True on success + */ + bool cancel(const CallID& id); + + /** + * Put the call on hold + * @param id The call identifier + * @return bool True on success + */ + bool onhold(const CallID& id); + + /** + * Put the call off hold + * @param id The call identifier + * @return bool True on success + */ + bool offhold(const CallID& id); + + /** + * Transfer the call + * @param id The call identifier + * @param to The recipient of the transfer + * @return bool True on success + */ + bool transfer(const CallID& id, const std::string& to); + + /** + * Refuse the call + * @param id The call identifier + * @return bool True on success + */ + bool refuse (const CallID& id); + + /** + * Send DTMF + * @param id The call identifier + * @param code The char code + * @return bool True on success + */ + bool carryingDTMFdigits(const CallID& id, char code); + + bool sendMessage(const std::string& to, const std::string& body); + + bool isContactPresenceSupported(); + + void subscribePresenceForContact(Contact* contact); + + void publishPresenceStatus(std::string status); + + // TODO Not used yet + void sendMessageToContact(const CallID& id, const std::string& message); + + /** + * If set to true, we check for a firewall + * @param use true if we use STUN + */ + void setUseStun(bool use) { _useStun = use; } + + /** + * The name of the STUN server + * @param server Server FQDN/IP + */ + void setStunServer(const std::string& server) { _stunServer = server; } + + /** + * Set the SIP proxy + * @param proxy Proxy FQDN/IP + */ + void setProxy(const std::string& proxy) { _proxy = proxy; } + + /** + * Set the user part + * @param userpart User part + */ + void setUserPart(const std::string& userpart) { _userpart = userpart; } + + /** + * Set the authentification name + * @param authname The authentification name + */ + void setAuthName(const std::string& authname) { _authname = authname; } + + /** + * Set the password + * @param password Password + */ + void setPassword(const std::string& password) { _password = password; } + + private: + + /** + * Terminate every call not hangup | brutal | Protected by mutex + */ + void terminateSIPCall(); + + /** + * Get the local Ip by eXosip + * only if the local ip address is to his default value: 127.0.0.1 + * setLocalIpAdress + * @return bool false if not found + */ + bool loadSIPLocalIP(); + + /** + * send SIP authentification + * @return bool true if sending succeed + */ + bool sendSIPAuthentification(); + + /** + * Get a SIP From header ("fullname" <sip:userpart@hostpart>) + * @param userpart User part + * @param hostpart Host name + * @return std::string SIP URI for from Header + */ + std::string SIPFromHeader(const std::string& userpart, const std::string& hostpart); + + /** + * Build a sip address with the number that you want to call + * Example: sip:124@domain.com + * @param to The header of the recipient + * @return std::string Result as a string + */ + std::string SIPToHeader(const std::string& to); + + /** + * Check if an url is sip-valid + * @param url The url to check + * @return bool True if osip tell that is valid + */ + bool SIPCheckUrl(const std::string& url); + + + /** + * Send an outgoing call invite + * @param call The current call + * @return bool True if all is correct + */ + bool SIPOutgoingInvite(SIPCall* call); + + /** + * Start a SIP Call + * @param call The current call + * @param subject Undocumented + * @return true if all is correct + */ + bool SIPStartCall(SIPCall* call, const std::string& subject); + + /** + * Get the Sip FROM url (add sip:, add @host, etc...) + * @return std::string The From url + */ + std::string getSipFrom(); + + /** + * Get the sip proxy (add sip: if there is one) + * @return std::string Empty string or <sip:proxy;lr> url + */ + std::string getSipRoute(); + + /** + * Get the Sip TO url (add sip:, add @host, etc...) + * @param to_url The To url + * @return std::string The SIP to address + */ + std::string getSipTo(const std::string& to_url); + + /** + * Set audio (SDP) configuration for a call + * localport, localip, localexternalport + * @param call a SIPCall valid pointer + * @return bool True + */ + bool setCallAudioLocal(SIPCall* call); + + /** + * Create a new call and send a incoming call notification to the user + * @param event eXosip Event + */ + void SIPCallInvite(eXosip_event_t *event); + + /** + * Use a exisiting call to restart the audio + * @param event eXosip Event + */ + void SIPCallReinvite(eXosip_event_t *event); + + /** + * Tell the user that the call is ringing + * @param event eXosip Event + */ + void SIPCallRinging(eXosip_event_t *event); + + /** + * Tell the user that the call was answered + * @param event eXosip Event + */ + void SIPCallAnswered(eXosip_event_t *event); + + /** + * Handling 4XX error + * @param event eXosip Event + */ + void SIPCallRequestFailure(eXosip_event_t *event); + + /** + * Handling 5XX/6XX error + * @param event eXosip Event + */ + void SIPCallServerFailure(eXosip_event_t *event); + + /** + * Handle registration failure cases ( SIP_FORBIDDEN , SIP_UNAUTHORIZED ) + * @param event eXosip event + */ + void SIPRegistrationFailure( eXosip_event_t *event ); + + /** + * Handling ack (restart audio if reinvite) + * @param event eXosip Event + */ + void SIPCallAck(eXosip_event_t *event); + + /** + * Handling message inside a call (like dtmf) + * @param event eXosip Event + */ + void SIPCallMessageNew(eXosip_event_t *event); + + /** + * Handle an INFO with application/dtmf-relay content-type + * @param event eXosip Event + */ + bool handleDtmfRelay(eXosip_event_t *event); + + /** + * Peer close the connection + * @param event eXosip Event + */ + void SIPCallClosed(eXosip_event_t *event); + + /** + * The call pointer was released + * If the call was not cleared before, report an error + * @param event eXosip Event + */ + void SIPCallReleased(eXosip_event_t *event); + + /** + * Receive a new Message request + * Option/Notify/Message + * @param event eXosip Event + */ + void SIPMessageNew(eXosip_event_t *event); + + /** + * Find a SIPCall with cid from eXosip Event + * Explication there is no DID when the dialog is not establish... + * @param cid call ID + * @return SIPCall* SIPCall pointer or 0 + */ + SIPCall* findSIPCallWithCid(int cid); + + /** + * Find a SIPCall with cid and did from eXosip Event + * @param cid call ID + * @param did domain ID + * @return SIPCall* SIPCall pointer or 0 + */ + SIPCall* findSIPCallWithCidDid(int cid, int did); + + /** + * SIPCall accessor + * @param id The call identifier + * @return SIPCall* A pointer on SIPCall object + */ + SIPCall* getSIPCall(const CallID& id); + + /** To build sdp when call is on-hold */ + int sdp_hold_call (sdp_message_t * sdp); + + /** To build sdp when call is off-hold */ + int sdp_off_hold_call (sdp_message_t * sdp); + + /** EventThread get every incoming events */ + EventThread* _evThread; + + /** Tell if eXosip was stared (eXosip_init) */ + bool _initDone; + + /** Registration identifier, needed by unregister to build message */ + int _eXosipRegID; + + /** Number of voicemail */ + int _nMsgVoicemail; + + /** when we init the listener, how many times we try to bind a port? */ + int _nbTryListenAddr; + + /** Do we use stun? */ + bool _useStun; + + /** What is the stun server? */ + std::string _stunServer; + + /** Local Extern Address is the IP address seen by peers for SIP listener */ + std::string _localExternAddress; + + /** Local Extern Port is the port seen by peers for SIP listener */ + unsigned int _localExternPort; + + /** SIP Proxy URL */ + std::string _proxy; + + /** SIP UserPart */ + std::string _userpart; + + /** SIP Authenfication name */ + std::string _authname; + + /** SIP Authenfication password */ + std::string _password; + + /** Starting sound */ + AudioRtp _audiortp; }; #endif diff --git a/src/user_cfg.h b/src/user_cfg.h index d55f124dd068d848574a60f7a2c125caadef77f1..6c94010836b867eeced149c586273b6d81b5ba6d 100644 --- a/src/user_cfg.h +++ b/src/user_cfg.h @@ -1,7 +1,8 @@ /* - * Copyright (C) 2004-2006 Savoir-Faire Linux inc. + * Copyright (C) 2004-2008 Savoir-Faire Linux inc. * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> + * Authoe: 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 @@ -23,73 +24,63 @@ #include <stdlib.h> -// Home directory -#define HOMEDIR (getenv ("HOME")) +#define HOMEDIR (getenv ("HOME")) /** Home directory */ -// TODO: change for a \ in Windows Environment -#define DIR_SEPARATOR_CH '/' -#define DIR_SEPARATOR_STR "/" +#define DIR_SEPARATOR_CH '/' /** Directory separator string */ +#define DIR_SEPARATOR_STR "/" /** Directory separator char */ -// Main menu -#define SIGNALISATION "VoIPLink" -#define AUDIO "Audio" -#define VIDEO "Video" -#define NETWORK "Network" -#define PREFERENCES "Preferences" +#define ACCOUNT_SIP0 "SIP0" /** Account type SIP */ +#define ACCOUNT_IAX0 "IAX0" /** Account type IAX */ -#define ACCOUNT_SIP0 "SIP0" -#define ACCOUNT_IAX0 "IAX0" +/** User configuration file fields */ +#define AUDIO "Audio" /** Section Audio */ +#define CODECS "ActiveCodecs" /** List of active codecs */ +#define ALSA_CARD_ID_IN "Alsa.cardID_In" /** Soundcard index to use for capture */ +#define ALSA_CARD_ID_OUT "Alsa.cardID_Out" /** Soundcard index to use for playback */ +#define ALSA_FRAME_SIZE "Alsa.framesize" /** Audio layer frame size */ +#define ALSA_PLUGIN "Alsa.plugin" /** Alsa plugin */ +#define ALSA_SAMPLE_RATE "Alsa.sampleRate" /** Audio layer sample rate */ +#define RING_CHOICE "Rings.ringChoice" /** Ringtone */ +#define VOLUME_SPKR "Volume.speakers" /** Speaker volume */ +#define VOLUME_MICRO "Volume.micro" /** Mic volume */ +#define VIDEO "Video" /** Section Video */ -// Fields to fill -#define SYMMETRIC "VoIPLink.symmetric" +#define PREFERENCES "Preferences" /** Section Preferences */ +#define CONFIG_DIALPAD "Dialpad.display" /** Display dialpad preferences */ +#define ZONE_TONE "Options.zoneToneChoice" /** Country tone */ +#define VOICEMAIL_NUM "Options.voicemailNumber" /** Voicemail number */ +#define CONFIG_RINGTONE "Ringtones.enable" /** Ringtones preferences */ +#define CONFIG_START "Start.hidden" /** SFLphone starts in the systm tray or not */ +#define CONFIG_POPUP "Window.popup" /** SFLphone pops up on incoming calls or not */ +#define CONFIG_ZEROCONF "Zeroconf.enable" /** Zero configuration networking module */ -#define PLAY_DTMF "DTMF.playDtmf" -#define PLAY_TONES "DTMF.playTones" -#define PULSE_LENGTH "DTMF.pulseLength" -#define SEND_DTMF_AS "DTMF.sendDTMFas" -#define ALSA_CARD_ID_IN "Alsa.cardID_In" -#define ALSA_CARD_ID_OUT "Alsa.cardID_Out" -#define ALSA_SAMPLE_RATE "Alsa.sampleRate" -#define ALSA_FRAME_SIZE "Alsa.framesize" -#define ALSA_PLUGIN "Alsa.plugin" -#define CODECS "ActiveCodecs" -#define RING_CHOICE "Rings.ringChoice" -#define ACCOUNT_SIP_COUNT_DEFAULT 4 -#define ACCOUNT_IAX_COUNT_DEFAULT 4 +#define SIGNALISATION "VoIPLink" /** Section Signalisation */ +#define PLAY_DTMF "DTMF.playDtmf" /** Whether or not should play dtmf */ +#define PLAY_TONES "DTMF.playTones" /** Whether or not should play tones */ +#define PULSE_LENGTH "DTMF.pulseLength" /** Length of the DTMF in millisecond */ +#define SEND_DTMF_AS "DTMF.sendDTMFas" /** DTMF send mode */ +#define SYMMETRIC "VoIPLink.symmetric" /** VoIP link type */ -// speakers and volume 0 to 100 -#define VOLUME_SPKR "Volume.speakers" -#define VOLUME_MICRO "Volume.micro" -#define ZONE_TONE "Options.zoneToneChoice" -#define VOICEMAIL_NUM "Options.voicemailNumber" -// zeroconfig module -#define CONFIG_ZEROCONF "Zeroconf.enable" -#define CONFIG_RINGTONE "Ringtones.enable" +#define EMPTY_FIELD "" /** Default value for empty field */ +#define DFT_STUN_SERVER "stun.fwdnet.net:3478" /** Default STUN server address */ +#define YES_STR "1" /** Default YES value */ +#define NO_STR "0" /** Default NO value */ +#define DFT_PULSE_LENGTH_STR "250" /** Default DTMF lenght */ +#define SIP_INFO_STR "0" /** Default DTMF transport mode */ +#define ALSA_DFT_CARD "0" /** Default sound card index */ +#define DFT_VOL_SPKR_STR "100" /** Default speaker volume */ +#define DFT_VOL_MICRO_STR "100" /** Default mic volume */ +#define DFT_RINGTONE "konga.ul" /** Default ringtone */ +#define DFT_ZONE "North America" /** Default geographical zone */ +#define DFT_VOICEMAIL "888" /** Default voicemail number */ +#define DFT_FRAME_SIZE "20" /** Default frame size in millisecond */ +#define DFT_SAMPLE_RATE "44100" /** Default sample rate in HZ */ -// Default values -#define EMPTY_FIELD "" -#define DFT_STUN_SERVER "stun.fwdnet.net:3478" -#define YES_STR "1" -#define NO_STR "0" -#define DFT_PULSE_LENGTH_STR "250" -#define SIP_INFO_STR "0" -#define ALSA_DFT_CARD "0" -// volume by default 100% -#define DFT_VOL_SPKR_STR "100" -#define DFT_VOL_MICRO_STR "100" - -#define DFT_RINGTONE "konga.ul" -#define DFT_ZONE "North America" -#define DFT_VOICEMAIL "888" -#define DFT_FRAME_SIZE "20" -#define DFT_SAMPLE_RATE "44100" - -// zeroconfig default value #ifdef USE_ZEROCONF -#define CONFIG_ZEROCONF_DEFAULT_STR "1" +#define CONFIG_ZEROCONF_DEFAULT_STR "1" /** Default Zero configuration networking module value */ #else -#define CONFIG_ZEROCONF_DEFAULT_STR "0" +#define CONFIG_ZEROCONF_DEFAULT_STR "0" /** Default Zero configuration networking module value */ #endif #endif // __USER_CFG_H__ diff --git a/src/voiplink.cpp b/src/voiplink.cpp index 7da85fa6f5b5a98c87e332faf20a87e1b904d284..84a44a9ccaa82e4764cff8d853609f1309b49985 100644 --- a/src/voiplink.cpp +++ b/src/voiplink.cpp @@ -25,7 +25,7 @@ #include "voiplink.h" #include "manager.h" -VoIPLink::VoIPLink(const AccountID& accountID) : _accountID(accountID), _localIPAddress("127.0.0.1"), _localPort(0), _registrationError(""), _initDone(false) +VoIPLink::VoIPLink(const AccountID& accountID) : _accountID(accountID), _localIPAddress("127.0.0.1"), _localPort(0), _registrationError(NO_ERROR), _initDone(false) { } @@ -82,23 +82,38 @@ VoIPLink::clearCallMap() } void -VoIPLink::setRegistrationState(const enum RegistrationState state, const std::string& errorMessage) +VoIPLink::setRegistrationState(const enum RegistrationState state, const int& errorCode) { - /** @todo Push to the GUI when state changes */ _registrationState = state; - _registrationError = errorMessage; + _registrationError = errorCode; + std::string acc_ID = getAccountID(); + + /** Push to the GUI when state changes */ switch (state) { case Registered: - Manager::instance().registrationSucceed(getAccountID()); + Manager::instance().registrationSucceed(acc_ID); break; case Trying: - //Manager::instance(). some function to say that + Manager::instance().registrationTrying( acc_ID); break; case Error: - Manager::instance().registrationFailed(getAccountID()); + Manager::instance().registrationFailed(acc_ID); + // Notify the error to the client + if( _registrationError != NO_ERROR ) + Manager::instance().notifyErrClient( errorCode ); + break; + case ErrorAuth: + Manager::instance().registrationFailed(acc_ID); + break; + case ErrorNetwork: + Manager::instance().registrationFailed(acc_ID); break; case Unregistered: + Manager::instance().unregistrationSucceed(acc_ID); + break; + case ErrorHost: + Manager::instance().registrationFailed(acc_ID); break; } } @@ -106,7 +121,7 @@ VoIPLink::setRegistrationState(const enum RegistrationState state, const std::st void VoIPLink::setRegistrationState(const enum RegistrationState state) { - setRegistrationState(state, ""); + setRegistrationState(state, NO_ERROR); } // NOW diff --git a/src/voiplink.h b/src/voiplink.h index 73c16896b55204b6ff8b3287b21a403c82d6eb19..4f4672e73e69af1cd87ea51edff18289cdb5e643 100644 --- a/src/voiplink.h +++ b/src/voiplink.h @@ -30,190 +30,290 @@ class AudioCodec; -//#include "account.h" // for AccountID -// replaced by: +/** Define AccountID type */ typedef std::string AccountID; +/** Define a map that associate a Call object to a call identifier */ typedef std::map<CallID, Call*> CallMap; /** - * Listener and manager interface for each VoIP protocol + * @file voiplink.h + * @brief Listener and manager interface for each VoIP protocol */ class VoIPLink { -public: - VoIPLink(const AccountID& accountID); - virtual ~VoIPLink (void); - - enum RegistrationState {Unregistered, Trying, Registered, Error}; - - // Pure virtual functions - virtual void getEvent (void) = 0; - virtual bool init (void) = 0; - virtual bool checkNetwork (void) = 0; - virtual void terminate (void) = 0; - virtual bool sendRegister (void) = 0; - virtual bool sendUnregister (void) = 0; - - /** Add a new outgoing call and return the call pointer or 0 if and error occurs */ - virtual Call* newOutgoingCall(const CallID& id, const std::string& toUrl) = 0; - virtual bool answer(const CallID& id) = 0; - - /** - * Hang up a call - */ - virtual bool hangup(const CallID& id) = 0; - - /** - * Cancel the call dialing - */ - virtual bool cancel(const CallID& id) = 0; - - /** - * Put a call on hold - */ - virtual bool onhold(const CallID& id) = 0; - - /** - * Resume a call from hold state - */ - virtual bool offhold(const CallID& id) = 0; - - /** - * Transfer a call to specified URI - */ - virtual bool transfer(const CallID& id, const std::string& to) = 0; - - /** - * Refuse incoming call - */ - virtual bool refuse(const CallID& id) = 0; - - virtual bool carryingDTMFdigits(const CallID& id, char code) = 0; - - /** - * Send text message - */ - virtual bool sendMessage(const std::string& to, const std::string& body) = 0; - - // NOW - /** - * Determine if link supports presence information - */ - virtual bool isContactPresenceSupported() = 0; - - /** - * Register contacts for presence information if supported - */ - virtual void subscribePresenceForContact(Contact* contact); - - /** - * Publish presence status to server - */ - virtual void publishPresenceStatus(std::string status); - - // these method are set only with 'Account init' and can be get by everyone - void setFullName (const std::string& fullname) { _fullname = fullname; } - std::string& getFullName (void) { return _fullname; } - void setHostName (const std::string& hostname) { _hostname = hostname; } - std::string& getHostName (void) { return _hostname; } - - /** - * Return parent Account's ID - */ - AccountID& getAccountID(void) { return _accountID; } - - /** Get the call pointer from the call map (protected by mutex) - * @param id A Call ID - * @return call pointer or 0 - */ - Call* getCall(const CallID& id); - - /** - * Get registration state - */ - enum RegistrationState getRegistrationState() { return _registrationState; } - - /** - * Get registration error message, if set. - */ - std::string getRegistrationError() { return _registrationError; } - - /** - * Set new registration state - * - * We use this function, in case the server needs to PUSH to the - * GUI when the state changes. - */ - void setRegistrationState(const enum RegistrationState state, - const std::string& errorMessage); - - /** - * Same, but with default error value to "" - */ - void setRegistrationState(const enum RegistrationState state); - -private: - /** - * Full name used as outgoing Caller ID - */ - std::string _fullname; - - /** - * Host name used for authentication - */ - std::string _hostname; - - /** - * ID of parent's Account - */ - AccountID _accountID; - - /** - * State of registration - */ - enum RegistrationState _registrationState; - - /** - * Registration error message - */ - std::string _registrationError; - -protected: - /** Add a call to the call map (protected by mutex) - * @param call A call pointer with a unique pointer - * @return true if the call was unique and added - */ - bool addCall(Call* call); - - /** Remove a call from the call map (protected by mutex) - * @param id A Call ID - * @return true if the call was correctly removed - */ - bool removeCall(const CallID& id); - - /** - * Remove all the call from the map - */ - bool clearCallMap(); - - /** Contains all the calls for this Link, protected by mutex */ - CallMap _callMap; - - /** Mutex to protect call map */ - ost::Mutex _callMapMutex; - - /** Get Local IP Address (ie: 127.0.0.1, 192.168.0.1, ...) */ - std::string _localIPAddress; - /** Get local listening port (5060 for SIP, ...) */ - unsigned int _localPort; - - - /** Whether init() was called already or not - * - * This should be used in [IAX|SIP]VoIPLink::init() and terminate(), to - * indicate that init() was called, or reset by terminate(). - */ - bool _initDone; + public: + + /** + * Constructor + * @param accountID The account identifier + */ + VoIPLink(const AccountID& accountID); + + /** + * Virtual destructor + */ + virtual ~VoIPLink (void); + + /** Contains all the state an Voip can be in */ + enum RegistrationState {Unregistered, Trying, Registered, Error, ErrorAuth , ErrorNetwork , ErrorHost}; + + /** + * Virtual method + * Event listener. Each event send by the call manager is received and handled from here + */ + virtual void getEvent (void) = 0; + + /** + * Virtual method + * Try to initiate the eXosip engine/thread and set config + * @return bool True if OK + */ + virtual bool init (void) = 0; + + /** + * Virtual method + * Check if a local IP can be found + * @return bool True if network is reachable + */ + virtual bool checkNetwork (void) = 0; + + /** + * Virtual method + * Delete link-related stuuf like calls + */ + virtual void terminate (void) = 0; + + /** + * Virtual method + * Build and send SIP registration request + * @return bool True on success + * false otherwise + */ + virtual bool sendRegister (void) = 0; + + /** + * Virtual method + * Build and send SIP unregistration request + * @return bool True on success + * false otherwise + */ + virtual bool sendUnregister (void) = 0; + + /** + * Place a new call + * @param id The call identifier + * @param toUrl The Sip address of the recipient of the call + * @return Call* The current call + */ + virtual Call* newOutgoingCall(const CallID& id, const std::string& toUrl) = 0; + /** + * Answer the call + * @param id The call identifier + * @return bool True on success + */ + virtual bool answer(const CallID& id) = 0; + + /** + * Hang up a call + * @param id The call identifier + * @return bool True on success + */ + virtual bool hangup(const CallID& id) = 0; + + /** + * Cancel the call dialing + * @param id The call identifier + * @return bool True on success + */ + virtual bool cancel(const CallID& id) = 0; + + /** + * Put a call on hold + * @param id The call identifier + * @return bool True on success + */ + virtual bool onhold(const CallID& id) = 0; + + /** + * Resume a call from hold state + * @param id The call identifier + * @return bool True on success + */ + virtual bool offhold(const CallID& id) = 0; + + /** + * Transfer a call to specified URI + * @param id The call identifier + * @param to The recipient of the call + * @return bool True on success + */ + virtual bool transfer(const CallID& id, const std::string& to) = 0; + + /** + * Refuse incoming call + * @param id The call identifier + * @return bool True on success + */ + virtual bool refuse(const CallID& id) = 0; + + /** + * Send DTMF + * @param id The call identifier + * @param code The char code + * @return bool True on success + */ + virtual bool carryingDTMFdigits(const CallID& id, char code) = 0; + + /** + * Send text message + */ + virtual bool sendMessage(const std::string& to, const std::string& body) = 0; + + // NOW + /** + * Determine if link supports presence information + */ + virtual bool isContactPresenceSupported() = 0; + + /** + * Register contacts for presence information if supported + */ + virtual void subscribePresenceForContact(Contact* contact); + + /** + * Publish presence status to server + */ + virtual void publishPresenceStatus(std::string status); + + /** + * Set the account full name + * @param fullname The full name + */ + void setFullName (const std::string& fullname) { _fullname = fullname; } + + /** + * Get the account full name + * @return std::string The full name + */ + std::string& getFullName (void) { return _fullname; } + + /** + * Set the account host name + * @param hostname The host name + */ + void setHostName (const std::string& hostname) { _hostname = hostname; } + + /** + * Get the account host name + * @return std::string The host name + */ + std::string& getHostName (void) { return _hostname; } + + /** + * @return AccountID parent Account's ID + */ + AccountID& getAccountID(void) { return _accountID; } + + /** + * @param accountID The account identifier + */ + void setAccountID( const AccountID& accountID) { _accountID = accountID; } + + /** Get the call pointer from the call map (protected by mutex) + * @param id A Call ID + * @return Call* Call pointer or 0 + */ + Call* getCall(const CallID& id); + + /** + * Get registration state + * @return RegistrationState + */ + enum RegistrationState getRegistrationState() { return _registrationState; } + + /** + * Get registration error message, if set. + */ + int getRegistrationError() { return _registrationError; } + + /** + * Set new registration state + * We use this function, in case the server needs to PUSH to the + * GUI when the state changes. + * @param state The registration state + * @param errorCode The error code + */ + void setRegistrationState(const enum RegistrationState state, + const int& errorCode); + + /** + * Set new registration state + * @param state The registration state + */ + void setRegistrationState(const enum RegistrationState state); + + private: + /** + * Full name used as outgoing Caller ID + */ + std::string _fullname; + + /** + * Host name used for authentication + */ + std::string _hostname; + + /** + * ID of parent's Account + */ + AccountID _accountID; + + /** + * State of registration + */ + enum RegistrationState _registrationState; + + /** + * Registration error code -> refers to global.h + */ + int _registrationError; + + protected: + /** Add a call to the call map (protected by mutex) + * @param call A call pointer with a unique pointer + * @return bool True if the call was unique and added + */ + bool addCall(Call* call); + + /** Remove a call from the call map (protected by mutex) + * @param id A Call ID + * @return bool True if the call was correctly removed + */ + bool removeCall(const CallID& id); + + /** + * Remove all the call from the map + * @return bool True on success + */ + bool clearCallMap(); + + /** Contains all the calls for this Link, protected by mutex */ + CallMap _callMap; + + /** Mutex to protect call map */ + ost::Mutex _callMapMutex; + + /** Get Local IP Address (ie: 127.0.0.1, 192.168.0.1, ...) */ + std::string _localIPAddress; + + /** Get local listening port (5060 for SIP, ...) */ + unsigned int _localPort; + + /** Whether init() was called already or not + * This should be used in [IAX|SIP]VoIPLink::init() and terminate(), to + * indicate that init() was called, or reset by terminate(). + */ + bool _initDone; }; #endif // __VOIP_LINK_H__