actions.c 31.3 KB
Newer Older
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
1
/*
2
 *  Copyright (C) 2004-2012 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
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 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 35
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

36
#include <glib/gi18n.h>
37
#include <gtk/gtk.h>
38 39

#include "str_utils.h"
Tristan Matthews's avatar
Tristan Matthews committed
40 41 42
#include "uimanager.h"
#include "mainwindow.h"
#include "calltree.h"
43
#include <glib.h>
44
#include <stdlib.h>
45
#include <string.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
46 47 48
#include <sys/types.h>
#include <unistd.h>

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

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

58 59
#include "actions.h"
#include "dbus/dbus.h"
60
#include "account_schema.h"
61
#include "contacts/calltab.h"
62 63 64 65
#include "contacts/searchbar.h"
#include "contacts/addrbookfactory.h"
#include "icons/icon_factory.h"
#include "statusicon.h"
66
#include "sliders.h"
67
#include "messaging/message_tab.h"
68
#include "history_loader.h"
69 70 71
#ifdef SFL_VIDEO
#include "video/video_callbacks.h"
#endif
72

73
static GHashTable * ip2ip_profile;
74

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

82
    g_debug("sflphone_notify_voice_mail begin");
83

84 85
    if (g_ascii_strcasecmp(id, current_id) != 0 ||
        account_list_get_size() == 0)
86 87
        return;

88
    // Set the number of voice messages for the current account
89 90
    current_account_set_message_number(count);
    account_t *current = account_list_get_current();
91

92
    // Update the voicemail tool button
93
    update_voicemail_status();
Emmanuel Milou's avatar
Emmanuel Milou committed
94

95
    if (current)
96
        notify_voice_mails(count, current, client);
Emmanuel Milou's avatar
Emmanuel Milou committed
97

98
    g_debug("sflphone_notify_voice_mail end");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
99 100
}

101 102 103 104 105 106 107
/*
 * 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
 */

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

117
        return TRUE;
Alexandre Savard's avatar
Alexandre Savard committed
118 119
    }

120 121
    return g_str_has_prefix(c->_peer_number, "sip:") ||
           g_str_has_prefix(c->_peer_number, "sips:");
122 123 124
}


125
void
126
status_bar_display_account()
127
{
128
    statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
129

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

Tristan Matthews's avatar
Tristan Matthews committed
133
    gchar* msg;
134
    if (acc) {
135 136
        msg = g_markup_printf_escaped("%s %s (%s)" ,
                                      _("Using account"),
137 138
                                      (gchar*) account_lookup(acc, CONFIG_ACCOUNT_ALIAS),
                                      (gchar*) account_lookup(acc, CONFIG_ACCOUNT_TYPE));
139
    } else {
140
        msg = g_markup_printf_escaped(_("No registered accounts"));
141
    }
142

143
    statusbar_push_message(msg, NULL, __MSG_ACCOUNT_DEFAULT);
144
    g_free(msg);
145 146
}

Emmanuel Milou's avatar
Emmanuel Milou committed
147

148
void
149
sflphone_quit(gboolean force_quit, SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
150
{
151
    if (force_quit || calllist_get_size(current_calls_tab) == 0 || main_window_ask_quit(client)) {
152 153 154
#ifdef SFL_VIDEO
        video_cleanup();
#endif
155 156
        dbus_unregister(getpid());
        dbus_clean();
Rafaël Carré's avatar
Cleanup  
Rafaël Carré committed
157
        account_list_free();
Tristan Matthews's avatar
Tristan Matthews committed
158 159 160
        calllist_clean(current_calls_tab);
        calllist_clean(contacts_tab);
        calllist_clean(history_tab);
161
        g_application_quit(G_APPLICATION(client));
Emmanuel Milou's avatar
Emmanuel Milou committed
162
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
163 164
}

165
void
166
sflphone_hold(callable_obj_t * c, SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
167
{
168
    c->_state = CALL_STATE_HOLD;
169
    calltree_update_call(current_calls_tab, c, client);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
170 171
}

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

179
void
180
sflphone_hung_up(callable_obj_t * c, SFLPhoneClient *client)
Emmanuel Milou's avatar
Emmanuel Milou committed
181
{
182
    disable_messaging_tab(c->_callID);
183
    calllist_remove_call(current_calls_tab, c->_callID, client);
184
    calltree_remove_call(current_calls_tab, c->_callID);
185
    c->_state = CALL_STATE_DIALING;
186
    call_remove_all_errors(c);
187
    update_actions(client);
188

189
    status_tray_icon_blink(FALSE);
190

191
    statusbar_update_clock("");
192 193
}

194
void sflphone_fill_account_list(void)
195
{
Rafaël Carré's avatar
Cleanup  
Rafaël Carré committed
196
    account_list_init();
197
    gchar **array = dbus_account_list();
198

199 200 201
    for (gchar **accountID = array; accountID && *accountID; ++accountID) {
        account_t *acc = create_account_with_ID(*accountID);
        if (acc->properties == NULL) {
202
            g_warning("SFLphone: Error: Could not fetch details for account %s",
203
                      *accountID);
204
            break;
205
        }
206
        account_list_add(acc);
207
        /* Fill the actual array of credentials */
208
        dbus_get_credentials(acc);
209
        gchar * status = account_lookup(acc, CONFIG_ACCOUNT_REGISTRATION_STATUS);
210

211
        if (g_strcmp0(status, "REGISTERED") == 0)
212
            acc->state = ACCOUNT_STATE_REGISTERED;
213
        else if (g_strcmp0(status, "UNREGISTERED") == 0)
214
            acc->state = ACCOUNT_STATE_UNREGISTERED;
215
        else if (g_strcmp0(status, "TRYING") == 0)
216
            acc->state = ACCOUNT_STATE_TRYING;
217
        else if (g_strcmp0(status, "g_warning") == 0)
218
            acc->state = ACCOUNT_STATE_ERROR;
219
        else if (g_strcmp0(status, "g_warning_AUTH") == 0)
220
            acc->state = ACCOUNT_STATE_ERROR_AUTH;
221
        else if (g_strcmp0(status, "g_warning_NETWORK") == 0)
222
            acc->state = ACCOUNT_STATE_ERROR_NETWORK;
223
        else if (g_strcmp0(status, "g_warning_HOST") == 0)
224
            acc->state = ACCOUNT_STATE_ERROR_HOST;
225
        else if (g_strcmp0(status, "g_warning_NOT_ACCEPTABLE") == 0)
226
            acc->state = ACCOUNT_STATE_ERROR_NOT_ACCEPTABLE;
227
        else if (g_strcmp0(status, "g_warning_EXIST_STUN") == 0)
228
            acc->state = ACCOUNT_STATE_ERROR_EXIST_STUN;
229
        else if (g_strcmp0(status, "ACCOUNT_STATE_IP2IP_READY") == 0)
230
            acc->state = ACCOUNT_STATE_IP2IP_READY;
231
        else
232
            acc->state = ACCOUNT_STATE_INVALID;
233

234
        gchar * code = account_lookup(acc, CONFIG_ACCOUNT_REGISTRATION_STATE_CODE);
235
        if (code != NULL)
236
            acc->protocol_state_code = atoi(code);
237
        acc->protocol_state_description = account_lookup(acc, CONFIG_ACCOUNT_REGISTRATION_STATE_DESC);
Emmanuel Milou's avatar
Emmanuel Milou committed
238 239
    }

240
    g_strfreev(array);
241

242
    // Set the current account message number
243
    current_account_set_message_number(current_account_get_message_number());
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
244 245
}

246
gboolean sflphone_init(GError **error, SFLPhoneClient *client)
247
{
248
    if (!dbus_connect(error, client) || !dbus_register(getpid(), "Gtk+ Client", error))
249
        return FALSE;
250

Rafaël Carré's avatar
Rafaël Carré committed
251
    abook_init();
252

253
    // Init icons factory
254
    init_icon_factory();
255

256 257 258
    current_calls_tab = calltab_init(FALSE, CURRENT_CALLS, client);
    contacts_tab = calltab_init(TRUE, CONTACTS, client);
    history_tab = calltab_init(TRUE, HISTORY, client);
259

Tristan Matthews's avatar
Tristan Matthews committed
260
    codecs_load();
Tristan Matthews's avatar
Tristan Matthews committed
261
    conferencelist_init(current_calls_tab);
262

263
    // Fetch the configured accounts
264
    sflphone_fill_account_list();
265

266 267
    // Fetch the ip2ip profile
    sflphone_fill_ip2ip_profile();
268

269
    return TRUE;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
270 271
}

272
void sflphone_fill_ip2ip_profile(void)
273 274 275 276
{
    ip2ip_profile = (GHashTable *) dbus_get_ip2_ip_details();
}

277
GHashTable *sflphone_get_ip2ip_properties(void)
278
{
279
    return ip2ip_profile;
280 281
}

282
void
283
sflphone_hang_up(SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
284
{
Tristan Matthews's avatar
Tristan Matthews committed
285 286
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
287

288
    if (selectedConf) {
289
        disable_messaging_tab(selectedConf->_confID);
290 291
        dbus_hang_up_conference(selectedConf);
    } else if (selectedCall) {
292
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
293
            case CALL_STATE_DIALING:
294
                dbus_hang_up(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
295 296
                break;
            case CALL_STATE_RINGING:
297
                dbus_hang_up(selectedCall);
298
                call_remove_all_errors(selectedCall);
299 300
                selectedCall->_state = CALL_STATE_DIALING;
                //selectedCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
301 302 303 304
                break;
            case CALL_STATE_CURRENT:
            case CALL_STATE_HOLD:
            case CALL_STATE_BUSY:
305
                dbus_hang_up(selectedCall);
306
                call_remove_all_errors(selectedCall);
307
                selectedCall->_state = CALL_STATE_DIALING;
308
                time(&selectedCall->_time_stop);
309

Emmanuel Milou's avatar
Emmanuel Milou committed
310 311
                break;
            case CALL_STATE_FAILURE:
312
                dbus_hang_up(selectedCall);
313
                call_remove_all_errors(selectedCall);
314
                selectedCall->_state = CALL_STATE_DIALING;
Emmanuel Milou's avatar
Emmanuel Milou committed
315 316
                break;
            case CALL_STATE_INCOMING:
317
                dbus_refuse(selectedCall);
318
                call_remove_all_errors(selectedCall);
319
                selectedCall->_state = CALL_STATE_DIALING;
320
                g_debug("from sflphone_hang_up : ");
Emmanuel Milou's avatar
Emmanuel Milou committed
321
                break;
322
            case CALL_STATE_TRANSFER:
323
                dbus_hang_up(selectedCall);
324
                call_remove_all_errors(selectedCall);
325
                time(&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
326 327
                break;
            default:
328
                g_warning("Should not happen in sflphone_hang_up()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
329 330
                break;
        }
331 332
    }

333
    calltree_update_call(history_tab, selectedCall, client);
334

335
    statusbar_update_clock("");
336 337 338 339 340

    // 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
341 342
}

343
void
344
sflphone_pick_up(SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
345
{
Tristan Matthews's avatar
Tristan Matthews committed
346
    callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab);
347

348 349 350 351 352
    // Disable screensaver if the list is empty call
    guint nbcall = calllist_get_size(current_calls_tab);
    if(nbcall == 0)
        dbus_screensaver_inhibit();

353
    if (!selectedCall) {
354
        sflphone_new_call(client);
355 356
        return;
    }
357

358 359
    switch (selectedCall->_state) {
        case CALL_STATE_DIALING:
360
            sflphone_place_call(selectedCall, client);
361 362
            break;
        case CALL_STATE_INCOMING:
363
            selectedCall->_history_state = g_strdup(INCOMING_STRING);
364
            calltree_update_call(history_tab, selectedCall, client);
365

366
            dbus_accept(selectedCall);
367
            break;
368
        case CALL_STATE_TRANSFER:
369 370
            dbus_transfer(selectedCall);
            time(&selectedCall->_time_stop);
371
            calltree_remove_call(current_calls_tab, selectedCall->_callID);
372 373
            update_actions(client);
            calllist_remove_call(current_calls_tab, selectedCall->_callID, client);
374 375 376 377
            break;
        case CALL_STATE_CURRENT:
        case CALL_STATE_HOLD:
        case CALL_STATE_RINGING:
378
            sflphone_new_call(client);
379 380
            break;
        default:
381
            g_warning("Should not happen in sflphone_pick_up()!");
382
            break;
383
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
384 385
}

386
void
387
sflphone_on_hold()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
388
{
Tristan Matthews's avatar
Tristan Matthews committed
389 390
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
391

392 393
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
394
            case CALL_STATE_CURRENT:
395
                dbus_hold(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
396 397
                break;
            default:
398
                g_warning("Should not happen in sflphone_on_hold!");
Emmanuel Milou's avatar
Emmanuel Milou committed
399 400
                break;
        }
401
    } else if (selectedConf)
402
        dbus_hold_conference(selectedConf);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
403 404
}

405
void
406
sflphone_off_hold()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
407
{
408
    g_debug("%s", __PRETTY_FUNCTION__);
Tristan Matthews's avatar
Tristan Matthews committed
409 410
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
411

412 413
    if (selectedCall) {
        switch (selectedCall->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
414
            case CALL_STATE_HOLD:
415
                dbus_unhold(selectedCall);
Emmanuel Milou's avatar
Emmanuel Milou committed
416 417
                break;
            default:
418
                g_warning("Should not happen in sflphone_off_hold ()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
419 420
                break;
        }
421
    } else if (selectedConf)
422
        dbus_unhold_conference(selectedConf);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
423 424 425
}


426
void
427
sflphone_fail(callable_obj_t * c, SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
428
{
429
    c->_state = CALL_STATE_FAILURE;
430
    calltree_update_call(current_calls_tab, c, client);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
431 432
}

433
void
434
sflphone_busy(callable_obj_t * c, SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
435
{
436
    c->_state = CALL_STATE_BUSY;
437
    calltree_update_call(current_calls_tab, c, client);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
438 439
}

440
void
441
sflphone_current(callable_obj_t * c, SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
442
{
443
    if (c->_state != CALL_STATE_HOLD)
444
        time(&c->_time_start);
445

446
    c->_state = CALL_STATE_CURRENT;
447
    calltree_update_call(current_calls_tab, c, client);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
448 449
}

450
void
451
sflphone_set_transfer(SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
452
{
Tristan Matthews's avatar
Tristan Matthews committed
453
    callable_obj_t * c = calltab_get_selected_call(current_calls_tab);
454 455

    if (c) {
456
        c->_state = CALL_STATE_TRANSFER;
Tristan Matthews's avatar
Tristan Matthews committed
457
        g_free(c->_trsft_to);
458
        c->_trsft_to = g_strdup("");
459
        calltree_update_call(current_calls_tab, c, client);
460
    } else {
461
        update_actions(client);
Emmanuel Milou's avatar
Emmanuel Milou committed
462
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
463 464
}

465
void
466
sflphone_unset_transfer(SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
467
{
Tristan Matthews's avatar
Tristan Matthews committed
468
    callable_obj_t * c = calltab_get_selected_call(current_calls_tab);
469 470

    if (c) {
471
        c->_state = CALL_STATE_CURRENT;
Tristan Matthews's avatar
Tristan Matthews committed
472
        g_free(c->_trsft_to);
473
        c->_trsft_to = g_strdup("");
474
        calltree_update_call(current_calls_tab, c, client);
475
    } else {
476
        update_actions(client);
Emmanuel Milou's avatar
Emmanuel Milou committed
477
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
478
}
Emmanuel Milou's avatar
Emmanuel Milou committed
479

480
void
481
sflphone_display_transfer_status(const gchar* message)
482
{
483
    statusbar_push_message(message , NULL, __MSG_ACCOUNT_DEFAULT);
484 485
}

486
void
487
sflphone_incoming_call(callable_obj_t * c, SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
488
{
489
    c->_history_state = g_strdup(MISSED_STRING);
Tristan Matthews's avatar
Tristan Matthews committed
490 491
    calllist_add_call(current_calls_tab, c);
    calltree_add_call(current_calls_tab, c, NULL);
492

493 494
    update_actions(client);
    calltree_display(current_calls_tab, client);
495 496

    // Change the status bar if we are dealing with a direct SIP call
497
    if (is_direct_call(c)) {
498 499 500 501
        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);
502
    }
503
    account_t *account = account_list_get_by_id(c->_accountID);
504
    if (!account) {
505
        g_warning("Account is NULL");
506
    } else if (account_has_autoanswer_on(account)) {
507
        calltab_set_selected_call(active_calltree_tab, c);
508
        sflphone_pick_up(client);
509
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
510
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
511

512
static void
513
process_dialing(callable_obj_t *c, guint keyval, const gchar *key, SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
514
{
Emmanuel Milou's avatar
Emmanuel Milou committed
515
    // We stop the tone
516
    if (!*c->_peer_number && c->_state != CALL_STATE_TRANSFER)
517
        dbus_start_tone(FALSE, 0);
518

519
    switch (keyval) {
520 521
        case GDK_KEY_Return:
        case GDK_KEY_KP_Enter:
522
            sflphone_place_call(c, client);
Emmanuel Milou's avatar
Emmanuel Milou committed
523
            break;
524
        case GDK_KEY_Escape:
525
            sflphone_hang_up(client);
Emmanuel Milou's avatar
Emmanuel Milou committed
526
            break;
527
        case GDK_KEY_BackSpace: {
528 529
            gchar *num = (c->_state == CALL_STATE_TRANSFER) ? c->_trsft_to : c->_peer_number;
            size_t len = strlen(num);
530

531 532 533
            if (len) {
                len--; // delete one character
                num[len] = '\0';
534
                calltree_update_call(current_calls_tab, c, client);
535

536
                /* If number is now empty, hang up immediately */
537
                if (c->_state != CALL_STATE_TRANSFER && len == 0)
538
                    dbus_hang_up(c);
Emmanuel Milou's avatar
Emmanuel Milou committed
539
            }
540

541
            break;
542
        }
543 544 545 546 547 548 549 550
        case GDK_KEY_Tab:
        case GDK_KEY_Alt_L:
        case GDK_KEY_Alt_R:
        case GDK_KEY_Control_L:
        case GDK_KEY_Control_R:
        case GDK_KEY_Super_L:
        case GDK_KEY_Super_R:
        case GDK_KEY_Caps_Lock:
Emmanuel Milou's avatar
Emmanuel Milou committed
551 552
            break;
        default:
553

554
            if (keyval < 127 /* ascii */ ||
555
                    (keyval >= GDK_KEY_Mode_switch && keyval <= GDK_KEY_KP_9) /* num keypad */) {
556

557
                if (c->_state == CALL_STATE_TRANSFER) {
558 559
                    gchar *new_trsft = g_strconcat(c->_trsft_to, key, NULL);
                    g_free(c->_trsft_to);
Tristan Matthews's avatar
Tristan Matthews committed
560
                    c->_trsft_to = new_trsft;
561
                } else {
562 563 564
                    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
565
                    c->_peer_number = new_peer_number;
Emmanuel Milou's avatar
Emmanuel Milou committed
566
                }
567

568
                calltree_update_call(current_calls_tab, c, client);
Emmanuel Milou's avatar
Emmanuel Milou committed
569
            }
570

Emmanuel Milou's avatar
Emmanuel Milou committed
571 572
            break;
    }
573 574
}

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

576
callable_obj_t *
577
sflphone_new_call(SFLPhoneClient *client)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
578
{
579 580 581 582 583
    // 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
584
    callable_obj_t *current_selected_call = calltab_get_selected_call(current_calls_tab);
585

586 587 588 589 590 591
    if (current_selected_call != NULL) {
        gchar *confID = dbus_get_conference_id(current_selected_call->_callID);
        if(g_strcmp0(confID, "") != 0) {
            sflphone_on_hold();
        }
    }
592

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

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

599
    c->_history_state = g_strdup(OUTGOING_STRING);
600

Tristan Matthews's avatar
Tristan Matthews committed
601 602
    calllist_add_call(current_calls_tab, c);
    calltree_add_call(current_calls_tab, c, NULL);
603
    update_actions(client);
604

Emmanuel Milou's avatar
Emmanuel Milou committed
605
    return c;
606 607
}

areversat's avatar
areversat committed
608

609
void
610
sflphone_keypad(guint keyval, const gchar * key, SFLPhoneClient *client)
areversat's avatar
areversat committed
611
{
Tristan Matthews's avatar
Tristan Matthews committed
612
    callable_obj_t * c = calltab_get_selected_call(current_calls_tab);
613

614 615
    const gboolean current_is_active_tab = calltab_has_name(active_calltree_tab, CURRENT_CALLS);
    if (!current_is_active_tab || (current_is_active_tab && !c)) {
616
        switch (keyval) {
617 618 619 620
            case GDK_KEY_Return:
            case GDK_KEY_KP_Enter:
            case GDK_KEY_Escape:
            case GDK_KEY_BackSpace:
Emmanuel Milou's avatar
Emmanuel Milou committed
621 622
                break;
            default:
623 624
                calltree_display(current_calls_tab, client);
                process_dialing(sflphone_new_call(client), keyval, key, client);
Emmanuel Milou's avatar
Emmanuel Milou committed
625 626
                break;
        }
627 628
    } else if (c) {
        switch (c->_state) {
Emmanuel Milou's avatar
Emmanuel Milou committed
629
            case CALL_STATE_DIALING: // Currently dialing => edit number
630
                process_dialing(c, keyval, key, client);
Emmanuel Milou's avatar
Emmanuel Milou committed
631 632
                break;
            case