diff --git a/daemon/src/dbus/callmanager-introspec.xml b/daemon/src/dbus/callmanager-introspec.xml index a742426b77507d01a447521eca94b2237ad136f1..9aa97ca930901f35d6e17d5041cf05b0f0b82208 100644 --- a/daemon/src/dbus/callmanager-introspec.xml +++ b/daemon/src/dbus/callmanager-introspec.xml @@ -375,6 +375,7 @@ <li>DISPLAY_NAME</li> <li>CALL_STATE</li> <li>CALL_TYPE</li> + <li>CONF_ID</li> </ul> </tp:docstring> </arg> diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index 490840e1aa0fb0d7e29bdc9ba1cde19f72198a6a..165f8e33d279f92b81d4da6f236771ec08b17a4f 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -2785,6 +2785,7 @@ std::map<std::string, std::string> ManagerImpl::getCallDetails(const std::string call_details["DISPLAY_NAME"] = call->getDisplayName(); call_details["CALL_STATE"] = call->getStateStr(); call_details["CALL_TYPE"] = type.str(); + call_details["CONF_ID"] = call->getConfId(); } else { ERROR("Call is NULL"); call_details["ACCOUNTID"] = ""; diff --git a/gnome/src/actions.c b/gnome/src/actions.c index 0f5fbdcfed9578dbf2d50ac5801db369a55aa375..9bb8954b072c3815f0877ef12c569669909ad0bc 100644 --- a/gnome/src/actions.c +++ b/gnome/src/actions.c @@ -277,9 +277,6 @@ gboolean sflphone_init(GError **error) // Fetch the ip2ip profile sflphone_fill_ip2ip_profile(); - // Fetch the conference list - sflphone_fill_conference_list(); - return TRUE; } @@ -954,11 +951,14 @@ void sflphone_fill_call_list(void) for (gchar **calls = list; calls && *calls; ++calls) { gchar *callID = *calls; - callable_obj_t *c = create_new_call_from_details(*calls, dbus_get_call_details(*calls)); - g_free(callID); - c->_zrtp_confirmed = FALSE; - calllist_add_call(current_calls_tab, c); - calltree_add_call(current_calls_tab, c, NULL); + if (!calllist_get_call(current_calls_tab, callID)) { + callable_obj_t *c = create_new_call_from_details(*calls, dbus_get_call_details(*calls)); + g_free(callID); + c->_zrtp_confirmed = FALSE; + calllist_add_call(current_calls_tab, c); + if (!c->_confID || strlen(c->_confID) == 0) + calltree_add_call(current_calls_tab, c, NULL); + } } g_strfreev(list); @@ -1001,7 +1001,7 @@ static void fill_treeview_with_calls(void) for (guint i = 0; i < n; ++i) { QueueElement *element = calllist_get_nth(history_tab, i); - if (element->type == HIST_CALL) + if (element->type == CALL_ELEMENT) calltree_add_history_entry(element->elem.call); } } diff --git a/gnome/src/callable_obj.c b/gnome/src/callable_obj.c index 545773077313fafe8aaf7e0aa6e0d4250a9846a9..e70a5ca9fe00c280cde90b345283d43da1bc8206 100644 --- a/gnome/src/callable_obj.c +++ b/gnome/src/callable_obj.c @@ -36,10 +36,10 @@ #include <glib/gi18n.h> #include "contacts/calltab.h" #include "contacts/calltree.h" +#include "logger.h" #include "dbus.h" #include <unistd.h> - gint get_state_callstruct(gconstpointer a, gconstpointer b) { callable_obj_t * c = (callable_obj_t*) a; @@ -146,6 +146,7 @@ callable_obj_t *create_new_call_from_details(const gchar *call_id, GHashTable *d const gchar * const peer_number = g_hash_table_lookup(details, "PEER_NUMBER"); const gchar * const display_name = g_hash_table_lookup(details, "DISPLAY_NAME"); const gchar * const state_str = g_hash_table_lookup(details, "CALL_STATE"); + const gchar * const conf_id = g_hash_table_lookup(details, "CONF_ID"); if (utf8_case_equal(state_str, "CURRENT")) state = CALL_STATE_CURRENT; @@ -162,6 +163,7 @@ callable_obj_t *create_new_call_from_details(const gchar *call_id, GHashTable *d gchar *number = call_get_peer_number(peer_number); callable_obj_t *c = create_new_call(CALL, state, call_id, accountID, display_name, number); + c->_confID = g_strdup(conf_id); g_free(number); return c; } @@ -307,3 +309,22 @@ gboolean call_was_outgoing(callable_obj_t * obj) { return g_strcmp0(obj->_history_state, OUTGOING_STRING) == 0; } + +void restore_call(const gchar *id) +{ + DEBUG("Restoring call %s", id); + // We fetch the details associated to the specified call + GHashTable *call_details = dbus_get_call_details(id); + if (!call_details) { + ERROR("Invalid call ID"); + return; + } + callable_obj_t *new_call = create_new_call_from_details(id, call_details); + + if (utf8_case_equal(g_hash_table_lookup(call_details, "CALL_TYPE"), INCOMING_STRING)) + new_call->_history_state = g_strdup(INCOMING_STRING); + else + new_call->_history_state = g_strdup(OUTGOING_STRING); + + calllist_add_call(current_calls_tab, new_call); +} diff --git a/gnome/src/conference_obj.c b/gnome/src/conference_obj.c index 5f3ce84f5018fd3d4e52b546fb7e86ae34f3f564..69d022827cb0024cdc4731f6fa531d3e789a805b 100644 --- a/gnome/src/conference_obj.c +++ b/gnome/src/conference_obj.c @@ -147,7 +147,7 @@ void conference_participant_list_update(gchar** participants, conference_obj_t* const gchar *call_id = (const gchar *) (*part); callable_obj_t *call = calllist_get_call(current_calls_tab, call_id); - if (call->_confID != NULL) { + if (call) { g_free(call->_confID); call->_confID = NULL; } @@ -161,6 +161,10 @@ void conference_participant_list_update(gchar** participants, conference_obj_t* for (gchar **part = participants; part && *part; ++part) { gchar *call_id = (gchar *) (*part); callable_obj_t *call = calllist_get_call(current_calls_tab, call_id); + if (!call) { + restore_call(call_id); + call = calllist_get_call(current_calls_tab, call_id); + } call->_confID = g_strdup(conf->_confID); conference_add_participant(call_id, conf); } diff --git a/gnome/src/contacts/calllist.c b/gnome/src/contacts/calllist.c index 3c00fa83bdbdff3d05b035a1ae3694718c5f9aee..b4f4ad101f6cc911648acb7e0b46baea7f240a71 100644 --- a/gnome/src/contacts/calllist.c +++ b/gnome/src/contacts/calllist.c @@ -42,10 +42,11 @@ gint is_callID_callstruct(gconstpointer a, gconstpointer b) { const QueueElement *c = a; - if (c == NULL || c->type != HIST_CALL) + // if it's null or a conference it's not the call we're looking for + if (c == NULL || c->type != CALL_ELEMENT) return 1; - return utf8_case_cmp(c->elem.call->_callID, (const gchar *) b); + return g_strcmp0(c->elem.call->_callID, (const gchar *) b); } // TODO : try to do this more generically @@ -93,7 +94,7 @@ calllist_free_element(gpointer data, gpointer user_data UNUSED) { QueueElement *element = data; - g_assert(element->type == HIST_CALL); + g_assert(element->type == CALL_ELEMENT); free_callable_obj_t(element->elem.call); g_free(element); @@ -116,17 +117,19 @@ calllist_reset(calltab_t* tab) void calllist_add_call(calltab_t* tab, callable_obj_t * c) { + DEBUG("Adding call with callID %s to tab %s", c->_callID, tab->_name); QueueElement *element = g_new0(QueueElement, 1); - element->type = HIST_CALL; + element->type = CALL_ELEMENT; element->elem.call = c; g_queue_push_tail(tab->callQueue, (gpointer) element); + DEBUG("Tab %s has %d calls", tab->_name, calllist_get_size(tab)); } void calllist_add_call_to_front(calltab_t* tab, callable_obj_t * c) { QueueElement *element = g_new0(QueueElement, 1); - element->type = HIST_CALL; + element->type = CALL_ELEMENT; element->elem.call = c; g_queue_push_head(tab->callQueue, (gpointer) element); } @@ -139,7 +142,7 @@ calllist_clean_history(void) for (guint i = 0; i < size; i++) { QueueElement* c = calllist_get_nth(history_tab, i); - if (c->type == HIST_CALL) + if (c->type == CALL_ELEMENT) calltree_remove_call(history_tab, c->elem.call); } @@ -163,7 +166,7 @@ calllist_remove_call(calltab_t* tab, const gchar * callID) QueueElement *element = (QueueElement *) c->data; - if (element->type != HIST_CALL) { + if (element->type != CALL_ELEMENT) { ERROR("CallList: Error: Element %s is not a call", callID); return; } @@ -203,14 +206,14 @@ calllist_get_call(calltab_t* tab, const gchar * callID) GList * c = g_queue_find_custom(tab->callQueue, callID, is_callID_callstruct); if (c == NULL) { - ERROR("CallList: Error: Could not find call %s", callID); + ERROR("Could not find call %s in tab %s", callID, tab->_name); return NULL; } QueueElement *element = c->data; - if (element->type != HIST_CALL) { - ERROR("CallList: Error: Element %s is not a call", callID); + if (element->type != CALL_ELEMENT) { + ERROR("Element %s is not a call", callID); return NULL; } diff --git a/gnome/src/contacts/calllist.h b/gnome/src/contacts/calllist.h index b69814b5e14d4549878e6747d6a72e8358fc8a0e..6382dfbeb90b780e996ff1a86e35c5492be640ba 100644 --- a/gnome/src/contacts/calllist.h +++ b/gnome/src/contacts/calllist.h @@ -39,7 +39,7 @@ * @brief A list to hold calls. */ -typedef enum { HIST_CALL } ElementType; +typedef enum { CALL_ELEMENT, CONF_ELEMENT } ElementType; typedef union { callable_obj_t *call; diff --git a/gnome/src/contacts/calltree.c b/gnome/src/contacts/calltree.c index 91718789a2fb5edd155821e067119a11f220140c..666a65868a8b69429e274ba7298f4b76fd00be7d 100644 --- a/gnome/src/contacts/calltree.c +++ b/gnome/src/contacts/calltree.c @@ -571,7 +571,7 @@ calltree_remove_call_recursive(calltab_t* tab, gconstpointer callable, GtkTreeIt GtkTreeModel *model = GTK_TREE_MODEL(store); if (!callable) - ERROR("Error: Not a valid call"); + ERROR("Not a valid call"); int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), parent); @@ -935,14 +935,14 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) account_t *account_details = NULL; if (!conf) { - ERROR("Calltree: Error: Conference is null"); + ERROR("Conference is null"); return; } else if (!conf->_confID) { - ERROR("Calltree: Error: Conference ID is null"); + ERROR("Conference ID is null"); return; } - DEBUG("Calltree: Add conference %s", conf->_confID); + DEBUG("Add conference %s", conf->_confID); GtkTreeIter iter; gtk_tree_store_append(current_calls_tab->store, &iter, NULL); @@ -989,33 +989,33 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) conf->_conference_secured = TRUE; if (conf->participant_list) { - DEBUG("Calltree: Determine if at least one participant uses SRTP"); + DEBUG("Determine if at least one participant uses SRTP"); for (GSList *part = conf->participant_list; part; part = g_slist_next(part)) { const gchar * const call_id = (const gchar *) part->data; callable_obj_t *call = calllist_get_call(current_calls_tab, call_id); if (call == NULL) - ERROR("Calltree: Error: Could not find call %s in call list", call_id); + ERROR("Could not find call %s in call list", call_id); else { account_details = account_list_get_by_id(call->_accountID); gchar *srtp_enabled = ""; if (!account_details) - ERROR("Calltree: Error: Could not find account %s in account list", call->_accountID); + ERROR("Could not find account %s in account list", call->_accountID); else srtp_enabled = g_hash_table_lookup(account_details->properties, ACCOUNT_SRTP_ENABLED); if (utf8_case_equal(srtp_enabled, "true")) { - DEBUG("Calltree: SRTP enabled for participant %s", call_id); + DEBUG("SRTP enabled for participant %s", call_id); conf->_conf_srtp_enabled = TRUE; break; } else - DEBUG("Calltree: SRTP is not enabled for participant %s", call_id); + DEBUG("SRTP is not enabled for participant %s", call_id); } } - DEBUG("Calltree: Determine if all conference participants are secured"); + DEBUG("Determine if all conference participants are secured"); if (conf->_conf_srtp_enabled) { for (GSList *part = conf->participant_list; part; part = g_slist_next(part)) { @@ -1024,11 +1024,11 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) if (call) { if (call->_srtp_state == SRTP_STATE_UNLOCKED) { - DEBUG("Calltree: Participant %s is not secured", call_id); + DEBUG("Participant %s is not secured", call_id); conf->_conference_secured = FALSE; break; } else - DEBUG("Calltree: Participant %s is secured", call_id); + DEBUG("Participant %s is secured", call_id); } } } @@ -1036,15 +1036,15 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) if (conf->_conf_srtp_enabled) { if (conf->_conference_secured) { - DEBUG("Calltree: Conference is secured"); + DEBUG("Conference is secured"); pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL); } else { - DEBUG("Calltree: Conference is not secured"); + DEBUG("Conference is not secured"); pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); } } - DEBUG("Calltree: Add conference to tree store"); + DEBUG("Add conference to tree store"); gchar *description = g_markup_printf_escaped("<b>%s</b>", ""); gtk_tree_store_set(current_calls_tab->store, &iter, @@ -1164,7 +1164,7 @@ void calltree_display(calltab_t *tab) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(contactButton_), TRUE); set_focus_on_addressbook_searchbar(); } else - ERROR("Error: Not a valid call tab (%d, %s)", __LINE__, __FILE__); + ERROR("Not a valid call tab (%d, %s)", __LINE__, __FILE__); gtk_widget_hide(active_calltree_tab->tree); active_calltree_tab = tab; @@ -1556,11 +1556,14 @@ void drag_data_received_cb(GtkWidget *widget, GdkDragContext *context UNUSED, gi static void menuitem_response(gchar * string) { - if (g_strcmp0(string, SFL_CREATE_CONFERENCE) == 0) + if (g_strcmp0(string, SFL_CREATE_CONFERENCE) == 0) { dbus_join_participant(calltree_source_call_for_drag->_callID, calltree_dest_call->_callID); + calltree_remove_call(current_calls_tab, calltree_source_call); + calltree_remove_call(current_calls_tab, calltree_dest_call); + } else if (g_strcmp0(string, SFL_TRANSFER_CALL) == 0) { - DEBUG("Calltree: Transferring call %s, to %s", + DEBUG("Transferring call %s, to %s", calltree_source_call->_peer_number, calltree_dest_call->_peer_number); dbus_attended_transfer(calltree_source_call, calltree_dest_call); diff --git a/gnome/src/dbus/callmanager-introspec.xml b/gnome/src/dbus/callmanager-introspec.xml index 0682fb319c33f663548c74b9ef0db686ed3b94f1..9aa97ca930901f35d6e17d5041cf05b0f0b82208 100644 --- a/gnome/src/dbus/callmanager-introspec.xml +++ b/gnome/src/dbus/callmanager-introspec.xml @@ -375,6 +375,7 @@ <li>DISPLAY_NAME</li> <li>CALL_STATE</li> <li>CALL_TYPE</li> + <li>CONF_ID</li> </ul> </tp:docstring> </arg> @@ -671,7 +672,7 @@ </arg> </signal> - <signal name="transferSucceded" tp:name-for-bindings="transferSucceded"> + <signal name="transferSucceeded" tp:name-for-bindings="transferSucceeded"> <tp:docstring> <p>Transfer has been successfully processed. Client should remove transfered @@ -682,7 +683,7 @@ <signal name="transferFailed" tp:name-for-bindings="transferFailed"> <tp:docstring> - <p>Transfer operation failed. Corespondin + <p>Transfer operation failed. Corresponding call is no longer accessible in SFLphone-daemon.</p> </tp:docstring> diff --git a/gnome/src/dbus/dbus.c b/gnome/src/dbus/dbus.c index 73975e6e18928b39880b1159dfc13c28e1a90680..a20f3a3745c313c08cdd7bfd1b60d4c8be423384 100644 --- a/gnome/src/dbus/dbus.c +++ b/gnome/src/dbus/dbus.c @@ -215,7 +215,7 @@ process_existing_call_state_change(callable_obj_t *c, const gchar *state) /** * This function process call state changes in case the call have not been created yet. - * This mainly occurs when anotehr SFLphone client takes actions. + * This mainly occurs when another SFLphone client takes actions. */ static void process_nonexisting_call_state_change(const gchar *callID, const gchar *state) @@ -229,7 +229,7 @@ process_nonexisting_call_state_change(const gchar *callID, const gchar *state) } else if (g_strcmp0(state, "HUNGUP") == 0) return; // Could occur if a user picked up the phone and hung up without making a call - // The callID is unknow, threat it like a new call + // The callID is unknown, treat it like a new call // If it were an incoming call, we won't be here // It means that a new call has been initiated with an other client (cli for instance) if (g_strcmp0(state, "RINGING") == 0 || @@ -238,17 +238,10 @@ process_nonexisting_call_state_change(const gchar *callID, const gchar *state) DEBUG("DBUS: New ringing call! accountID: %s", callID); - // We fetch the details associated to the specified call - GHashTable *call_details = dbus_get_call_details(callID); - callable_obj_t *new_call = create_new_call_from_details(callID, call_details); - - if (utf8_case_equal(g_hash_table_lookup(call_details, "CALL_TYPE"), INCOMING_STRING)) - new_call->_history_state = g_strdup(INCOMING_STRING); - else - new_call->_history_state = g_strdup(OUTGOING_STRING); - - calllist_add_call(current_calls_tab, new_call); - calltree_add_call(current_calls_tab, new_call, NULL); + restore_call(callID); + callable_obj_t *new_call = calllist_get_call(current_calls_tab, callID); + if (new_call) + calltree_add_call(current_calls_tab, new_call, NULL); update_actions(); calltree_display(current_calls_tab); } @@ -417,7 +410,7 @@ record_playback_stopped_cb(DBusGProxy *proxy UNUSED, const gchar *filepath) if (element == NULL) { ERROR("DBUS: ERROR: Could not find %dth call", i); break; - } else if (element->type == HIST_CALL) { + } else if (element->type == CALL_ELEMENT) { if (g_strcmp0(element->elem.call->_recordfile, filepath) == 0) element->elem.call->_record_is_playing = FALSE; } @@ -1476,7 +1469,7 @@ dbus_is_iax2_enabled() void dbus_join_participant(const gchar *sel_callID, const gchar *drag_callID) { - DEBUG("DBUS: Join participant %s and %s\n", sel_callID, drag_callID); + DEBUG("Join participant %s and %s\n", sel_callID, drag_callID); GError *error = NULL; org_sflphone_SFLphone_CallManager_join_participant(call_proxy, sel_callID, drag_callID, &error); check_error(error); diff --git a/gnome/src/main.c b/gnome/src/main.c index e8a52457e724eeea02470007e9a25983c963b24f..7c5da73a9639c3530c9c79977b22fb5d0c952dd2 100644 --- a/gnome/src/main.c +++ b/gnome/src/main.c @@ -115,8 +115,8 @@ main(int argc, char *argv[]) status_bar_display_account(); sflphone_fill_history(); - sflphone_fill_call_list(); sflphone_fill_conference_list(); + sflphone_fill_call_list(); history_search_init(); // Update the GUI diff --git a/gnome/src/mainwindow.c b/gnome/src/mainwindow.c index c57a325fc22573a65a128a813ca9d123fb69aca5..26c3118fa74f9cf75e9ebd89f75b2ad176920d95 100644 --- a/gnome/src/mainwindow.c +++ b/gnome/src/mainwindow.c @@ -130,6 +130,7 @@ main_window_ask_quit() question = _("There is one call in progress."); else question = _("There are calls in progress."); + DEBUG("Currently %d calls in progress", calllist_get_size(current_calls_tab)); GtkWidget *dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s\n%s",