uimanager.c 65.2 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 *  Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com
 *
 *  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
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  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.
 *
 *  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.
18
19
20
21
22
23
24
25
26
27
28
 *
 *  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.
29
30
 */

31
32
33
34
35
36
#include "config.h"
#include "preferencesdialog.h"
#include "logger.h"
#include "dbus/dbus.h"
#include "mainwindow.h"
#include "assistant.h"
37
#include <gtk/gtk.h>
38
#include <string.h>
39
#include <glib/gprintf.h>
40

41
42
43
44
#include "uimanager.h"
#include "statusicon.h"
#include "widget/imwidget.h"
#include "eel-gconf-extensions.h"
45

46
#include "config/audioconf.h"
47
#include "unused.h"
Julien Bonjean's avatar
Julien Bonjean committed
48
49
#include "uimanager.h"
#include "statusicon.h"
50
51

#include "contacts/addrbookfactory.h"
52
#include "contacts/calltab.h"
53
#include "config/addressbook-config.h"
54

Tristan Matthews's avatar
Tristan Matthews committed
55
56
#include "eel-gconf-extensions.h"

Julien Bonjean's avatar
Julien Bonjean committed
57
58
59
#include "accountlist.h"
#include "config/accountlistconfigdialog.h"

60
61
#include <sys/stat.h>

62
63
#include <sliders.h>

64
65
66
67
68
69
void show_edit_number(callable_obj_t *call);

static GtkWidget *toolbar_;

static guint transferButtonConnId_; //The button toggled signal connection ID
static guint recordButtonConnId_; //The button toggled signal connection ID
70
static guint muteCallButtonId_; //The button toggled signal connection ID
71
72
73
74
75
76
77
78
79
80
81
82
83
84

static GtkAction * pickUpAction_;
static GtkWidget * pickUpWidget_;
static GtkAction * newCallAction_;
static GtkWidget * newCallWidget_;
static GtkAction * hangUpAction_;
static GtkWidget * hangUpWidget_;
static GtkWidget * holdMenu_;
static GtkWidget * holdToolbar_;
static GtkWidget * offHoldToolbar_;
static GtkWidget * transferToolbar_;
static GtkAction * copyAction_;
static GtkAction * pasteAction_;
static GtkAction * recordAction_;
85
static GtkAction * muteAction_;
86
static GtkWidget * recordWidget_;
87
static GtkWidget * muteWidget_;
88
89
90
91
92
93
94
95
96
static GtkAction * voicemailAction_;
static GtkWidget * voicemailToolbar_;
static GtkWidget * imToolbar_;
static GtkAction * imAction_;
static GtkWidget * playRecordWidget_;
static GtkWidget * stopRecordWidget_;

static GtkWidget * editable_num_;
static GtkWidget * edit_dialog_;
97

98
99
enum {
    CALLTREE_CALLS, CALLTREE_HISTORY, CALLTREE_CONTACTS
100
};
101

102
103
static void
remove_from_toolbar(GtkWidget *widget)
104
{
105
106
    /* We must ensure that a widget is a child of a container
     * before removing it. */
107
    if (gtk_widget_get_parent(widget) == toolbar_)
108
        gtk_container_remove(GTK_CONTAINER(toolbar_), widget);
109
110
}

Tristan Matthews's avatar
Tristan Matthews committed
111
static bool
112
is_non_empty(const char *str)
Tristan Matthews's avatar
Tristan Matthews committed
113
114
115
116
{
    return str && strlen(str) > 0;
}

117
118
119
120
121
122
123
124
/* Inserts an item in a toolbar at a given position, making sure that the index
 * is valid, that it does not exceed the number of elements */
static void add_to_toolbar(GtkWidget *toolbar, GtkWidget *item, int pos)
{
    g_assert(gtk_toolbar_get_n_items(GTK_TOOLBAR(toolbar)) >= pos);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), pos);
}

125
126
127
128
129
130
131
static void
call_mute(void)
{
    DEBUG("UIManager: Mute call button pressed");
    sflphone_mute_call();
}

132
void
133
update_actions()
134
{
135
136
    int pos = 0;

137
138
139
140
141
142
143
    gtk_action_set_sensitive(newCallAction_, TRUE);
    gtk_action_set_sensitive(pickUpAction_, FALSE);
    gtk_action_set_sensitive(hangUpAction_, FALSE);
    gtk_action_set_sensitive(imAction_, FALSE);

    g_object_ref(hangUpWidget_);
    g_object_ref(recordWidget_);
144
    g_object_ref(muteWidget_);
145
146
    g_object_ref(holdToolbar_);
    g_object_ref(offHoldToolbar_);
147

Rafaël Carré's avatar
Rafaël Carré committed
148
    if (addrbook)
149
150
151
152
153
154
155
156
157
        g_object_ref(contactButton_);

    g_object_ref(historyButton_);
    g_object_ref(transferToolbar_);
    g_object_ref(voicemailToolbar_);
    g_object_ref(imToolbar_);

    remove_from_toolbar(hangUpWidget_);
    remove_from_toolbar(recordWidget_);
158
    remove_from_toolbar(muteWidget_);
159
160
161
    remove_from_toolbar(transferToolbar_);
    remove_from_toolbar(historyButton_);

Rafaël Carré's avatar
Rafaël Carré committed
162
    if (addrbook)
163
164
165
166
167
168
169
170
171
        remove_from_toolbar(contactButton_);

    remove_from_toolbar(voicemailToolbar_);
    remove_from_toolbar(imToolbar_);

    gtk_widget_set_sensitive(holdMenu_, FALSE);
    gtk_widget_set_sensitive(holdToolbar_, FALSE);
    gtk_widget_set_sensitive(offHoldToolbar_, FALSE);
    gtk_action_set_sensitive(recordAction_, FALSE);
172
    gtk_action_set_sensitive(muteAction_, FALSE);
173
    gtk_widget_set_sensitive(recordWidget_, FALSE);
174
    gtk_widget_set_sensitive(muteWidget_, FALSE);
175
176
    gtk_action_set_sensitive(copyAction_, FALSE);

Rafaël Carré's avatar
Rafaël Carré committed
177
    if (addrbook)
178
179
180
        gtk_widget_set_sensitive(contactButton_, FALSE);

    gtk_widget_set_sensitive(historyButton_, FALSE);
181

Rafaël Carré's avatar
Rafaël Carré committed
182
    if (addrbook)
183
184
185
186
187
188
189
        gtk_widget_set_tooltip_text(contactButton_, _("No address book selected"));

    remove_from_toolbar(holdToolbar_);
    remove_from_toolbar(offHoldToolbar_);
    remove_from_toolbar(newCallWidget_);
    remove_from_toolbar(pickUpWidget_);

190
    add_to_toolbar(toolbar_, newCallWidget_, 0);
191
192
193
194
195

    remove_from_toolbar(playRecordWidget_);
    remove_from_toolbar(stopRecordWidget_);

    if (eel_gconf_get_integer(HISTORY_ENABLED)) {
196
        add_to_toolbar(toolbar_, historyButton_, -1);
197
        gtk_widget_set_sensitive(historyButton_, TRUE);
198
199
    }

200
201
202
203
204
205
    GtkToolItem *separator = gtk_separator_tool_item_new();
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), separator, -1);
    // add mute button
    add_to_toolbar(toolbar_, muteWidget_, -1);
    gtk_action_set_sensitive(muteAction_, TRUE);

206
    // If addressbook support has been enabled and all addressbooks are loaded, display the icon
Rafaël Carré's avatar
Cleanup    
Rafaël Carré committed
207
    if (addrbook && addrbook->is_ready() && addressbook_config_load_parameters()->enable) {
208
        add_to_toolbar(toolbar_, contactButton_, -1);
209

Rafaël Carré's avatar
Cleanup    
Rafaël Carré committed
210
211
212
213
        // Make the icon clickable only if at least one address book is active
        if (addrbook->is_active()) {
            gtk_widget_set_sensitive(contactButton_, TRUE);
            gtk_widget_set_tooltip_text(contactButton_, _("Address book"));
214
215
216
        }
    }

Tristan Matthews's avatar
Tristan Matthews committed
217
218
    callable_obj_t * selectedCall = calltab_get_selected_call(active_calltree_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
219

220
    gboolean instant_messaging_enabled = TRUE;
221

222
223
    if (eel_gconf_key_exists(INSTANT_MESSAGING_ENABLED))
        instant_messaging_enabled = eel_gconf_get_integer(INSTANT_MESSAGING_ENABLED);
224

225
226
    if (selectedCall) {
        DEBUG("UIManager: Update actions for call %s", selectedCall->_callID);
227

228
229
230
        // update icon in systray
        show_status_hangup_icon();

231
        gtk_action_set_sensitive(copyAction_, TRUE);
232
233
234

        switch (selectedCall->_state) {
            case CALL_STATE_INCOMING:
235
236
237
238
239
240
241
242
                {
                    DEBUG("UIManager: Call State Incoming");
                    // Make the button toolbar clickable
                    gtk_action_set_sensitive(pickUpAction_, TRUE);
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
                    // Replace the dial button with the hangup button
                    g_object_ref(newCallWidget_);
                    remove_from_toolbar(newCallWidget_);
243
                    pos = 0;
244
                    add_to_toolbar(toolbar_, pickUpWidget_, pos++);
245
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
246
247
                    break;
                }
248
            case CALL_STATE_HOLD:
249
250
251
252
253
254
                {
                    DEBUG("UIManager: Call State Hold");
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
                    gtk_widget_set_sensitive(holdMenu_, TRUE);
                    gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
                    gtk_widget_set_sensitive(newCallWidget_, TRUE);
255

256
                    // Replace the hold button with the off-hold button
257
                    pos = 1;
258
259
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                    add_to_toolbar(toolbar_, offHoldToolbar_, pos++);
260

261
262
                    if (instant_messaging_enabled) {
                        gtk_action_set_sensitive(imAction_, TRUE);
263
                        add_to_toolbar(toolbar_, imToolbar_, pos++);
264
                    }
265

266
267
                    break;
                }
268
            case CALL_STATE_RINGING:
269
270
271
                {
                    DEBUG("UIManager: Call State Ringing");
                    gtk_action_set_sensitive(pickUpAction_, TRUE);
272
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
273
274
                    pos = 1;
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
275
276
277
278
279
280
281
282
283
284
285
286
                    break;
                }
            case CALL_STATE_DIALING:
                {
                    DEBUG("UIManager: Call State Dialing");
                    gtk_action_set_sensitive(pickUpAction_, TRUE);

                    if (active_calltree_tab == current_calls_tab)
                        gtk_action_set_sensitive(hangUpAction_, TRUE);

                    g_object_ref(newCallWidget_);
                    remove_from_toolbar(newCallWidget_);
287
                    pos = 0;
288
289
290
291
292
                    add_to_toolbar(toolbar_, pickUpWidget_, pos++);

                    if (active_calltree_tab == current_calls_tab)
                        add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                    else if (active_calltree_tab == history_tab) {
293
                        if (is_non_empty(selectedCall->_recordfile)) {
294
                            if (selectedCall->_record_is_playing)
295
                                add_to_toolbar(toolbar_, stopRecordWidget_, pos++);
296
                            else
297
                                add_to_toolbar(toolbar_, playRecordWidget_, pos++);
298
                        }
299
                    }
300
                    break;
301
                }
302
303
304
305
            case CALL_STATE_CURRENT:
                {
                    DEBUG("UIManager: Call State Current");
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
306
                    pos = 1;
307
308
309
310
311
312
313
314
315
316
317
318
319
320
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                    gtk_widget_set_sensitive(holdMenu_, TRUE);
                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
                    gtk_widget_set_sensitive(transferToolbar_, TRUE);
                    gtk_action_set_sensitive(recordAction_, TRUE);
                    add_to_toolbar(toolbar_, holdToolbar_, pos++);
                    add_to_toolbar(toolbar_, transferToolbar_, pos++);
                    add_to_toolbar(toolbar_, recordWidget_, pos++);
                    g_signal_handler_block(transferToolbar_, transferButtonConnId_);
                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
                    g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
                    g_signal_handler_block(recordWidget_, recordButtonConnId_);
                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE);
                    g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
321

322
323
                    if (instant_messaging_enabled) {
                        gtk_action_set_sensitive(imAction_, TRUE);
324
                        add_to_toolbar(toolbar_, imToolbar_, pos++);
325
                    }
326

327
                    break;
328
                }
329

330
331
332
            case CALL_STATE_RECORD:
                {
                    DEBUG("UIManager: Call State Record");
333
                    pos = 1;
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                    gtk_widget_set_sensitive(holdMenu_, TRUE);
                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
                    gtk_widget_set_sensitive(transferToolbar_, TRUE);
                    gtk_action_set_sensitive(recordAction_, TRUE);
                    add_to_toolbar(toolbar_, holdToolbar_, pos++);
                    add_to_toolbar(toolbar_, transferToolbar_, pos++);
                    add_to_toolbar(toolbar_, recordWidget_, pos++);
                    g_signal_handler_block(transferToolbar_, transferButtonConnId_);
                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
                    g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
                    g_signal_handler_block(recordWidget_, recordButtonConnId_);
                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE);
                    g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
349

350
351
                    if (instant_messaging_enabled) {
                        gtk_action_set_sensitive(imAction_, TRUE);
352
                        add_to_toolbar(toolbar_, imToolbar_, pos++);
353
                    }
354

355
                    break;
356
                }
357
358
            case CALL_STATE_BUSY:
            case CALL_STATE_FAILURE:
359
                {
360
                    pos = 1;
361
362
                    DEBUG("UIManager: Call State Busy/Failure");
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
363
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
364
365
                    break;
                }
366
            case CALL_STATE_TRANSFER:
367
                {
368
                    pos = 1;
369
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
370
                    add_to_toolbar(toolbar_, transferToolbar_, pos++);
371
372
373
374
375
376
377
378
379
                    g_signal_handler_block(transferToolbar_, transferButtonConnId_);
                    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE);
                    g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
                    gtk_widget_set_sensitive(holdMenu_, TRUE);
                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
                    gtk_widget_set_sensitive(transferToolbar_, TRUE);
                    break;
                }
380
            default:
381
                ERROR("UIMAnager: Error: Unknown state in action update!");
382
383
                break;
        }
384
        
385
386
    } else if (selectedConf) {

387
388
        DEBUG("UIManager: Update actions for conference");

389
390
391
392
393
        // update icon in systray
        show_status_hangup_icon();

        switch (selectedConf->_state) {

394
            case CONFERENCE_STATE_ACTIVE_ATTACHED:
395
            case CONFERENCE_STATE_ACTIVE_DETACHED:
396
                DEBUG("UIManager: Conference State Active");
397

Tristan Matthews's avatar
Tristan Matthews committed
398
                if (active_calltree_tab == current_calls_tab) {
399
400
401
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
                    gtk_action_set_sensitive(recordAction_, TRUE);
402
                    pos = 1;
403
404
405
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                    add_to_toolbar(toolbar_, holdToolbar_, pos++);
                    add_to_toolbar(toolbar_, recordWidget_, pos++);
406

407
                    if (instant_messaging_enabled) {
408
                        gtk_action_set_sensitive(imAction_, TRUE);
409
                        add_to_toolbar(toolbar_, imToolbar_, pos);
410
                    }
Tristan Matthews's avatar
Tristan Matthews committed
411
                } else if (active_calltree_tab == history_tab) {
412
                    if (is_non_empty(selectedConf->_recordfile)) {
413
                        pos = 2;
414
                        if (selectedConf->_record_is_playing)
415
                            add_to_toolbar(toolbar_, stopRecordWidget_, pos);
416
                        else
417
                            add_to_toolbar(toolbar_, playRecordWidget_, pos);
418
                    }
419
                }
420

421
                break;
422
            case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
423
            case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: {
424
                pos = 1;
425
426
427
428
                DEBUG("UIManager: Conference State Record");
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_widget_set_sensitive(holdToolbar_, TRUE);
                gtk_action_set_sensitive(recordAction_, TRUE);
429
430
431
                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                add_to_toolbar(toolbar_, holdToolbar_, pos++);
                add_to_toolbar(toolbar_, recordWidget_, pos++);
432

433
                if (instant_messaging_enabled) {
434
                    gtk_action_set_sensitive(imAction_, TRUE);
435
                    add_to_toolbar(toolbar_, imToolbar_, pos);
436
                }
437

438
                break;
439
            }
440
            case CONFERENCE_STATE_HOLD:
441
442
            case CONFERENCE_STATE_HOLD_RECORD: {
                DEBUG("UIManager: Conference State Hold");
443
                pos = 1;
444
445
446
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
                gtk_action_set_sensitive(recordAction_, TRUE);
447
448
449
                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                add_to_toolbar(toolbar_, offHoldToolbar_, pos++);
                add_to_toolbar(toolbar_, recordWidget_, pos++);
450

451
                if (instant_messaging_enabled) {
452
                    gtk_action_set_sensitive(imAction_, TRUE);
453
                    add_to_toolbar(toolbar_, imToolbar_, pos);
454
                }
455

456
                break;
457
            }
458
            default:
459
                WARN("UIManager: Error: Should not happen in action update!");
460
461
                break;
        }
462
    } else {
463
464
465
466
        // update icon in systray
        hide_status_hangup_icon();

        if (account_list_get_size() > 0 && current_account_has_mailbox()) {
467
            add_to_toolbar(toolbar_, voicemailToolbar_, -1);
468
469
470
            update_voicemail_status();
        }
    }
471
472
}

473
void
474
update_voicemail_status()
475
{
476
    gchar *messages = g_markup_printf_escaped(_("Voicemail(%i)"),
477
                      current_account_get_message_number());
478
479
480

    if (current_account_has_new_message())
        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(voicemailToolbar_),
481
                                      "mail-message-new");
482
483
484
    else
        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(voicemailToolbar_),
                                      "mail-read");
485

486
487
    gtk_tool_button_set_label(GTK_TOOL_BUTTON(voicemailToolbar_), messages);
    g_free(messages);
488
489
}

490
static void
491
volume_bar_cb(GtkToggleAction *togglemenuitem, gpointer user_data UNUSED)
492
{
493
    gboolean toggled = gtk_toggle_action_get_active(togglemenuitem);
494
495
496
497

    if (toggled == SHOW_VOLUME)
        return;

498
    main_window_volume_controls(toggled);
499
500

    if (toggled || SHOW_VOLUME)
501
        eel_gconf_set_integer(SHOW_VOLUME_CONTROLS, toggled);
502
503
}

504
static void
505
dialpad_bar_cb(GtkToggleAction *togglemenuitem, gpointer user_data UNUSED)
506
{
507
508
    gboolean toggled = gtk_toggle_action_get_active(togglemenuitem);
    gboolean conf_dialpad = eel_gconf_get_boolean(CONF_SHOW_DIALPAD);
509
510
511
512

    if (toggled == conf_dialpad)
        return;

513
    main_window_dialpad(toggled);
514
515

    if (toggled || conf_dialpad)
516
        eel_gconf_set_boolean(CONF_SHOW_DIALPAD, toggled);
517
518
}

519
static void
520
help_contents_cb(GtkAction *action UNUSED)
521
{
522
    GError *error = NULL;
Tristan Matthews's avatar
Tristan Matthews committed
523
    gtk_show_uri(NULL, "ghelp:sflphone", GDK_CURRENT_TIME, &error);
524
    if (error != NULL) {
525
526
        g_warning("%s", error->message);
        g_error_free(error);
527
    }
528
529
}

530
static void
531
help_about(void * foo UNUSED)
532
{
Tristan Matthews's avatar
Tristan Matthews committed
533
    static const gchar *authors[] = {
534
535
536
537
538
539
540
541
542
543
544
545
546
        "Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>",
        "Jean-Philippe Barrette-LaPierre",
        "Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>",
        "Julien Bonjean <julien.bonjean@savoirfairelinux.com>",
        "Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>",
        "Laurielle Lea",
        "Yun Liu <yun.liu@savoirfairelinux.com>",
        "Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>",
        "Yan Morin <yan.morin@savoirfairelinux.com>",
        "Jérôme Oufella <jerome.oufella@savoirfairelinux.com>",
        "Julien Plissonneau Duquene <julien.plissonneau.duquene@savoirfairelinux.com>",
        "Alexandre Savard <alexandre.savard@savoirfairelinux.com>", NULL
    };
Tristan Matthews's avatar
Tristan Matthews committed
547
548
549
550
    static const gchar *artists[] = {
        "Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>",
        "Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>", NULL
    };
551

Tristan Matthews's avatar
Tristan Matthews committed
552
553
554
555
556
557
558
559
560
561
    gtk_show_about_dialog(GTK_WINDOW(get_main_window()),
            "artists", artists,
            "authors", authors,
            "comments", _("SFLphone is a VoIP client compatible with SIP and IAX2 protocols."),
            "copyright", "Copyright © 2004-2011 Savoir-faire Linux Inc.",
            "name", PACKAGE,
            "title", _("About SFLphone"),
            "version", VERSION,
            "website", "http://www.sflphone.org",
            NULL);
562
563
564
565
}

/* ----------------------------------------------------------------- */

566
static void
567
call_new_call(void * foo UNUSED)
568
{
569
    DEBUG("UIManager: New call button pressed");
570
    sflphone_new_call();
571
572
}

573
static void
574
call_quit(void * foo UNUSED)
575
{
576
    sflphone_quit();
577
578
}

579
static void
580
call_minimize(void * foo UNUSED)
581
{
582
583
584
585
586
    if (eel_gconf_get_integer(SHOW_STATUSICON)) {
        gtk_widget_hide(get_main_window());
        set_minimized(TRUE);
    } else
        sflphone_quit();
587
588
}

589
static void
590
switch_account(GtkWidget* item, gpointer data UNUSED)
591
{
592
593
594
    account_t* acc = g_object_get_data(G_OBJECT(item), "account");
    DEBUG("%s" , acc->accountID);
    account_list_set_current(acc);
595
    status_bar_display_account();
596
597
}

598
static void
599
call_hold(void* foo UNUSED)
600
{
Tristan Matthews's avatar
Tristan Matthews committed
601
602
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
603

604
    DEBUG("UIManager: Hold button pressed");
605

606
    if (selectedCall) {
607
        if (selectedCall->_state == CALL_STATE_HOLD)
608
            sflphone_off_hold();
609
        else
610
611
612
            sflphone_on_hold();
    } else if (selectedConf) {
        switch (selectedConf->_state) {
613
            case CONFERENCE_STATE_HOLD:
614
                selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED;
615
                dbus_unhold_conference(selectedConf);
616
617
618
                break;
            case CONFERENCE_STATE_HOLD_RECORD:
                selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD;
619
                dbus_unhold_conference(selectedConf);
620
                break;
621

622
            case CONFERENCE_STATE_ACTIVE_ATTACHED:
623
            case CONFERENCE_STATE_ACTIVE_DETACHED:
624
                selectedConf->_state = CONFERENCE_STATE_HOLD;
625
                dbus_hold_conference(selectedConf);
626
627
628
                break;
            case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
            case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD:
629
630
631
                selectedConf->_state = CONFERENCE_STATE_HOLD_RECORD;
                dbus_hold_conference(selectedConf);
                break;
632
633
634
635
            default:
                break;
        }
    }
636
637
}

638
static void
639
call_im(void* foo UNUSED)
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
640
{
Tristan Matthews's avatar
Tristan Matthews committed
641
642
    callable_obj_t *selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t *selectedConf = calltab_get_selected_conf(current_calls_tab);
643

Tristan Matthews's avatar
Tristan Matthews committed
644
    if (calltab_get_selected_type(current_calls_tab) == A_CALL) {
645
646
647
648
        if (selectedCall) {
            if (!selectedCall->_im_widget)
                selectedCall->_im_widget = im_widget_display(selectedCall->_callID);
        } else
649
            WARN("Sorry. Instant messaging is not allowed outside a call\n");
650
    } else {
651
652
653
654
        if (selectedConf) {
            if (!selectedConf->_im_widget)
                selectedConf->_im_widget = im_widget_display(selectedConf->_confID);
        } else
655
            WARN("Sorry. Instant messaging is not allowed outside a call\n");
656
    }
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
657
658
}

659
static void
660
conference_hold(void* foo UNUSED)
661
{
Tristan Matthews's avatar
Tristan Matthews committed
662
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
663

664
    DEBUG("UIManager: Hold button pressed for conference");
665

666
    if (selectedConf == NULL) {
667
        ERROR("UIManager: No conference selected");
668
        return;
669
    }
670

671
    switch (selectedConf->_state) {
672
        case CONFERENCE_STATE_HOLD:
673
            selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED;
674
            dbus_unhold_conference(selectedConf);
675
676
677
            break;
        case CONFERENCE_STATE_HOLD_RECORD:
            selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD;
678
            dbus_unhold_conference(selectedConf);
679
            break;
680
        case CONFERENCE_STATE_ACTIVE_ATTACHED:
681
        case CONFERENCE_STATE_ACTIVE_DETACHED:
682
            selectedConf->_state = CONFERENCE_STATE_HOLD;
683
            dbus_hold_conference(selectedConf);
684
685
686
687
            break;
        case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
        case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD:
            selectedConf->_state = CONFERENCE_STATE_HOLD_RECORD;
688
            dbus_hold_conference(selectedConf);
689
690
691
        default:
            break;
    }
692
693
}

694
static void
695
call_pick_up(void * foo UNUSED)
696
{
697
    DEBUG("UIManager: Pick up");
698

Tristan Matthews's avatar
Tristan Matthews committed
699
    if (calllist_get_size(current_calls_tab) > 0) {
700
        sflphone_pick_up();
Tristan Matthews's avatar
Tristan Matthews committed
701
702
    } else if (calllist_get_size(active_calltree_tab) > 0) {
        callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab);
703

704
        if (selectedCall) {
705
            callable_obj_t *new_call = create_new_call(CALL, CALL_STATE_DIALING, "", "", "",
706
                                       selectedCall->_peer_number);
Tristan Matthews's avatar
Tristan Matthews committed
707
708
            calllist_add_call(current_calls_tab, new_call);
            calltree_add_call(current_calls_tab, new_call, NULL);
709
            sflphone_place_call(new_call);
Tristan Matthews's avatar
Tristan Matthews committed
710
            calltree_display(current_calls_tab);
711
712
        } else {
            sflphone_new_call();
Tristan Matthews's avatar
Tristan Matthews committed
713
            calltree_display(current_calls_tab);
714
715
716
        }
    } else {
        sflphone_new_call();
Tristan Matthews's avatar
Tristan Matthews committed
717
        calltree_display(current_calls_tab);
718
    }
719
720
}

721
static void
722
call_hang_up(void)
723
{
724
    DEBUG("UIManager: Hang up button pressed(call)");
725
726
727
728
    /*
     * [#3020]	Restore the record toggle button
     *			We set it to FALSE, as when we hang up a call, the recording is stopped.
     */
729

730
    sflphone_hang_up();
731
732
}

733
static void
734
conference_hang_up(void)
735
{
736
    DEBUG("UIManager: Hang up button pressed(conference)");
Tristan Matthews's avatar
Tristan Matthews committed
737
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
738

739
    if (selectedConf)
740
        dbus_hang_up_conference(selectedConf);
741
742
}

743
static void
744
call_record(void)
745
{
746
    DEBUG("UIManager: Record button pressed");
747
    sflphone_rec_call();
748
749
}

750
static void
751
start_playback_record_cb(void)
752
{
753
    DEBUG("UIManager: Start playback button pressed");
754

Tristan Matthews's avatar
Tristan Matthews committed
755
    callable_obj_t *selectedCall = calltab_get_selected_call(history_tab);
756

757
    if (selectedCall == NULL) {
758
        ERROR("UIManager: Error: No selected object in playback record callback");
759
        return;
760
761
    }

762
763
    DEBUG("UIManager: Start selected call file playback %s", selectedCall->_recordfile);
    selectedCall->_record_is_playing = dbus_start_recorded_file_playback(selectedCall->_recordfile);
764
765
766
767
768
769
770
771
772

    update_actions();
}

static void
stop_playback_record_cb(void)
{
    DEBUG("UIManager: Stop playback button pressed");

Tristan Matthews's avatar
Tristan Matthews committed
773
    callable_obj_t *selectedCall = calltab_get_selected_call(history_tab);
774

775
    if (selectedCall == NULL) {
776
        ERROR("UIManager: Error: No selected object in history treeview");
777
        return;
778
779
    }

780
781
    if (selectedCall) {
        if (selectedCall->_recordfile == NULL) {
Alexandre Savard's avatar
Alexandre Savard committed
782
            ERROR("UIManager: Error: Record file is NULL");
783
            return;
Alexandre Savard's avatar
Alexandre Savard committed
784
        }
785

786
787
788
        dbus_stop_recorded_file_playback(selectedCall->_recordfile);
        DEBUG("UIManager: Stop selected call file playback %s", selectedCall->_recordfile);
        selectedCall->_record_is_playing = FALSE;
789
790
791
    }

    update_actions();
792
793
}

794
static void
795
call_configuration_assistant(void * foo UNUSED)
796
{
797
    build_wizard();
798
799
}

800
static void
801
remove_from_history(void * foo UNUSED)
802
{
Tristan Matthews's avatar
Tristan Matthews committed
803
    callable_obj_t* call = calltab_get_selected_call(history_tab);
804

805
    DEBUG("UIManager: Remove the call from the history");
806

807
808
    if (call == NULL) {
        ERROR("UIManager: Error: Call is NULL");
809
        return;
810
    }
811

812
    calllist_remove_from_history(call);
813
814
}

815
static void
816
call_back(void * foo UNUSED)
817
{
Tristan Matthews's avatar
Tristan Matthews committed
818
    callable_obj_t *selected_call = calltab_get_selected_call(active_calltree_tab);
819

820
    DEBUG("UIManager: Call back");
821

822
823
824
    if (selected_call == NULL) {
        ERROR("UIManager: Error: No selected call");
        return;
825
    }
Alexandre Savard's avatar