actions.c 45.4 KB
Newer Older
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
1
/*
2
 *  Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
3
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
4
 *  Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
Emmanuel Milou's avatar
Emmanuel Milou committed
5
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
6 7
 *  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
8
 *  the Free Software Foundation; either version 3 of the License, or
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
9
 *  (at your option) any later version.
Emmanuel Milou's avatar
Emmanuel Milou committed
10
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
11 12 13 14
 *  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.
Emmanuel Milou's avatar
Emmanuel Milou committed
15
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
16 17 18
 *  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.
19 20 21 22 23 24 25 26 27 28 29
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
30
 */
31

32 33 34
#include <gtk/gtk.h>
#include <glib/gprintf.h>
#include <stdlib.h>
35
#include <string.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
36 37
#include <sys/types.h>
#include <unistd.h>
38
#include <assert.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
39

40
#include <arpa/nameser.h>
41
#include <netinet/in.h>
42 43
#include <resolv.h>

44
#include <linux/if.h>
45 46 47 48
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

49 50 51 52 53 54 55 56 57
#include "actions.h"
#include "dbus/dbus.h"
#include "contacts/searchbar.h"
#include "contacts/addrbookfactory.h"
#include "icons/icon_factory.h"
#include "imwindow.h"
#include "statusicon.h"
#include "widget/imwidget.h"

58

59
static GHashTable * ip2ip_profile=NULL;
60

61
static gchar ** sflphone_order_history_hash_table(GHashTable *result)
62 63
{
    GHashTableIter iter;
64 65
    gint size = 0;
    gchar **ordered_list = NULL;
66

67
    assert(result);
68
    while (g_hash_table_size (result)) {
69
        gpointer key, key_to_min, value;
70 71 72 73

        // find lowest timestamp in map
        g_hash_table_iter_init (&iter, result);

74
        gint min_timestamp = G_MAXINT;
75
        while (g_hash_table_iter_next (&iter, &key, &value))  {
76 77
            gint timestamp = atoi ( (gchar*) key);
            if (timestamp < min_timestamp) {
78 79 80 81 82
                min_timestamp = timestamp;
                key_to_min = key;
            }
        }

Tristan Matthews's avatar
Tristan Matthews committed
83 84 85 86 87 88 89 90 91
        if (g_hash_table_lookup_extended(result, key_to_min, &key, &value)) {
            GSList *llist = (GSList *)value;
            while (llist) {
                ordered_list = (void *) g_realloc(ordered_list, (size + 1) * sizeof (void *));
                *(ordered_list + size) = g_strdup((gchar *)llist->data);
                size++;
                llist = g_slist_next(llist);
            }
            g_hash_table_remove(result, key_to_min);
92 93 94
        }
    }

95 96
    ordered_list = (void *) g_realloc(ordered_list, (size + 1) * sizeof(void *));
    *(ordered_list + size) = NULL;
97

98
    return ordered_list;
99 100
}

101
void
102
sflphone_notify_voice_mail (const gchar* accountID , guint count)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
103
{
104
    gchar *id;
105
    gchar *current_id;
106
    account_t *current;
Emmanuel Milou's avatar
Emmanuel Milou committed
107

108 109 110 111
    // We want to notify only the current account; ie the first in the list
    id = g_strdup (accountID);
    current_id = account_list_get_current_id ();

Julien Bonjean's avatar
Julien Bonjean committed
112
    DEBUG ("sflphone_notify_voice_mail begin");
113

114
    if (g_strcasecmp (id, current_id) != 0 || account_list_get_size() == 0)
115 116
        return;

117 118 119
    // Set the number of voice messages for the current account
    current_account_set_message_number (count);
    current = account_list_get_current ();
120

121 122
    // Update the voicemail tool button
    update_voicemail_status ();
Emmanuel Milou's avatar
Emmanuel Milou committed
123

124 125
    if (current)
        notify_voice_mails (count, current);
Emmanuel Milou's avatar
Emmanuel Milou committed
126

Julien Bonjean's avatar
Julien Bonjean committed
127
    DEBUG ("sflphone_notify_voice_mail end");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
128 129
}

130 131 132 133 134 135 136
/*
 * Place a call with the current account.
 * If there is no default account selected, place a call with the first
 * registered account of the account list
 * Else, check if it an IP call. if not, popup an error message
 */

137 138 139 140 141 142 143
static gboolean _is_direct_call (callable_obj_t * c)
{

    if (g_strcasecmp (c->_accountID, EMPTY_ENTRY) == 0) {
        if (!g_str_has_prefix (c->_peer_number, "sip:")) {
            gchar * new_number = g_strconcat ("sip:", c->_peer_number, NULL);
            g_free (c->_peer_number);
144 145
            c->_peer_number = new_number;
        }
146

147 148 149
        return 1;
    }

150
    if (g_str_has_prefix (c->_peer_number, "sip:")) {
151 152 153
        return 1;
    }

154
    if (g_str_has_prefix (c->_peer_number, "sips:")) {
Alexandre Savard's avatar
Alexandre Savard committed
155 156 157
        return 1;
    }

158 159 160 161
    return 0;
}


162
void
163
status_bar_display_account ()
164
{
165
    gchar* msg;
166
    account_t* acc;
167

168
    statusbar_pop_message (__MSG_ACCOUNT_DEFAULT);
169

Julien Bonjean's avatar
Julien Bonjean committed
170
    DEBUG ("status_bar_display_account begin");
171

172
    acc = account_list_get_current ();
173 174 175 176 177 178 179 180 181 182

    if (acc) {
        status_tray_icon_online (TRUE);
        msg = g_markup_printf_escaped ("%s %s (%s)" ,
                                       _ ("Using account"),
                                       (gchar*) g_hash_table_lookup (acc->properties , ACCOUNT_ALIAS),
                                       (gchar*) g_hash_table_lookup (acc->properties , ACCOUNT_TYPE));
    } else {
        status_tray_icon_online (FALSE);
        msg = g_markup_printf_escaped (_ ("No registered accounts"));
183
    }
184

Julien Bonjean's avatar
Julien Bonjean committed
185
    statusbar_push_message (msg, NULL,  __MSG_ACCOUNT_DEFAULT);
186
    g_free (msg);
Julien Bonjean's avatar
Julien Bonjean committed
187 188

    DEBUG ("status_bar_display_account_end");
189 190
}

Emmanuel Milou's avatar
Emmanuel Milou committed
191

192
gboolean
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
193 194
sflphone_quit ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
195
    gboolean quit = FALSE;
196 197 198
    guint count = calllist_get_size (current_calls);

    if (count > 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
199
        quit = main_window_ask_quit();
200
    } else {
Emmanuel Milou's avatar
Emmanuel Milou committed
201 202 203
        quit = TRUE;
    }

204 205
    if (quit) {
        // Save the history
206 207
        sflphone_save_history ();

208
        dbus_unregister (getpid());
Emmanuel Milou's avatar
Emmanuel Milou committed
209 210 211 212 213
        dbus_clean ();
        //call_list_clean(); TODO
        //account_list_clean()
        gtk_main_quit ();
    }
214

Emmanuel Milou's avatar
Emmanuel Milou committed
215
    return quit;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
216 217
}

218 219
void
sflphone_hold (callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
220
{
221
    c->_state = CALL_STATE_HOLD;
222
    calltree_update_call (current_calls, c, NULL);
223
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
224 225
}

226 227
void
sflphone_ringing (callable_obj_t * c)
228
{
229
    c->_state = CALL_STATE_RINGING;
230
    calltree_update_call (current_calls, c, NULL);
231
    update_actions();
232
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
233

234 235
void
sflphone_hung_up (callable_obj_t * c)
Emmanuel Milou's avatar
Emmanuel Milou committed
236
{
Julien Bonjean's avatar
Julien Bonjean committed
237
    DEBUG ("SFLphone: Hung up");
238

239
    calllist_remove_call (current_calls, c->_callID);
240
    calltree_remove_call (current_calls, c, NULL);
241
    c->_state = CALL_STATE_DIALING;
242
    call_remove_all_errors (c);
243
    update_actions();
244

245 246 247 248 249
    if(c->_confID) {
	g_free(c->_confID);
	c->_confID = NULL;
    }

250 251 252 253 254
    // test wether the widget contain text, if not remove it
    if ( (im_window_get_nb_tabs() > 1) && c->_im_widget && ! (IM_WIDGET (c->_im_widget)->containText))
        im_window_remove_tab (c->_im_widget);
    else
        im_widget_update_state (IM_WIDGET (c->_im_widget), FALSE);
255

256
#if GTK_CHECK_VERSION(2,10,0)
257
    status_tray_icon_blink (FALSE);
258
#endif
259
    stop_call_clock(c);
260
    calltree_update_clock();
261 262
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
263
/** Internal to actions: Fill account list */
264 265
void sflphone_fill_account_list (void)
{
266 267 268 269

    gchar** array;
    gchar** accountID;
    unsigned int i;
270
    int count;
271

272
    DEBUG ("SFLphone: Fill account list");
273

274
    count = current_account_get_message_number ();
275

Emmanuel Milou's avatar
Emmanuel Milou committed
276
    account_list_clear ();
277

278 279 280
    array = (gchar **) dbus_account_list();

    if (array) {
Julien Bonjean's avatar
Julien Bonjean committed
281

282 283 284
        for (accountID = array; *accountID; accountID++) {
            account_t * a = g_new0 (account_t,1);
            a->accountID = g_strdup (*accountID);
285
            a->credential_information = NULL;
286
            account_list_add (a);
Emmanuel Milou's avatar
Emmanuel Milou committed
287
        }
288

Emmanuel Milou's avatar
Emmanuel Milou committed
289
        g_strfreev (array);
290
    }
291

292
    for (i = 0; i < account_list_get_size(); i++) {
Emmanuel Milou's avatar
Emmanuel Milou committed
293
        account_t  * a = account_list_get_nth (i);
294 295
        if(a == NULL) {
            ERROR("SFLphone: Error: Could not find account %d in list", i);
296
            break;
297
        }
298

299 300 301 302 303
        GHashTable * details = (GHashTable *) dbus_get_account_details (a->accountID);
        if (details == NULL) {
            ERROR("SFLphone: Error: Could not fetch detais for account %s", a->accountID);
	    break;
        }
304

305
        a->properties = details;
306 307

        /* Fill the actual array of credentials */
308
        dbus_get_credentials (a);
Emmanuel Milou's avatar
Emmanuel Milou committed
309

310 311 312
        gchar * status = g_hash_table_lookup (details, REGISTRATION_STATUS);

        if (strcmp (status, "REGISTERED") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
313
            a->state = ACCOUNT_STATE_REGISTERED;
314
        } else if (strcmp (status, "UNREGISTERED") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
315
            a->state = ACCOUNT_STATE_UNREGISTERED;
316
        } else if (strcmp (status, "TRYING") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
317
            a->state = ACCOUNT_STATE_TRYING;
318
        } else if (strcmp (status, "ERROR") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
319
            a->state = ACCOUNT_STATE_ERROR;
320
        } else if (strcmp (status , "ERROR_AUTH") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
321
            a->state = ACCOUNT_STATE_ERROR_AUTH;
322
        } else if (strcmp (status , "ERROR_NETWORK") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
323
            a->state = ACCOUNT_STATE_ERROR_NETWORK;
324
        } else if (strcmp (status , "ERROR_HOST") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
325
            a->state = ACCOUNT_STATE_ERROR_HOST;
326
        } else if (strcmp (status , "ERROR_CONF_STUN") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
327
            a->state = ACCOUNT_STATE_ERROR_CONF_STUN;
328
        } else if (strcmp (status , "ERROR_EXIST_STUN") == 0) {
Emmanuel Milou's avatar
Emmanuel Milou committed
329
            a->state = ACCOUNT_STATE_ERROR_EXIST_STUN;
330 331 332
        } else if (strcmp (status, "READY") == 0) {
            a->state = IP2IP_PROFILE_STATUS;
        } else {
Emmanuel Milou's avatar
Emmanuel Milou committed
333 334 335
            a->state = ACCOUNT_STATE_INVALID;
        }

336
        gchar * code = NULL;
337 338
        code = g_hash_table_lookup (details, REGISTRATION_STATE_CODE);

339
        if (code != NULL) {
340
            a->protocol_state_code = atoi (code);
341
        }
342 343 344

        g_free (a->protocol_state_description);
        a->protocol_state_description = g_hash_table_lookup (details, REGISTRATION_STATE_DESCRIPTION);
Emmanuel Milou's avatar
Emmanuel Milou committed
345 346
    }

347 348
    // Set the current account message number
    current_account_set_message_number (count);
349

350
    sflphone_fill_codec_list ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
351 352
}

353
gboolean sflphone_init (GError **error)
354
{
355
    if (!dbus_connect (error)) {
356
        return FALSE;
357
    }
Emmanuel Milou's avatar
Emmanuel Milou committed
358

359
    if (!dbus_register (getpid (), "Gtk+ Client", error)) {
Emmanuel Milou's avatar
Emmanuel Milou committed
360
        return FALSE;
361
    }
362 363

    abookfactory_init_factory();
364

365 366
    // Init icons factory
    init_icon_factory ();
367

368 369 370
    current_calls = calltab_init (FALSE, CURRENT_CALLS);
    contacts = calltab_init (TRUE, CONTACTS);
    history = calltab_init (TRUE, HISTORY);
371

372 373
    account_list_init ();
    codec_capabilities_load ();
374 375
    conferencelist_init (current_calls);
    conferencelist_init (history);
376

377 378
    // Fetch the configured accounts
    sflphone_fill_account_list ();
379

380 381
    // Fetch the ip2ip profile
    sflphone_fill_ip2ip_profile();
382

383 384
    // Fetch the conference list
    // sflphone_fill_conference_list();
385

386
    return TRUE;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
387 388
}

389
void sflphone_fill_ip2ip_profile (void)
390 391 392 393
{
    ip2ip_profile = (GHashTable *) dbus_get_ip2_ip_details();
}

Emmanuel Milou's avatar
Emmanuel Milou committed
394
void sflphone_get_ip2ip_properties (GHashTable **properties)
395
{
396
    *properties	= ip2ip_profile;
397 398
}

399
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
400
sflphone_hang_up()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
401
{
402 403
    callable_obj_t * selectedCall = calltab_get_selected_call (current_calls);
    conference_obj_t * selectedConf = calltab_get_selected_conf (active_calltree);
404

Julien Bonjean's avatar
Julien Bonjean committed
405
    DEBUG ("SFLphone: Hang up");
406

407 408
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
409 410 411 412 413
            case CALL_STATE_DIALING:
                dbus_hang_up (selectedCall);
                break;
            case CALL_STATE_RINGING:
                dbus_hang_up (selectedCall);
414
                call_remove_all_errors (selectedCall);
415 416
                selectedCall->_state = CALL_STATE_DIALING;
                //selectedCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
417 418 419 420
                break;
            case CALL_STATE_CURRENT:
            case CALL_STATE_HOLD:
            case CALL_STATE_BUSY:
421
            case CALL_STATE_RECORD:
Emmanuel Milou's avatar
Emmanuel Milou committed
422
                dbus_hang_up (selectedCall);
423
                call_remove_all_errors (selectedCall);
424
                selectedCall->_state = CALL_STATE_DIALING;
425
                set_timestamp (&selectedCall->_time_stop);
426 427 428 429 430

                //if ( (im_window_get_nb_tabs() > 1) && selectedCall->_im_widget &&
                //        ! (IM_WIDGET (selectedCall->_im_widget)->containText))
                //    im_window_remove_tab (selectedCall->_im_widget);
                //else
431
                im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), FALSE);
432

Emmanuel Milou's avatar
Emmanuel Milou committed
433 434 435
                break;
            case CALL_STATE_FAILURE:
                dbus_hang_up (selectedCall);
436
                call_remove_all_errors (selectedCall);
437
                selectedCall->_state = CALL_STATE_DIALING;
Emmanuel Milou's avatar
Emmanuel Milou committed
438 439 440
                break;
            case CALL_STATE_INCOMING:
                dbus_refuse (selectedCall);
441
                call_remove_all_errors (selectedCall);
442
                selectedCall->_state = CALL_STATE_DIALING;
443 444
                DEBUG ("from sflphone_hang_up : ");
                stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
445 446 447
                break;
            case CALL_STATE_TRANSFERT:
                dbus_hang_up (selectedCall);
448
                call_remove_all_errors (selectedCall);
449
                set_timestamp (&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
450 451
                break;
            default:
452
                WARN ("Should not happen in sflphone_hang_up()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
453 454
                break;
        }
455
    } else if (selectedConf) {
456
        im_widget_update_state (IM_WIDGET (selectedConf->_im_widget), FALSE);
457
        dbus_hang_up_conference (selectedConf);
458 459
    }

460
    calltree_update_call (history, selectedCall, NULL);
461

462 463
    stop_call_clock (selectedCall);

464
    calltree_update_clock();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
465 466 467
}


Alexandre Savard's avatar
Alexandre Savard committed
468 469 470
void
sflphone_conference_hang_up()
{
471
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls);
Alexandre Savard's avatar
Alexandre Savard committed
472

473
    if (selectedConf) {
474
        dbus_hang_up_conference (selectedConf);
475
    }
Alexandre Savard's avatar
Alexandre Savard committed
476 477 478
}


479
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
480 481
sflphone_pick_up()
{
482
    callable_obj_t * selectedCall = NULL;
483 484
    selectedCall = calltab_get_selected_call (active_calltree);

485 486
    DEBUG("SFLphone: Pick up");

487 488
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
489 490
            case CALL_STATE_DIALING:
                sflphone_place_call (selectedCall);
491 492 493 494 495

                // if instant messaging window is visible, create new tab (deleted automatically if not used)
                if (im_window_is_visible())
                    im_widget_display ( (IMWidget **) (&selectedCall->_im_widget), NULL, selectedCall->_callID, NULL);

Emmanuel Milou's avatar
Emmanuel Milou committed
496 497
                break;
            case CALL_STATE_INCOMING:
498
                selectedCall->_history_state = INCOMING;
499
                calltree_update_call (history, selectedCall, NULL);
500 501

                // if instant messaging window is visible, create new tab (deleted automatically if not used)
502
                if (selectedCall->_im_widget && im_window_is_visible()) {
503
                    im_widget_display ( (IMWidget **) (&selectedCall->_im_widget), NULL, selectedCall->_callID, NULL);
504
	        }
505

Emmanuel Milou's avatar
Emmanuel Milou committed
506
                dbus_accept (selectedCall);
507
                stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
508
                break;
509
            case CALL_STATE_HOLD:
Emmanuel Milou's avatar
Emmanuel Milou committed
510 511 512 513
                sflphone_new_call();
                break;
            case CALL_STATE_TRANSFERT:
                dbus_transfert (selectedCall);
514
                set_timestamp (&selectedCall->_time_stop);
515
                calltree_remove_call(current_calls, selectedCall, NULL);
516
                calllist_remove_call(current_calls, selectedCall->_callID);
517
		break;
Emmanuel Milou's avatar
Emmanuel Milou committed
518 519 520 521 522 523 524 525
            case CALL_STATE_CURRENT:
            case CALL_STATE_RECORD:
                sflphone_new_call();
                break;
            case CALL_STATE_RINGING:
                sflphone_new_call();
                break;
            default:
526
                WARN ("Should not happen in sflphone_pick_up()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
527 528
                break;
        }
529
    } else {
530 531
        sflphone_new_call();
    }
532

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
533 534
}

535
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
536 537
sflphone_on_hold ()
{
538 539
    callable_obj_t * selectedCall = calltab_get_selected_call (current_calls);
    conference_obj_t * selectedConf = calltab_get_selected_conf (active_calltree);
540

541 542 543 544
    DEBUG ("sflphone_on_hold");

    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
545 546 547 548 549 550 551
            case CALL_STATE_CURRENT:
                dbus_hold (selectedCall);
                break;
            case CALL_STATE_RECORD:
                dbus_hold (selectedCall);
                break;
            default:
552
                WARN ("Should not happen in sflphone_on_hold!");
Emmanuel Milou's avatar
Emmanuel Milou committed
553 554
                break;
        }
555 556
    } else if (selectedConf) {
        dbus_hold_conference (selectedConf);
557
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
558 559
}

560
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
561 562
sflphone_off_hold ()
{
563 564 565
    DEBUG ("sflphone_off_hold");
    callable_obj_t * selectedCall = calltab_get_selected_call (current_calls);
    conference_obj_t * selectedConf = calltab_get_selected_conf (active_calltree);
566

567 568
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
569 570 571 572
            case CALL_STATE_HOLD:
                dbus_unhold (selectedCall);
                break;
            default:
573
                WARN ("Should not happen in sflphone_off_hold ()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
574 575
                break;
        }
576 577
    } else if (selectedConf) {

Julien Bonjean's avatar
Julien Bonjean committed
578

579
        dbus_unhold_conference (selectedConf);
580
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
581 582 583
}


584 585
void
sflphone_fail (callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
586
{
587
    c->_state = CALL_STATE_FAILURE;
588
    calltree_update_call (current_calls, c, NULL);
589
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
590 591
}

592 593
void
sflphone_busy (callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
594
{
595
    c->_state = CALL_STATE_BUSY;
596
    calltree_update_call (current_calls, c, NULL);
597
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
598 599
}

600 601
void
sflphone_current (callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
602
{
603

604
    if (c->_state != CALL_STATE_HOLD)
605
        set_timestamp (&c->_time_start);
606

607
    c->_state = CALL_STATE_CURRENT;
608
    calltree_update_call (current_calls, c, NULL);
609
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
610 611
}

612 613
void
sflphone_record (callable_obj_t * c)
alexandresavard's avatar
alexandresavard committed
614
{
615
    if (c->_state != CALL_STATE_HOLD)
616
        set_timestamp (&c->_time_start);
617

618
    c->_state = CALL_STATE_RECORD;
619
    calltree_update_call (current_calls, c, NULL);
620
    update_actions();
alexandresavard's avatar
alexandresavard committed
621 622
}

623
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
624
sflphone_set_transfert()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
625
{
626 627 628
    callable_obj_t * c = calltab_get_selected_call (current_calls);

    if (c) {
629
        c->_state = CALL_STATE_TRANSFERT;
Tristan Matthews's avatar
Tristan Matthews committed
630
        g_free(c->_trsft_to);
631 632
        c->_trsft_to = g_strdup ("");
        calltree_update_call (current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
633
    }
634

635
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
636 637
}

638
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
639 640
sflphone_unset_transfert()
{
641 642 643
    callable_obj_t * c = calltab_get_selected_call (current_calls);

    if (c) {
644
        c->_state = CALL_STATE_CURRENT;
Tristan Matthews's avatar
Tristan Matthews committed
645
        g_free(c->_trsft_to);
646 647
        c->_trsft_to = g_strdup ("");
        calltree_update_call (current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
648
    }
649

650
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
651
}
Emmanuel Milou's avatar
Emmanuel Milou committed
652

653 654
void
sflphone_display_transfer_status (const gchar* message)
655
{
Julien Bonjean's avatar
Julien Bonjean committed
656
    statusbar_push_message (message , NULL, __MSG_ACCOUNT_DEFAULT);
657 658
}

659
void
660
sflphone_incoming_call (callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
661
{
662
    gchar *msg = "";
663

664
    c->_history_state = MISSED;
665 666
    calllist_add_call (current_calls, c);
    calllist_add_call (history, c);
667
    calltree_add_call (current_calls, c, NULL);
668
    calltree_add_call (history, c, NULL);
669
    update_actions();
Julien Bonjean's avatar
Julien Bonjean committed
670
    calltree_display (current_calls);
671 672 673 674 675

    // Change the status bar if we are dealing with a direct SIP call
    if (_is_direct_call (c)) {
        msg = g_markup_printf_escaped (_ ("Direct SIP call"));
        statusbar_pop_message (__MSG_ACCOUNT_DEFAULT);
Julien Bonjean's avatar
Julien Bonjean committed
676
        statusbar_push_message (msg , NULL, __MSG_ACCOUNT_DEFAULT);
677 678
        g_free (msg);
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
679
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
680

681
void
682
process_dialing (callable_obj_t *c, guint keyval, gchar *key)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
683
{
Emmanuel Milou's avatar
Emmanuel Milou committed
684
    // We stop the tone
685 686
    if (strlen (c->_peer_number) == 0 && c->_state != CALL_STATE_TRANSFERT) {
        dbus_start_tone (FALSE , 0);
Emmanuel Milou's avatar
Emmanuel Milou committed
687 688
        //dbus_play_dtmf( key );
    }
689

690
    switch (keyval) {
Emmanuel Milou's avatar
Emmanuel Milou committed
691 692
        case 65293: /* ENTER */
        case 65421: /* ENTER numpad */
693
            sflphone_place_call (c);
Emmanuel Milou's avatar
Emmanuel Milou committed
694 695
            break;
        case 65307: /* ESCAPE */
Rafaël Carré's avatar
Rafaël Carré committed
696
            sflphone_hang_up ();
Emmanuel Milou's avatar
Emmanuel Milou committed
697
            break;
Alexandre Savard's avatar
Alexandre Savard committed
698 699
        case 65288: { /* BACKSPACE */
            /* Brackets mandatory because of local vars */
700 701 702 703 704 705 706 707 708 709 710
            gchar * before = c->_peer_number;

            if (strlen (c->_peer_number) >= 1) {

                if (c->_state == CALL_STATE_TRANSFERT) {
                    // Process backspace if and only if string not NULL
                    if (strlen (c->_trsft_to) > 0)
                        c->_trsft_to = g_strndup (c->_trsft_to, strlen (c->_trsft_to) - 1);
                } else {
                    c->_peer_number = g_strndup (c->_peer_number, strlen (c->_peer_number) -1);
                    g_free (before);
711
                    DEBUG ("SFLphone: TO: backspace %s", c->_peer_number);
Emmanuel Milou's avatar
Emmanuel Milou committed
712
                }
713 714 715 716 717

                calltree_update_call (current_calls, c, NULL);
            } else if (strlen (c->_peer_number) == 0) {
                if (c->_state != CALL_STATE_TRANSFERT)
                    dbus_hang_up (c);
Emmanuel Milou's avatar
Emmanuel Milou committed
718
            }
719 720
        }
        break;
Emmanuel Milou's avatar
Emmanuel Milou committed
721 722 723 724 725 726 727
        case 65289: /* TAB */
        case 65513: /* ALT */
        case 65507: /* CTRL */
        case 65515: /* SUPER */
        case 65509: /* CAPS */
            break;
        default:
728

Emmanuel Milou's avatar
Emmanuel Milou committed
729
            // if (keyval < 255 || (keyval >65453 && keyval < 65466))
730
            if (keyval < 127 || (keyval > 65400 && keyval < 65466)) {
Emmanuel Milou's avatar
Emmanuel Milou committed
731

732
                if (c->_state == CALL_STATE_TRANSFERT) {
Tristan Matthews's avatar
Tristan Matthews committed
733 734 735
                    gchar *new_trsft = g_strconcat (c->_trsft_to, key, NULL);
                    g_free (c->_trsft_to);
                    c->_trsft_to = new_trsft;