actions.c 34.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
#include <gtk/gtk.h>
33 34 35 36
/* Backward compatibility for gtk < 2.22.0 */
#if GTK_CHECK_VERSION(2,22,0)
#include <gdk/gdkkeysyms-compat.h>
#else
37
#include <gdk/gdkkeysyms.h>
38
#endif
39 40
#include <glib/gprintf.h>
#include <stdlib.h>
41
#include <string.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
42 43 44
#include <sys/types.h>
#include <unistd.h>

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

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

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

66
static GHashTable * ip2ip_profile;
67

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

75
    DEBUG("sflphone_notify_voice_mail begin");
76

77
    if (g_ascii_strcasecmp(id, current_id) != 0 || account_list_get_size() == 0)
78 79
        return;

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

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

87
    if (current)
88
        notify_voice_mails(count, current);
Emmanuel Milou's avatar
Emmanuel Milou committed
89

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

93 94 95 96 97 98 99
/*
 * 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
 */

100
static gboolean _is_direct_call(callable_obj_t * c)
101
{
102 103 104 105
    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);
106 107
            c->_peer_number = new_number;
        }
108

109
        return TRUE;
Alexandre Savard's avatar
Alexandre Savard committed
110 111
    }

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


117
void
118
status_bar_display_account()
119
{
120
    gchar* msg;
121

122
    statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
123

124 125
    account_t *acc = account_list_get_current();
    status_tray_icon_online(acc != NULL);
126 127

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

136 137
    statusbar_push_message(msg, NULL,  __MSG_ACCOUNT_DEFAULT);
    g_free(msg);
138 139
}

Emmanuel Milou's avatar
Emmanuel Milou committed
140

141
void
142
sflphone_quit()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
143
{
Tristan Matthews's avatar
Tristan Matthews committed
144
    if (calllist_get_size(current_calls_tab) == 0 || main_window_ask_quit()) {
145
        // Save the history
146
        sflphone_save_history();
147

148 149
        dbus_unregister(getpid());
        dbus_clean();
Rafaël Carré's avatar
Cleanup  
Rafaël Carré committed
150
        account_list_free();
Tristan Matthews's avatar
Tristan Matthews committed
151 152 153 154 155 156
        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);
157
        gtk_main_quit();
Emmanuel Milou's avatar
Emmanuel Milou committed
158
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
159 160
}

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

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

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

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

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

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

199
    status_tray_icon_blink(FALSE);
200

201
    statusbar_update_clock("");
202 203
}

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

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

212
    gchar **array = dbus_account_list();
213

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

222
        g_strfreev(array);
223
    }
224

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

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

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

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

240
        a->properties = details;
241 242

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

383
    statusbar_update_clock("");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
384 385
}

386
void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
387 388
sflphone_pick_up()
{
Tristan Matthews's avatar
Tristan Matthews committed
389
    callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab);
390

391 392 393 394
    if (!selectedCall) {
        sflphone_new_call();
        return;
    }
395

396 397
    switch (selectedCall->_state) {
        case CALL_STATE_DIALING:
398
            sflphone_place_call(selectedCall);
399

400 401
            // if instant messaging window is visible, create new tab (deleted automatically if not used)
            if (im_window_is_visible())
402 403
                if (!selectedCall->_im_widget)
                    selectedCall->_im_widget = im_widget_display(selectedCall->_callID);
404

405 406
            break;
        case CALL_STATE_INCOMING:
407
            selectedCall->_history_state = g_strdup(INCOMING_STRING);
Tristan Matthews's avatar
Tristan Matthews committed
408
            calltree_update_call(history_tab, selectedCall);
409

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

415
            dbus_accept(selectedCall);
416
            break;
417
        case CALL_STATE_TRANSFER:
418 419
            dbus_transfer(selectedCall);
            time(&selectedCall->_time_stop);
Tristan Matthews's avatar
Tristan Matthews committed
420 421
            calltree_remove_call(current_calls_tab, selectedCall);
            calllist_remove_call(current_calls_tab, selectedCall->_callID);
422 423 424 425 426 427 428 429
            break;
        case CALL_STATE_CURRENT:
        case CALL_STATE_HOLD:
        case CALL_STATE_RECORD:
        case CALL_STATE_RINGING:
            sflphone_new_call();
            break;
        default:
430
            WARN("Should not happen in sflphone_pick_up()!");
431
            break;
432
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
433 434
}

435
void
436
sflphone_on_hold()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
437
{
Tristan Matthews's avatar
Tristan Matthews committed
438 439
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
440

441 442
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
443 444
            case CALL_STATE_CURRENT:
            case CALL_STATE_RECORD:
445
                dbus_hold(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
446 447
                break;
            default:
448
                WARN("Should not happen in sflphone_on_hold!");
Emmanuel Milou's avatar
Emmanuel Milou committed
449 450
                break;
        }
451
    } else if (selectedConf)
452
        dbus_hold_conference(selectedConf);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
453 454
}

455
void
456
sflphone_off_hold()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
457
{
458
    DEBUG("sflphone_off_hold");
Tristan Matthews's avatar
Tristan Matthews committed
459 460
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
461

462 463
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
464
            case CALL_STATE_HOLD:
465
                dbus_unhold(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
466 467
                break;
            default:
468
                WARN("Should not happen in sflphone_off_hold ()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
469 470
                break;
        }
471
    } else if (selectedConf)
472
        dbus_unhold_conference(selectedConf);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
473 474 475
}


476
void
477
sflphone_fail(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
478
{
479
    c->_state = CALL_STATE_FAILURE;
Tristan Matthews's avatar
Tristan Matthews committed
480
    calltree_update_call(current_calls_tab, c);
481
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
482 483
}

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

492
void
493
sflphone_current(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
494
{
495
    if (c->_state != CALL_STATE_HOLD)
496
        time(&c->_time_start);
497

498
    c->_state = CALL_STATE_CURRENT;
Tristan Matthews's avatar
Tristan Matthews committed
499
    calltree_update_call(current_calls_tab, c);
500
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
501 502
}

503
void
504
sflphone_record(callable_obj_t * c)
alexandresavard's avatar
alexandresavard committed
505
{
506
    if (c->_state != CALL_STATE_HOLD)
507
        time(&c->_time_start);
508

509
    c->_state = CALL_STATE_RECORD;
Tristan Matthews's avatar
Tristan Matthews committed
510
    calltree_update_call(current_calls_tab, c);
511
    update_actions();
alexandresavard's avatar
alexandresavard committed
512 513
}

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

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

526
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
527 528
}

529
void
530
sflphone_unset_transfer()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
531
{
Tristan Matthews's avatar
Tristan Matthews committed
532
    callable_obj_t * c = calltab_get_selected_call(current_calls_tab);
533 534

    if (c) {
535
        c->_state = CALL_STATE_CURRENT;
Tristan Matthews's avatar
Tristan Matthews committed
536
        g_free(c->_trsft_to);
537
        c->_trsft_to = g_strdup("");
Tristan Matthews's avatar
Tristan Matthews committed
538
        calltree_update_call(current_calls_tab, c);
Emmanuel Milou's avatar
Emmanuel Milou committed
539
    }
540

541
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
542
}
Emmanuel Milou's avatar
Emmanuel Milou committed
543

544
void
545
sflphone_display_transfer_status(const gchar* message)
546
{
547
    statusbar_push_message(message , NULL, __MSG_ACCOUNT_DEFAULT);
548 549
}

550
void
551
sflphone_incoming_call(callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
552
{
553
    c->_history_state = g_strdup(MISSED_STRING);
Tristan Matthews's avatar
Tristan Matthews committed
554 555
    calllist_add_call(current_calls_tab, c);
    calltree_add_call(current_calls_tab, c, NULL);
556

557
    update_actions();
Tristan Matthews's avatar
Tristan Matthews committed
558
    calltree_display(current_calls_tab);
559 560

    // Change the status bar if we are dealing with a direct SIP call
561 562 563 564 565
    if (_is_direct_call(c)) {
        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);
566
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
567
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
568

569
static void
570
process_dialing(callable_obj_t *c, guint keyval, gchar *key)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
571
{
Emmanuel Milou's avatar
Emmanuel Milou committed
572
    // We stop the tone
573
    if (!*c->_peer_number && c->_state != CALL_STATE_TRANSFER)
574
        dbus_start_tone(FALSE, 0);
575

576
    switch (keyval) {
577 578
        case GDK_Return:
        case GDK_KP_Enter:
579
            sflphone_place_call(c);
Emmanuel Milou's avatar
Emmanuel Milou committed
580
            break;
581
        case GDK_Escape:
582
            sflphone_hang_up();
Emmanuel Milou's avatar
Emmanuel Milou committed
583
            break;
584
        case GDK_BackSpace: {
585 586
            gchar *num = (c->_state == CALL_STATE_TRANSFER) ? c->_trsft_to : c->_peer_number;
            size_t len = strlen(num);
587

588 589 590
            if (len) {
                len--; // delete one character
                num[len] = '\0';
Tristan Matthews's avatar
Tristan Matthews committed
591
                calltree_update_call(current_calls_tab, c);
592

593
                /* If number is now empty, hang up immediately */
594
                if (c->_state != CALL_STATE_TRANSFER && len == 0)
595
                    dbus_hang_up(c);
Emmanuel Milou's avatar
Emmanuel Milou committed
596
            }
597

598
            break;
599
        }
600 601 602 603 604
        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
605 606
            break;
        default:
607

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

611
                if (c->_state == CALL_STATE_TRANSFER) {
612 613
                    gchar *new_trsft = g_strconcat(c->_trsft_to, key, NULL);
                    g_free(c->_trsft_to);
Tristan Matthews's avatar
Tristan Matthews committed
614
                    c->_trsft_to = new_trsft;
615
                } else {
616 617 618
                    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
619
                    c->_peer_number = new_peer_number;
Emmanuel Milou's avatar
Emmanuel Milou committed
620
                }
621

Tristan Matthews's avatar
Tristan Matthews committed
622
                calltree_update_call(current_calls_tab, c);
Emmanuel Milou's avatar
Emmanuel Milou committed
623
            }
624

Emmanuel Milou's avatar
Emmanuel Milou committed
625 626
            break;
    }
627 628
}

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

630
callable_obj_t *
areversat's avatar
areversat committed
631
sflphone_new_call()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
632
{
Tristan Matthews's avatar
Tristan Matthews committed
633
    callable_obj_t *current_selected_call = calltab_get_selected_call(current_calls_tab);
634

635
    if ((current_selected_call != NULL) && (current_selected_call->_confID == NULL))
636
        sflphone_on_hold();
637

Emmanuel Milou's avatar
Emmanuel Milou committed
638
    // Play a tone when creating a new call
Tristan Matthews's avatar
Tristan Matthews committed
<