actions.c 33.5 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
#include <glib.h>
41
#include <stdlib.h>
42
#include <string.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
43 44 45
#include <sys/types.h>
#include <unistd.h>

46
#include <arpa/nameser.h>
47
#include <netinet/in.h>
48 49
#include <resolv.h>

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

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

68
static GHashTable * ip2ip_profile;
69

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

77
    DEBUG("sflphone_notify_voice_mail begin");
78

79
    if (g_ascii_strcasecmp(id, current_id) != 0 || account_list_get_size() == 0)
80 81
        return;

82
    // Set the number of voice messages for the current account
83 84
    current_account_set_message_number(count);
    account_t *current = account_list_get_current();
85

86
    // Update the voicemail tool button
87
    update_voicemail_status();
Emmanuel Milou's avatar
Emmanuel Milou committed
88

89
    if (current)
90
        notify_voice_mails(count, current);
Emmanuel Milou's avatar
Emmanuel Milou committed
91

92
    DEBUG("sflphone_notify_voice_mail end");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
93 94
}

95 96 97 98 99 100 101
/*
 * 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
 */

102
static gboolean is_direct_call(callable_obj_t * c)
103
{
104 105 106 107
    if (g_strcasecmp(c->_accountID, "empty") == 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);
108 109
            c->_peer_number = new_number;
        }
110

111
        return TRUE;
Alexandre Savard's avatar
Alexandre Savard committed
112 113
    }

114 115
    return g_str_has_prefix(c->_peer_number, "sip:") ||
           g_str_has_prefix(c->_peer_number, "sips:");
116 117 118
}


119
void
120
status_bar_display_account()
121
{
122
    gchar* msg;
123

124
    statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
125

126 127
    account_t *acc = account_list_get_current();
    status_tray_icon_online(acc != NULL);
128 129

    if (acc) {
130 131
        msg = g_markup_printf_escaped("%s %s (%s)" ,
                                      _("Using account"),
132 133
                                      (gchar*) g_hash_table_lookup(acc->properties, ACCOUNT_ALIAS),
                                      (gchar*) g_hash_table_lookup(acc->properties, ACCOUNT_TYPE));
134
    } else {
135
        msg = g_markup_printf_escaped(_("No registered accounts"));
136
    }
137

138 139
    statusbar_push_message(msg, NULL,  __MSG_ACCOUNT_DEFAULT);
    g_free(msg);
140 141
}

Emmanuel Milou's avatar
Emmanuel Milou committed
142

143
void
144
sflphone_quit()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
145
{
Tristan Matthews's avatar
Tristan Matthews committed
146
    if (calllist_get_size(current_calls_tab) == 0 || main_window_ask_quit()) {
147 148
        dbus_unregister(getpid());
        dbus_clean();
Rafaël Carré's avatar
Cleanup  
Rafaël Carré committed
149
        account_list_free();
Tristan Matthews's avatar
Tristan Matthews committed
150 151 152 153 154 155
        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);
156
        gtk_main_quit();
Emmanuel Milou's avatar
Emmanuel Milou committed
157
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
158 159
}

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

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

176
void
177
sflphone_hung_up(callable_obj_t * c)
Emmanuel Milou's avatar
Emmanuel Milou committed
178
{
179
    DEBUG("SFLphone: Hung up");
180

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

187 188 189
    if (c->_confID) {
        g_free(c->_confID);
        c->_confID = NULL;
190 191
    }

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

198
    status_tray_icon_blink(FALSE);
199

200
    statusbar_update_clock("");
201 202
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
203
/** Internal to actions: Fill account list */
204
void sflphone_fill_account_list(void)
205
{
206
    int count = current_account_get_message_number();
207

Rafaël Carré's avatar
Cleanup  
Rafaël Carré committed
208 209
    account_list_free();
    account_list_init();
210

211
    gchar **array = dbus_account_list();
212

213
    if (array) {
214
        for (gchar **accountID = array; accountID && *accountID; accountID++) {
215
            account_t * a = g_new0(account_t, 1);
216
            a->accountID = g_strdup(*accountID);
217
            a->credential_information = NULL;
218
            account_list_add(a);
Emmanuel Milou's avatar
Emmanuel Milou committed
219
        }
220

221
        g_strfreev(array);
222
    }
223

224
    for (unsigned i = 0; i < account_list_get_size(); i++) {
225 226 227
        account_t  * a = account_list_get_nth(i);

        if (a == NULL) {
228
            ERROR("SFLphone: Error: Could not find account %d in list", i);
229
            break;
230
        }
231

232 233
        GHashTable * details = (GHashTable *) dbus_get_account_details(a->accountID);

234 235
        if (details == NULL) {
            ERROR("SFLphone: Error: Could not fetch detais for account %s", a->accountID);
236
            break;
237
        }
238

239
        a->properties = details;
240 241

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

244
        gchar * status = g_hash_table_lookup(details, REGISTRATION_STATUS);
245

246
        if (g_strcmp0(status, "REGISTERED") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
247
            a->state = ACCOUNT_STATE_REGISTERED;
248
        else if (g_strcmp0(status, "UNREGISTERED") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
249
            a->state = ACCOUNT_STATE_UNREGISTERED;
250
        else if (g_strcmp0(status, "TRYING") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
251
            a->state = ACCOUNT_STATE_TRYING;
252
        else if (g_strcmp0(status, "ERROR") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
253
            a->state = ACCOUNT_STATE_ERROR;
254
        else if (g_strcmp0(status , "ERROR_AUTH") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
255
            a->state = ACCOUNT_STATE_ERROR_AUTH;
256
        else if (g_strcmp0(status , "ERROR_NETWORK") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
257
            a->state = ACCOUNT_STATE_ERROR_NETWORK;
258
        else if (g_strcmp0(status , "ERROR_HOST") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
259
            a->state = ACCOUNT_STATE_ERROR_HOST;
260
        else if (g_strcmp0(status , "ERROR_CONF_STUN") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
261
            a->state = ACCOUNT_STATE_ERROR_CONF_STUN;
262
        else if (g_strcmp0(status , "ERROR_EXIST_STUN") == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
263
            a->state = ACCOUNT_STATE_ERROR_EXIST_STUN;
264
        else if (g_strcmp0(status, "READY") == 0)
265
            a->state = IP2IP_PROFILE_STATUS;
266
        else
Emmanuel Milou's avatar
Emmanuel Milou committed
267 268
            a->state = ACCOUNT_STATE_INVALID;

269 270
        gchar * code = g_hash_table_lookup(details, REGISTRATION_STATE_CODE);

271
        if (code != NULL)
272
            a->protocol_state_code = atoi(code);
273

274 275
        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
276 277
    }

278
    // Set the current account message number
279
    current_account_set_message_number(count);
280

281
    sflphone_fill_codec_list();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
282 283
}

284
gboolean sflphone_init(GError **error)
285
{
286
    if (!dbus_connect(error) || !dbus_register(getpid(), "Gtk+ Client", error))
287
        return FALSE;
288

Rafaël Carré's avatar
Rafaël Carré committed
289
    abook_init();
290

291
    // Init icons factory
292
    init_icon_factory();
293

Tristan Matthews's avatar
Tristan Matthews committed
294 295 296
    current_calls_tab = calltab_init(FALSE, CURRENT_CALLS);
    contacts_tab = calltab_init(TRUE, CONTACTS);
    history_tab = calltab_init(TRUE, HISTORY);
297

298 299
    account_list_init();
    codec_capabilities_load();
Tristan Matthews's avatar
Tristan Matthews committed
300
    conferencelist_init(current_calls_tab);
301

302
    // Fetch the configured accounts
303
    sflphone_fill_account_list();
304

305 306
    // Fetch the ip2ip profile
    sflphone_fill_ip2ip_profile();
307

308
    // Fetch the conference list
309
    sflphone_fill_conference_list();
310

311
    return TRUE;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
312 313
}

314
void sflphone_fill_ip2ip_profile(void)
315 316 317 318
{
    ip2ip_profile = (GHashTable *) dbus_get_ip2_ip_details();
}

319
GHashTable *sflphone_get_ip2ip_properties(void)
320
{
321
    return ip2ip_profile;
322 323
}

324
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
325
sflphone_hang_up()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
326
{
Tristan Matthews's avatar
Tristan Matthews committed
327 328
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
329

330
    DEBUG("SFLphone: Hang up");
331

332
    if (selectedConf) {
333 334 335
        im_widget_update_state(IM_WIDGET(selectedConf->_im_widget), FALSE);
        dbus_hang_up_conference(selectedConf);
    } else if (selectedCall) {
336
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
337
            case CALL_STATE_DIALING:
338
                dbus_hang_up(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
339 340
                break;
            case CALL_STATE_RINGING:
341 342
                dbus_hang_up(selectedCall);
                call_remove_all_errors(selectedCall);
343 344
                selectedCall->_state = CALL_STATE_DIALING;
                //selectedCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
345 346 347 348
                break;
            case CALL_STATE_CURRENT:
            case CALL_STATE_HOLD:
            case CALL_STATE_BUSY:
349
            case CALL_STATE_RECORD:
350 351
                dbus_hang_up(selectedCall);
                call_remove_all_errors(selectedCall);
352
                selectedCall->_state = CALL_STATE_DIALING;
353
                time(&selectedCall->_time_stop);
354

355
                im_widget_update_state(IM_WIDGET(selectedCall->_im_widget), FALSE);
356

Emmanuel Milou's avatar
Emmanuel Milou committed
357 358
                break;
            case CALL_STATE_FAILURE:
359 360
                dbus_hang_up(selectedCall);
                call_remove_all_errors(selectedCall);
361
                selectedCall->_state = CALL_STATE_DIALING;
Emmanuel Milou's avatar
Emmanuel Milou committed
362 363
                break;
            case CALL_STATE_INCOMING:
364 365
                dbus_refuse(selectedCall);
                call_remove_all_errors(selectedCall);
366
                selectedCall->_state = CALL_STATE_DIALING;
367
                DEBUG("from sflphone_hang_up : ");
Emmanuel Milou's avatar
Emmanuel Milou committed
368
                break;
369
            case CALL_STATE_TRANSFER:
370 371 372
                dbus_hang_up(selectedCall);
                call_remove_all_errors(selectedCall);
                time(&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
373 374
                break;
            default:
375
                WARN("Should not happen in sflphone_hang_up()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
376 377
                break;
        }
378 379
    }

Tristan Matthews's avatar
Tristan Matthews committed
380
    calltree_update_call(history_tab, selectedCall);
381

382
    statusbar_update_clock("");
383 384 385 386 387

    // 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
388 389
}

390
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
391 392
sflphone_pick_up()
{
Tristan Matthews's avatar
Tristan Matthews committed
393
    callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab);
394

395 396 397 398 399
    // Disable screensaver if the list is empty call
    guint nbcall = calllist_get_size(current_calls_tab);
    if(nbcall == 0)
        dbus_screensaver_inhibit();

400 401 402 403
    if (!selectedCall) {
        sflphone_new_call();
        return;
    }
404

405 406
    switch (selectedCall->_state) {
        case CALL_STATE_DIALING:
407
            sflphone_place_call(selectedCall);
408

409 410
            // if instant messaging window is visible, create new tab (deleted automatically if not used)
            if (im_window_is_visible())
411 412
                if (!selectedCall->_im_widget)
                    selectedCall->_im_widget = im_widget_display(selectedCall->_callID);
413

414 415
            break;
        case CALL_STATE_INCOMING:
416
            selectedCall->_history_state = g_strdup(INCOMING_STRING);
Tristan Matthews's avatar
Tristan Matthews committed
417
            calltree_update_call(history_tab, selectedCall);
418

419
            // if instant messaging window is visible, create new tab (deleted automatically if not used)
420 421 422
            if (im_window_is_visible())
                if (!selectedCall->_im_widget)
                    selectedCall->_im_widget = im_widget_display(selectedCall->_callID);
423

424
            dbus_accept(selectedCall);
425
            break;
426
        case CALL_STATE_TRANSFER:
427 428
            dbus_transfer(selectedCall);
            time(&selectedCall->_time_stop);
Tristan Matthews's avatar
Tristan Matthews committed
429 430
            calltree_remove_call(current_calls_tab, selectedCall);
            calllist_remove_call(current_calls_tab, selectedCall->_callID);
431 432 433 434 435 436 437 438
            break;
        case CALL_STATE_CURRENT:
        case CALL_STATE_HOLD:
        case CALL_STATE_RECORD:
        case CALL_STATE_RINGING:
            sflphone_new_call();
            break;
        default:
439
            WARN("Should not happen in sflphone_pick_up()!");
440
            break;
441
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
442 443
}

444
void
445
sflphone_on_hold()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
446
{
Tristan Matthews's avatar
Tristan Matthews committed
447 448
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
449

450 451
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
452 453
            case CALL_STATE_CURRENT:
            case CALL_STATE_RECORD:
454
                dbus_hold(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
455 456
                break;
            default:
457
                WARN("Should not happen in sflphone_on_hold!");
Emmanuel Milou's avatar
Emmanuel Milou committed
458 459
                break;
        }
460
    } else if (selectedConf)
461
        dbus_hold_conference(selectedConf);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
462 463
}

464
void
465
sflphone_off_hold()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
466
{
467
    DEBUG("sflphone_off_hold");
Tristan Matthews's avatar
Tristan Matthews committed
468 469
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
470

471 472
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
473
            case CALL_STATE_HOLD:
474
                dbus_unhold(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
475 476
                break;
            default:
477
                WARN("Should not happen in sflphone_off_hold ()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
478 479
                break;
        }
480
    } else if (selectedConf)
481
        dbus_unhold_conference(selectedConf);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
482 483 484
}


485
void
486
sflphone_fail(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
487
{
488
    c->_state = CALL_STATE_FAILURE;
Tristan Matthews's avatar
Tristan Matthews committed
489
    calltree_update_call(current_calls_tab, c);
490
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
491 492
}

493
void
494
sflphone_busy(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
495
{
496
    c->_state = CALL_STATE_BUSY;
Tristan Matthews's avatar
Tristan Matthews committed
497
    calltree_update_call(current_calls_tab, c);
498
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
499 500
}

501
void
502
sflphone_current(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
503
{
504
    if (c->_state != CALL_STATE_HOLD)
505
        time(&c->_time_start);
506

507
    c->_state = CALL_STATE_CURRENT;
Tristan Matthews's avatar
Tristan Matthews committed
508
    calltree_update_call(current_calls_tab, c);
509
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
510 511
}

512
void
513
sflphone_record(callable_obj_t * c)
alexandresavard's avatar
alexandresavard committed
514
{
515
    if (c->_state != CALL_STATE_HOLD)
516
        time(&c->_time_start);
517

518
    c->_state = CALL_STATE_RECORD;
Tristan Matthews's avatar
Tristan Matthews committed
519
    calltree_update_call(current_calls_tab, c);
520
    update_actions();
alexandresavard's avatar
alexandresavard committed
521 522
}

523
void
524
sflphone_set_transfer()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
525
{
Tristan Matthews's avatar
Tristan Matthews committed
526
    callable_obj_t * c = calltab_get_selected_call(current_calls_tab);
527 528

    if (c) {
529
        c->_state = CALL_STATE_TRANSFER;
Tristan Matthews's avatar
Tristan Matthews committed
530
        g_free(c->_trsft_to);
531
        c->_trsft_to = g_strdup("");
Tristan Matthews's avatar
Tristan Matthews committed
532
        calltree_update_call(current_calls_tab, c);
Emmanuel Milou's avatar
Emmanuel Milou committed
533
    }
534

535
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
536 537
}

538
void
539
sflphone_unset_transfer()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
540
{
Tristan Matthews's avatar
Tristan Matthews committed
541
    callable_obj_t * c = calltab_get_selected_call(current_calls_tab);
542 543

    if (c) {
544
        c->_state = CALL_STATE_CURRENT;
Tristan Matthews's avatar
Tristan Matthews committed
545
        g_free(c->_trsft_to);
546
        c->_trsft_to = g_strdup("");
Tristan Matthews's avatar
Tristan Matthews committed
547
        calltree_update_call(current_calls_tab, c);
Emmanuel Milou's avatar
Emmanuel Milou committed
548
    }
549

550
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
551
}
Emmanuel Milou's avatar
Emmanuel Milou committed
552

553
void
554
sflphone_display_transfer_status(const gchar* message)
555
{
556
    statusbar_push_message(message , NULL, __MSG_ACCOUNT_DEFAULT);
557 558
}

559
void
560
sflphone_incoming_call(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
561
{
562
    c->_history_state = g_strdup(MISSED_STRING);
Tristan Matthews's avatar
Tristan Matthews committed
563 564
    calllist_add_call(current_calls_tab, c);
    calltree_add_call(current_calls_tab, c, NULL);
565

566
    update_actions();
Tristan Matthews's avatar
Tristan Matthews committed
567
    calltree_display(current_calls_tab);
568 569

    // Change the status bar if we are dealing with a direct SIP call
570
    if (is_direct_call(c)) {
571 572 573 574
        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);
575
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
576
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
577

578
static void
579
process_dialing(callable_obj_t *c, guint keyval, gchar *key)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
580
{
Emmanuel Milou's avatar
Emmanuel Milou committed
581
    // We stop the tone
582
    if (!*c->_peer_number && c->_state != CALL_STATE_TRANSFER)
583
        dbus_start_tone(FALSE, 0);
584

585
    switch (keyval) {
586 587
        case GDK_Return:
        case GDK_KP_Enter:
588
            sflphone_place_call(c);
Emmanuel Milou's avatar
Emmanuel Milou committed
589
            break;
590
        case GDK_Escape:
591
            sflphone_hang_up();
Emmanuel Milou's avatar
Emmanuel Milou committed
592
            break;
593
        case GDK_BackSpace: {
594 595
            gchar *num = (c->_state == CALL_STATE_TRANSFER) ? c->_trsft_to : c->_peer_number;
            size_t len = strlen(num);
596

597 598 599
            if (len) {
                len--; // delete one character
                num[len] = '\0';
Tristan Matthews's avatar
Tristan Matthews committed
600
                calltree_update_call(current_calls_tab, c);
601

602
                /* If number is now empty, hang up immediately */
603
                if (c->_state != CALL_STATE_TRANSFER && len == 0)
604
                    dbus_hang_up(c);
Emmanuel Milou's avatar
Emmanuel Milou committed
605
            }
606

607
            break;
608
        }
609 610 611 612 613
        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
614 615
            break;
        default:
616

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

620
                if (c->_state == CALL_STATE_TRANSFER) {
621 622
                    gchar *new_trsft = g_strconcat(c->_trsft_to, key, NULL);
                    g_free(c->_trsft_to);
Tristan Matthews's avatar
Tristan Matthews committed
623
                    c->_trsft_to = new_trsft;
624
                } else {
625 626 627
                    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
628
                    c->_peer_number = new_peer_number;
Emmanuel Milou's avatar
Emmanuel Milou committed
629
                }
630

Tristan Matthews's avatar
Tristan Matthews committed
631
                calltree_update_call(current_calls_tab, c);
Emmanuel Milou's avatar
Emmanuel Milou committed
632
            }
633

Emmanuel Milou's avatar
Emmanuel Milou committed
634 635
            break;
    }
636 637
}

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

639
callable_obj_t *
areversat's avatar
areversat committed
640
sflphone_new_call()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
641
{