actions.c 32.6 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
#include <glib/gi18n.h>
33
#include <gtk/gtk.h>
34 35 36 37
/* Backward compatibility for gtk < 2.22.0 */
#if GTK_CHECK_VERSION(2,22,0)
#include <gdk/gdkkeysyms-compat.h>
#else
38
#include <gdk/gdkkeysyms.h>
39
#endif
40 41

#include "str_utils.h"
42
#include <glib.h>
43
#include <stdlib.h>
44
#include <string.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
45 46 47
#include <sys/types.h>
#include <unistd.h>

48
#include <arpa/nameser.h>
49
#include <netinet/in.h>
50 51
#include <resolv.h>

52
#include <linux/if.h>
53 54 55 56
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

57 58
#include "actions.h"
#include "dbus/dbus.h"
59
#include "logger.h"
60
#include "config/accountlistconfigdialog.h"
61
#include "contacts/calltab.h"
62 63 64 65 66
#include "contacts/searchbar.h"
#include "contacts/addrbookfactory.h"
#include "icons/icon_factory.h"
#include "imwindow.h"
#include "statusicon.h"
67
#include "unused.h"
68
#include "widget/imwidget.h"
69
#include "sliders.h"
70

71
static GHashTable * ip2ip_profile;
72

73
void
74
sflphone_notify_voice_mail(const gchar* accountID , guint count)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
75
{
76
    // We want to notify only the current account; ie the first in the list
77 78
    gchar *id = g_strdup(accountID);
    const gchar * const current_id = account_list_get_current_id();
79

80
    DEBUG("sflphone_notify_voice_mail begin");
81

82
    if (g_ascii_strcasecmp(id, current_id) != 0 || account_list_get_size() == 0)
83 84
        return;

85
    // Set the number of voice messages for the current account
86 87
    current_account_set_message_number(count);
    account_t *current = account_list_get_current();
88

89
    // Update the voicemail tool button
90
    update_voicemail_status();
Emmanuel Milou's avatar
Emmanuel Milou committed
91

92
    if (current)
93
        notify_voice_mails(count, current);
Emmanuel Milou's avatar
Emmanuel Milou committed
94

95
    DEBUG("sflphone_notify_voice_mail end");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
96 97
}

98 99 100 101 102 103 104
/*
 * 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
 */

105
static gboolean is_direct_call(callable_obj_t * c)
106
{
107
    if (utf8_case_equal(c->_accountID, "empty")) {
108 109 110
        if (!g_str_has_prefix(c->_peer_number, "sip:")) {
            gchar * new_number = g_strconcat("sip:", c->_peer_number, NULL);
            g_free(c->_peer_number);
111 112
            c->_peer_number = new_number;
        }
113

114
        return TRUE;
Alexandre Savard's avatar
Alexandre Savard committed
115 116
    }

117 118
    return g_str_has_prefix(c->_peer_number, "sip:") ||
           g_str_has_prefix(c->_peer_number, "sips:");
119 120 121
}


122
void
123
status_bar_display_account()
124
{
125
    gchar* msg;
126

127
    statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
128

129 130
    account_t *acc = account_list_get_current();
    status_tray_icon_online(acc != NULL);
131 132

    if (acc) {
133 134
        msg = g_markup_printf_escaped("%s %s (%s)" ,
                                      _("Using account"),
135 136
                                      (gchar*) account_lookup(acc, ACCOUNT_ALIAS),
                                      (gchar*) account_lookup(acc, ACCOUNT_TYPE));
137
    } else {
138
        msg = g_markup_printf_escaped(_("No registered accounts"));
139
    }
140

141 142
    statusbar_push_message(msg, NULL,  __MSG_ACCOUNT_DEFAULT);
    g_free(msg);
143 144
}

Emmanuel Milou's avatar
Emmanuel Milou committed
145

146
void
147
sflphone_quit()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
148
{
Tristan Matthews's avatar
Tristan Matthews committed
149
    if (calllist_get_size(current_calls_tab) == 0 || main_window_ask_quit()) {
150 151
        dbus_unregister(getpid());
        dbus_clean();
Rafaël Carré's avatar
Cleanup  
Rafaël Carré committed
152
        account_list_free();
Tristan Matthews's avatar
Tristan Matthews committed
153 154 155 156 157 158
        calllist_clean(current_calls_tab);
        calllist_clean(contacts_tab);
        calllist_clean(history_tab);
        gtk_tree_store_clear(history_tab->store);
        gtk_tree_store_clear(current_calls_tab->store);
        gtk_tree_store_clear(contacts_tab->store);
159
        gtk_main_quit();
Emmanuel Milou's avatar
Emmanuel Milou committed
160
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
161 162
}

163
void
164
sflphone_hold(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
165
{
166
    c->_state = CALL_STATE_HOLD;
Tristan Matthews's avatar
Tristan Matthews committed
167
    calltree_update_call(current_calls_tab, c);
168
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
169 170
}

171
void
172
sflphone_ringing(callable_obj_t * c)
173
{
174
    c->_state = CALL_STATE_RINGING;
Tristan Matthews's avatar
Tristan Matthews committed
175
    calltree_update_call(current_calls_tab, c);
176
    update_actions();
177
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
178

179
void
180
sflphone_hung_up(callable_obj_t * c)
Emmanuel Milou's avatar
Emmanuel Milou committed
181
{
182
    DEBUG("SFLphone: Hung up");
183

Tristan Matthews's avatar
Tristan Matthews committed
184 185
    calllist_remove_call(current_calls_tab, c->_callID);
    calltree_remove_call(current_calls_tab, c);
186
    c->_state = CALL_STATE_DIALING;
187
    call_remove_all_errors(c);
188
    update_actions();
189

190 191 192
    if (c->_confID) {
        g_free(c->_confID);
        c->_confID = NULL;
193 194
    }

195
    // test whether the widget contains text, if not remove it
196 197
    if ((im_window_get_nb_tabs() > 1) && c->_im_widget && !(IM_WIDGET(c->_im_widget)->containText))
        im_window_remove_tab(c->_im_widget);
198
    else
199
        im_widget_update_state(IM_WIDGET(c->_im_widget), FALSE);
200

201
    status_tray_icon_blink(FALSE);
202

203
    statusbar_update_clock("");
204 205
}

206
void sflphone_fill_account_list(void)
207
{
Rafaël Carré's avatar
Cleanup  
Rafaël Carré committed
208
    account_list_init();
209
    gchar **array = dbus_account_list();
210

211 212 213 214 215
    for (gchar **accountID = array; accountID && *accountID; ++accountID) {
        account_t *acc = create_account_with_ID(*accountID);
        if (acc->properties == NULL) {
            ERROR("SFLphone: Error: Could not fetch details for account %s",
                  accountID);
216
            break;
217
        }
218
        account_list_add(acc);
219
        /* Fill the actual array of credentials */
220 221
        dbus_get_credentials(acc);
        gchar * status = account_lookup(acc, REGISTRATION_STATUS);
222

223
        if (g_strcmp0(status, "REGISTERED") == 0)
224
            acc->state = ACCOUNT_STATE_REGISTERED;
225
        else if (g_strcmp0(status, "UNREGISTERED") == 0)
226
            acc->state = ACCOUNT_STATE_UNREGISTERED;
227
        else if (g_strcmp0(status, "TRYING") == 0)
228
            acc->state = ACCOUNT_STATE_TRYING;
229
        else if (g_strcmp0(status, "ERROR") == 0)
230
            acc->state = ACCOUNT_STATE_ERROR;
231
        else if (g_strcmp0(status , "ERROR_AUTH") == 0)
232
            acc->state = ACCOUNT_STATE_ERROR_AUTH;
233
        else if (g_strcmp0(status , "ERROR_NETWORK") == 0)
234
            acc->state = ACCOUNT_STATE_ERROR_NETWORK;
235
        else if (g_strcmp0(status , "ERROR_HOST") == 0)
236
            acc->state = ACCOUNT_STATE_ERROR_HOST;
237
        else if (g_strcmp0(status , "ERROR_CONF_STUN") == 0)
238
            acc->state = ACCOUNT_STATE_ERROR_CONF_STUN;
239
        else if (g_strcmp0(status , "ERROR_EXIST_STUN") == 0)
240
            acc->state = ACCOUNT_STATE_ERROR_EXIST_STUN;
241
        else if (g_strcmp0(status, "READY") == 0)
242
            acc->state = IP2IP_PROFILE_STATUS;
243
        else
244
            acc->state = ACCOUNT_STATE_INVALID;
245

246
        gchar * code = account_lookup(acc, REGISTRATION_STATE_CODE);
247
        if (code != NULL)
248 249
            acc->protocol_state_code = atoi(code);
        acc->protocol_state_description = account_lookup(acc, REGISTRATION_STATE_DESCRIPTION);
Emmanuel Milou's avatar
Emmanuel Milou committed
250 251
    }

252 253
    g_strfreev(array);

254
    // Set the current account message number
255 256
    current_account_set_message_number(current_account_get_message_number());
    account_store_fill();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
257 258
}

259
gboolean sflphone_init(GError **error)
260
{
261
    if (!dbus_connect(error) || !dbus_register(getpid(), "Gtk+ Client", error))
262
        return FALSE;
263

Rafaël Carré's avatar
Rafaël Carré committed
264
    abook_init();
265

266
    // Init icons factory
267
    init_icon_factory();
268

Tristan Matthews's avatar
Tristan Matthews committed
269 270 271
    current_calls_tab = calltab_init(FALSE, CURRENT_CALLS);
    contacts_tab = calltab_init(TRUE, CONTACTS);
    history_tab = calltab_init(TRUE, HISTORY);
272

273
    codec_capabilities_load();
Tristan Matthews's avatar
Tristan Matthews committed
274
    conferencelist_init(current_calls_tab);
275

276
    // Fetch the configured accounts
277
    sflphone_fill_account_list();
278

279 280
    // Fetch the ip2ip profile
    sflphone_fill_ip2ip_profile();
281

282
    // Fetch the conference list
283
    sflphone_fill_conference_list();
284

285
    return TRUE;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
286 287
}

288
void sflphone_fill_ip2ip_profile(void)
289 290 291 292
{
    ip2ip_profile = (GHashTable *) dbus_get_ip2_ip_details();
}

293
GHashTable *sflphone_get_ip2ip_properties(void)
294
{
295
    return ip2ip_profile;
296 297
}

298
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
299
sflphone_hang_up()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
300
{
Tristan Matthews's avatar
Tristan Matthews committed
301 302
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
303

304
    DEBUG("SFLphone: Hang up");
305

306
    if (selectedConf) {
307 308 309
        im_widget_update_state(IM_WIDGET(selectedConf->_im_widget), FALSE);
        dbus_hang_up_conference(selectedConf);
    } else if (selectedCall) {
310
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
311
            case CALL_STATE_DIALING:
312
                dbus_hang_up(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
313 314
                break;
            case CALL_STATE_RINGING:
315 316
                dbus_hang_up(selectedCall);
                call_remove_all_errors(selectedCall);
317 318
                selectedCall->_state = CALL_STATE_DIALING;
                //selectedCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
319 320 321 322
                break;
            case CALL_STATE_CURRENT:
            case CALL_STATE_HOLD:
            case CALL_STATE_BUSY:
323
            case CALL_STATE_RECORD:
324 325
                dbus_hang_up(selectedCall);
                call_remove_all_errors(selectedCall);
326
                selectedCall->_state = CALL_STATE_DIALING;
327
                time(&selectedCall->_time_stop);
328

329
                im_widget_update_state(IM_WIDGET(selectedCall->_im_widget), FALSE);
330

Emmanuel Milou's avatar
Emmanuel Milou committed
331 332
                break;
            case CALL_STATE_FAILURE:
333 334
                dbus_hang_up(selectedCall);
                call_remove_all_errors(selectedCall);
335
                selectedCall->_state = CALL_STATE_DIALING;
Emmanuel Milou's avatar
Emmanuel Milou committed
336 337
                break;
            case CALL_STATE_INCOMING:
338 339
                dbus_refuse(selectedCall);
                call_remove_all_errors(selectedCall);
340
                selectedCall->_state = CALL_STATE_DIALING;
341
                DEBUG("from sflphone_hang_up : ");
Emmanuel Milou's avatar
Emmanuel Milou committed
342
                break;
343
            case CALL_STATE_TRANSFER:
344 345 346
                dbus_hang_up(selectedCall);
                call_remove_all_errors(selectedCall);
                time(&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
347 348
                break;
            default:
349
                WARN("Should not happen in sflphone_hang_up()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
350 351
                break;
        }
352 353
    }

Tristan Matthews's avatar
Tristan Matthews committed
354
    calltree_update_call(history_tab, selectedCall);
355

356
    statusbar_update_clock("");
357 358 359 360 361

    // Allow screen saver to start
    guint nbcall = calllist_get_size(current_calls_tab);
    if(nbcall == 1)
        dbus_screensaver_uninhibit();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
362 363
}

364
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
365 366
sflphone_pick_up()
{
Tristan Matthews's avatar
Tristan Matthews committed
367
    callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab);
368

369 370 371 372 373
    // Disable screensaver if the list is empty call
    guint nbcall = calllist_get_size(current_calls_tab);
    if(nbcall == 0)
        dbus_screensaver_inhibit();

374 375 376 377
    if (!selectedCall) {
        sflphone_new_call();
        return;
    }
378

379 380
    switch (selectedCall->_state) {
        case CALL_STATE_DIALING:
381
            sflphone_place_call(selectedCall);
382

383 384
            // if instant messaging window is visible, create new tab (deleted automatically if not used)
            if (im_window_is_visible())
385 386
                if (!selectedCall->_im_widget)
                    selectedCall->_im_widget = im_widget_display(selectedCall->_callID);
387

388 389
            break;
        case CALL_STATE_INCOMING:
390
            selectedCall->_history_state = g_strdup(INCOMING_STRING);
Tristan Matthews's avatar
Tristan Matthews committed
391
            calltree_update_call(history_tab, selectedCall);
392

393
            // if instant messaging window is visible, create new tab (deleted automatically if not used)
394 395 396
            if (im_window_is_visible())
                if (!selectedCall->_im_widget)
                    selectedCall->_im_widget = im_widget_display(selectedCall->_callID);
397

398
            dbus_accept(selectedCall);
399
            break;
400
        case CALL_STATE_TRANSFER:
401 402
            dbus_transfer(selectedCall);
            time(&selectedCall->_time_stop);
Tristan Matthews's avatar
Tristan Matthews committed
403 404
            calltree_remove_call(current_calls_tab, selectedCall);
            calllist_remove_call(current_calls_tab, selectedCall->_callID);
405 406 407 408 409 410 411 412
            break;
        case CALL_STATE_CURRENT:
        case CALL_STATE_HOLD:
        case CALL_STATE_RECORD:
        case CALL_STATE_RINGING:
            sflphone_new_call();
            break;
        default:
413
            WARN("Should not happen in sflphone_pick_up()!");
414
            break;
415
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
416 417
}

418
void
419
sflphone_on_hold()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
420
{
Tristan Matthews's avatar
Tristan Matthews committed
421 422
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
423

424 425
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
426 427
            case CALL_STATE_CURRENT:
            case CALL_STATE_RECORD:
428
                dbus_hold(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
429 430
                break;
            default:
431
                WARN("Should not happen in sflphone_on_hold!");
Emmanuel Milou's avatar
Emmanuel Milou committed
432 433
                break;
        }
434
    } else if (selectedConf)
435
        dbus_hold_conference(selectedConf);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
436 437
}

438
void
439
sflphone_off_hold()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
440
{
441
    DEBUG("sflphone_off_hold");
Tristan Matthews's avatar
Tristan Matthews committed
442 443
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
444

445 446
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
447
            case CALL_STATE_HOLD:
448
                dbus_unhold(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
449 450
                break;
            default:
451
                WARN("Should not happen in sflphone_off_hold ()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
452 453
                break;
        }
454
    } else if (selectedConf)
455
        dbus_unhold_conference(selectedConf);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
456 457 458
}


459
void
460
sflphone_fail(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
461
{
462
    c->_state = CALL_STATE_FAILURE;
Tristan Matthews's avatar
Tristan Matthews committed
463
    calltree_update_call(current_calls_tab, c);
464
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
465 466
}

467
void
468
sflphone_busy(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
469
{
470
    c->_state = CALL_STATE_BUSY;
Tristan Matthews's avatar
Tristan Matthews committed
471
    calltree_update_call(current_calls_tab, c);
472
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
473 474
}

475
void
476
sflphone_current(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
477
{
478
    if (c->_state != CALL_STATE_HOLD)
479
        time(&c->_time_start);
480

481
    c->_state = CALL_STATE_CURRENT;
Tristan Matthews's avatar
Tristan Matthews committed
482
    calltree_update_call(current_calls_tab, c);
483
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
484 485
}

486
void
487
sflphone_record(callable_obj_t * c)
alexandresavard's avatar
alexandresavard committed
488
{
489
    if (c->_state != CALL_STATE_HOLD)
490
        time(&c->_time_start);
491

492
    c->_state = CALL_STATE_RECORD;
Tristan Matthews's avatar
Tristan Matthews committed
493
    calltree_update_call(current_calls_tab, c);
494
    update_actions();
alexandresavard's avatar
alexandresavard committed
495 496
}

497
void
498
sflphone_set_transfer()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
499
{
Tristan Matthews's avatar
Tristan Matthews committed
500
    callable_obj_t * c = calltab_get_selected_call(current_calls_tab);
501 502

    if (c) {
503
        c->_state = CALL_STATE_TRANSFER;
Tristan Matthews's avatar
Tristan Matthews committed
504
        g_free(c->_trsft_to);
505
        c->_trsft_to = g_strdup("");
Tristan Matthews's avatar
Tristan Matthews committed
506
        calltree_update_call(current_calls_tab, c);
Emmanuel Milou's avatar
Emmanuel Milou committed
507
    }
508

509
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
510 511
}

512
void
513
sflphone_unset_transfer()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
514
{
Tristan Matthews's avatar
Tristan Matthews committed
515
    callable_obj_t * c = calltab_get_selected_call(current_calls_tab);
516 517

    if (c) {
518
        c->_state = CALL_STATE_CURRENT;
Tristan Matthews's avatar
Tristan Matthews committed
519
        g_free(c->_trsft_to);
520
        c->_trsft_to = g_strdup("");
Tristan Matthews's avatar
Tristan Matthews committed
521
        calltree_update_call(current_calls_tab, c);
Emmanuel Milou's avatar
Emmanuel Milou committed
522
    }
523

524
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
525
}
Emmanuel Milou's avatar
Emmanuel Milou committed
526

527
void
528
sflphone_display_transfer_status(const gchar* message)
529
{
530
    statusbar_push_message(message , NULL, __MSG_ACCOUNT_DEFAULT);
531 532
}

533
void
534
sflphone_incoming_call(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
535
{
536
    c->_history_state = g_strdup(MISSED_STRING);
Tristan Matthews's avatar
Tristan Matthews committed
537 538
    calllist_add_call(current_calls_tab, c);
    calltree_add_call(current_calls_tab, c, NULL);
539

540
    update_actions();
Tristan Matthews's avatar
Tristan Matthews committed
541
    calltree_display(current_calls_tab);
542 543

    // Change the status bar if we are dealing with a direct SIP call
544
    if (is_direct_call(c)) {
545 546 547 548
        gchar *msg = g_markup_printf_escaped(_("Direct SIP call"));
        statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
        statusbar_push_message(msg , NULL, __MSG_ACCOUNT_DEFAULT);
        g_free(msg);
549
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
550
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
551

552
static void
553
process_dialing(callable_obj_t *c, guint keyval, gchar *key)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
554
{
Emmanuel Milou's avatar
Emmanuel Milou committed
555
    // We stop the tone
556
    if (!*c->_peer_number && c->_state != CALL_STATE_TRANSFER)
557
        dbus_start_tone(FALSE, 0);
558

559
    switch (keyval) {
560 561
        case GDK_Return:
        case GDK_KP_Enter:
562
            sflphone_place_call(c);
Emmanuel Milou's avatar
Emmanuel Milou committed
563
            break;
564
        case GDK_Escape:
565
            sflphone_hang_up();
Emmanuel Milou's avatar
Emmanuel Milou committed
566
            break;
567
        case GDK_BackSpace: {
568 569
            gchar *num = (c->_state == CALL_STATE_TRANSFER) ? c->_trsft_to : c->_peer_number;
            size_t len = strlen(num);
570

571 572 573
            if (len) {
                len--; // delete one character
                num[len] = '\0';
Tristan Matthews's avatar
Tristan Matthews committed
574
                calltree_update_call(current_calls_tab, c);
575

576
                /* If number is now empty, hang up immediately */
577
                if (c->_state != CALL_STATE_TRANSFER && len == 0)
578
                    dbus_hang_up(c);
Emmanuel Milou's avatar
Emmanuel Milou committed
579
            }
580

581
            break;
582
        }
583 584 585 586 587
        case GDK_Tab:
        case GDK_Alt_L:
        case GDK_Control_L:
        case GDK_Super_L:
        case GDK_Caps_Lock:
Emmanuel Milou's avatar
Emmanuel Milou committed
588 589
            break;
        default:
590

591
            if (keyval < 127 /* ascii */ ||
592
                    (keyval >= GDK_Mode_switch && keyval <= GDK_KP_9) /* num keypad */) {
Emmanuel Milou's avatar
Emmanuel Milou committed
593

594
                if (c->_state == CALL_STATE_TRANSFER) {
595 596
                    gchar *new_trsft = g_strconcat(c->_trsft_to, key, NULL);
                    g_free(c->_trsft_to);
Tristan Matthews's avatar
Tristan Matthews committed
597
                    c->_trsft_to = new_trsft;
598
                } else {
599 600 601
                    dbus_play_dtmf(key);
                    gchar *new_peer_number = g_strconcat(c->_peer_number, key, NULL);
                    g_free(c->_peer_number);
Tristan Matthews's avatar
Tristan Matthews committed
602
                    c->_peer_number = new_peer_number;
Emmanuel Milou's avatar
Emmanuel Milou committed
603
                }
604

Tristan Matthews's avatar
Tristan Matthews committed
605
                calltree_update_call(current_calls_tab, c);
Emmanuel Milou's avatar
Emmanuel Milou committed
606
            }
607

Emmanuel Milou's avatar
Emmanuel Milou committed
608 609
            break;
    }
610 611
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
612

613
callable_obj_t *
areversat's avatar
areversat committed
614
sflphone_new_call()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
615
{
616 617 618 619 620
    // Disable screensaver if the list is empty call
    guint nbcall = calllist_get_size(current_calls_tab);
    if(nbcall == 0)
        dbus_screensaver_inhibit();

Tristan Matthews's avatar
Tristan Matthews committed
621
    callable_obj_t *current_selected_call = calltab_get_selected_call(current_calls_tab);
622

623
    if ((current_selected_call != NULL) && (current_selected_call->_confID == NULL))
624
        sflphone_on_hold();
625

Emmanuel Milou's avatar
Emmanuel Milou committed
626
    // Play a tone when creating a new call
Tristan Matthews's avatar
Tristan Matthews committed
627
    if (calllist_get_size(current_calls_tab) == 0)
628
        dbus_start_tone(TRUE , (current_account_has_new_message()  > 0) ? TONE_WITH_MESSAGE : TONE_WITHOUT_MESSAGE) ;
Emmanuel Milou's avatar
Emmanuel Milou committed
629

630
    callable_obj_t *c = create_new_call(CALL, CALL_STATE_DIALING, "", "", "", "");
Emmanuel Milou's avatar
Emmanuel Milou committed
631

632
    c->_history_state = g_strdup(OUTGOING_STRING);
633

Tristan Matthews's avatar
Tristan Matthews committed
634 635
    calllist_add_call(current_calls_tab, c);
    calltree_add_call(current_calls_tab, c, NULL);
636
    update_actions();
637

Emmanuel Milou's avatar
Emmanuel Milou committed
638
    return c;
639 640
}

areversat's avatar
areversat committed
641

642
void
643
sflphone_keypad(guint keyval, gchar * key)
areversat's avatar
areversat committed
644
{