actions.c 36 KB
Newer Older
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
1
/*
2
 *  Copyright (C) 2007 - 2008 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
19
 *  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.
 */
20

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
21
#include <actions.h>
22
#include <dbus/dbus.h>
23
#include <statusicon.h>
Julien Bonjean's avatar
Julien Bonjean committed
24
#include <contacts/searchbar.h>
25
#include "icons/icon_factory.h"
26

27
28
29
30
#include <gtk/gtk.h>
#include <string.h>
#include <glib/gprintf.h>
#include <stdlib.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
31
32
33
#include <sys/types.h>
#include <unistd.h>

34
GHashTable * ip2ip_profile=NULL;
35

Emmanuel Milou's avatar
Emmanuel Milou committed
36
    void
37
sflphone_notify_voice_mail (const gchar* accountID , guint count)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
38
{
39
    gchar *id;
40
41
    gchar *current_id;
	account_t *current;
Emmanuel Milou's avatar
Emmanuel Milou committed
42

43
44
45
46
47
    // We want to notify only the current account; ie the first in the list
    id = g_strdup (accountID);
    current_id = account_list_get_current_id ();

    if (g_strcasecmp (id, current_id) != 0 || account_list_get_size() == 0)
48
49
        return;

50
51
52
	// Set the number of voice messages for the current account
	current_account_set_message_number (count);
	current = account_list_get_current ();
53

54
55
	// Update the voicemail tool button
	update_voicemail_status ();
Emmanuel Milou's avatar
Emmanuel Milou committed
56

57
58
	if (current)
		notify_voice_mails (count, current);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
59
60
}

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
 * 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
 */
 
static gboolean _is_direct_call(callable_obj_t * c) {

    if(g_strcasecmp(c->_accountID, EMPTY_ENTRY) == 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);
            c->_peer_number = new_number;
        }
        return 1;
    }

    if(g_str_has_prefix (c->_peer_number, "sip:")) {
        return 1;
    }

    return 0;
}


Emmanuel Milou's avatar
Emmanuel Milou committed
87
    void
88
status_bar_display_account ()
89
{
90
    gchar* msg;
91
    account_t* acc;
92
93
94
95
96

    statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);

    acc = account_list_get_current ();
    if(acc){
97
	status_tray_icon_online(TRUE);
98
99
        msg = g_markup_printf_escaped("%s %s (%s)" ,
                _("Using account"),
100
101
                (gchar*)g_hash_table_lookup( acc->properties , ACCOUNT_ALIAS),
                (gchar*)g_hash_table_lookup( acc->properties , ACCOUNT_TYPE));
Emmanuel Milou's avatar
Emmanuel Milou committed
102
    }
103
104
    else
    {
105
	status_tray_icon_online(FALSE);
106
        msg = g_markup_printf_escaped(_("No registered accounts"));
107
108
109
    }
    statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT);
    g_free(msg);
110
111
}

Emmanuel Milou's avatar
Emmanuel Milou committed
112
113

    gboolean
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
114
115
sflphone_quit ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
116
    gboolean quit = FALSE;
Julien Bonjean's avatar
Julien Bonjean committed
117
    guint count = calllist_get_size(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
118
119
120
121
122
123
124
125
126
    if(count > 0){
        quit = main_window_ask_quit();
    }
    else{
        quit = TRUE;
    }

    if (quit)
    {
127
128
129
        // Save the history 
        sflphone_save_history ();

Emmanuel Milou's avatar
Emmanuel Milou committed
130
131
132
133
134
135
136
        dbus_unregister(getpid());
        dbus_clean ();
        //call_list_clean(); TODO
        //account_list_clean()
        gtk_main_quit ();
    }
    return quit;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
137
138
}

Emmanuel Milou's avatar
Emmanuel Milou committed
139
    void
140
sflphone_hold (callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
141
{
142
    c->_state = CALL_STATE_HOLD;
143
    calltree_update_call(current_calls, c, NULL);
144
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
145
146
}

Emmanuel Milou's avatar
Emmanuel Milou committed
147
    void
148
sflphone_ringing(callable_obj_t * c )
149
{
150
    c->_state = CALL_STATE_RINGING;
151
    calltree_update_call(current_calls, c, NULL);
152
    update_actions();
153
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
154

Emmanuel Milou's avatar
Emmanuel Milou committed
155
    void
156
sflphone_hung_up( callable_obj_t * c)
Emmanuel Milou's avatar
Emmanuel Milou committed
157
{
158
    calllist_remove( current_calls, c->_callID);
159
    calltree_remove_call(current_calls, c, NULL);
160
    c->_state = CALL_STATE_DIALING;
161
    call_remove_all_errors(c);
162
    update_actions();
163
#if GTK_CHECK_VERSION(2,10,0)
Emmanuel Milou's avatar
Emmanuel Milou committed
164
    status_tray_icon_blink( FALSE );
165
#endif
Emmanuel Milou's avatar
Emmanuel Milou committed
166
167
}

168
169
static hashtable_free(gpointer key, gpointer value, gpointer user_data)
{
170
    g_free(key);
171
172
173
    g_free(value);
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
174
/** Internal to actions: Fill account list */
Emmanuel Milou's avatar
Emmanuel Milou committed
175
    void
176
sflphone_fill_account_list(gboolean toolbarInitialized)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
177
{
178
179
180
181

    gchar** array;
    gchar** accountID;
    unsigned int i;
182
183
184
	int count;

	count = current_account_get_message_number ();
185

Emmanuel Milou's avatar
Emmanuel Milou committed
186
    account_list_clear ( );
187

Emmanuel Milou's avatar
Emmanuel Milou committed
188
    array = (gchar **)dbus_account_list();
189
190
    if(array)
    {
Emmanuel Milou's avatar
Emmanuel Milou committed
191
192
193
194
        for (accountID = array; *accountID; accountID++)
        {
            account_t * a = g_new0(account_t,1);
            a->accountID = g_strdup(*accountID);
195
            a->credential_information = NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
196
197
198
            account_list_add(a);
        }
        g_strfreev (array);
199
    }
200

Emmanuel Milou's avatar
Emmanuel Milou committed
201
202
203
204
    for( i = 0; i < account_list_get_size(); i++)
    {
        account_t  * a = account_list_get_nth (i);
        GHashTable * details = (GHashTable *) dbus_account_details(a->accountID);
205
206
        if( details == NULL )
            break;
Emmanuel Milou's avatar
Emmanuel Milou committed
207
        a->properties = details;
208
                        
209
210
211
        /* As this function might be called numberous time, we should free the 
         * previously allocated space to avoid memory leaks.
         */
212
213
214
215
216
217
218

        /* Fill the actual array of credentials */

        int number_of_credential = dbus_get_number_of_credential(a->accountID);
        if(number_of_credential) {
            a->credential_information = g_ptr_array_new();
        } else {
219
220
221
            a->credential_information = NULL;
        }
        
222
        int credential_index;
223
224
        for(credential_index = 0; credential_index < number_of_credential; credential_index++) {
            GHashTable * credential_information = dbus_get_credential(a->accountID, credential_index);
225
            g_ptr_array_add(a->credential_information, credential_information);
226
        }
Emmanuel Milou's avatar
Emmanuel Milou committed
227

228
        gchar * status = g_hash_table_lookup(details, REGISTRATION_STATUS);
Emmanuel Milou's avatar
Emmanuel Milou committed
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
        if(strcmp(status, "REGISTERED") == 0)
        {
            a->state = ACCOUNT_STATE_REGISTERED;
        }
        else if(strcmp(status, "UNREGISTERED") == 0)
        {
            a->state = ACCOUNT_STATE_UNREGISTERED;
        }
        else if(strcmp(status, "TRYING") == 0)
        {
            a->state = ACCOUNT_STATE_TRYING;
        }
        else if(strcmp(status, "ERROR") == 0)
        {
            a->state = ACCOUNT_STATE_ERROR;
        }
        else if(strcmp( status , "ERROR_AUTH") == 0 )
        {
            a->state = ACCOUNT_STATE_ERROR_AUTH;
        }
        else if(strcmp( status , "ERROR_NETWORK") == 0 )
        {
            a->state = ACCOUNT_STATE_ERROR_NETWORK;
        }
        else if(strcmp( status , "ERROR_HOST") == 0 )
        {
            a->state = ACCOUNT_STATE_ERROR_HOST;
        }
        else if(strcmp( status , "ERROR_CONF_STUN") == 0 )
        {
            a->state = ACCOUNT_STATE_ERROR_CONF_STUN;
        }
        else if(strcmp( status , "ERROR_EXIST_STUN") == 0 )
        {
            a->state = ACCOUNT_STATE_ERROR_EXIST_STUN;
        }
        else
        {
            a->state = ACCOUNT_STATE_INVALID;
        }

270
271
272
273
274
275
276
        gchar * code = NULL;
        code = g_hash_table_lookup(details, REGISTRATION_STATE_CODE);
        if (code != NULL) {
            a->protocol_state_code = atoi(code);
        }
        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);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
281
282
}

283
gboolean sflphone_init()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
284
{
Emmanuel Milou's avatar
Emmanuel Milou committed
285
286
287
288
289
290
291
292
    if(!dbus_connect ()){

        main_window_error_message(_("Unable to connect to the SFLphone server.\nMake sure the daemon is running."));
        return FALSE;
    }
    else
    {
        dbus_register(getpid(), "Gtk+ Client");
293

294
295
296
		// Init icons factory
		init_icon_factory ();

297
298
299
        current_calls = calltab_init(FALSE, CURRENT_CALLS);
        contacts = calltab_init(TRUE, CONTACTS);
        history = calltab_init(TRUE, HISTORY);
300

Emmanuel Milou's avatar
Emmanuel Milou committed
301
        account_list_init ();
302
        codec_list_init();
303
		conferencelist_init();
304

305
        // Fetch the configured accounts
Emmanuel Milou's avatar
Emmanuel Milou committed
306
        sflphone_fill_account_list(FALSE);
307

308
309
310
        // Fetch the ip2ip profile 
        sflphone_fill_ip2ip_profile();
        
311
        // Fetch the audio codecs
Emmanuel Milou's avatar
Emmanuel Milou committed
312
        sflphone_fill_codec_list();
313

314
		// Fetch the conference list
315
		// sflphone_fill_conference_list();
316

Emmanuel Milou's avatar
Emmanuel Milou committed
317
318
        return TRUE;
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
319
320
}

321
322
323
324
325
void sflphone_fill_ip2ip_profile(void)
{
    ip2ip_profile = (GHashTable *) dbus_get_ip2_ip_details();
}

Emmanuel Milou's avatar
Emmanuel Milou committed
326
void sflphone_get_ip2ip_properties (GHashTable **properties)
327
{
Emmanuel Milou's avatar
Emmanuel Milou committed
328
	*properties	= ip2ip_profile;
329
330
}

Emmanuel Milou's avatar
Emmanuel Milou committed
331
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
332
sflphone_hang_up()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
333
{
334
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
335
336
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

Emmanuel Milou's avatar
Emmanuel Milou committed
337
338
    if(selectedCall)
    {
339
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
340
341
342
343
344
345
        {
            case CALL_STATE_DIALING:
                dbus_hang_up (selectedCall);
                break;
            case CALL_STATE_RINGING:
                dbus_hang_up (selectedCall);
346
                call_remove_all_errors(selectedCall);
347
348
                selectedCall->_state = CALL_STATE_DIALING;
                //selectedCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
349
350
351
352
                break;
            case CALL_STATE_CURRENT:
            case CALL_STATE_HOLD:
            case CALL_STATE_BUSY:
353
            case CALL_STATE_RECORD:
Emmanuel Milou's avatar
Emmanuel Milou committed
354
                dbus_hang_up (selectedCall);
355
                call_remove_all_errors(selectedCall);
356
                selectedCall->_state = CALL_STATE_DIALING;
357
                set_timestamp (&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
358
359
360
                break;
            case CALL_STATE_FAILURE:
                dbus_hang_up (selectedCall);
361
                call_remove_all_errors(selectedCall);
362
                selectedCall->_state = CALL_STATE_DIALING;
Emmanuel Milou's avatar
Emmanuel Milou committed
363
364
365
                break;
            case CALL_STATE_INCOMING:
                dbus_refuse (selectedCall);
366
                call_remove_all_errors(selectedCall);
367
                selectedCall->_state = CALL_STATE_DIALING;
368
                DEBUG("from sflphone_hang_up : "); stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
369
370
371
                break;
            case CALL_STATE_TRANSFERT:
                dbus_hang_up (selectedCall);
372
                call_remove_all_errors(selectedCall);
373
                set_timestamp (&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
379
                break;
        }
    }
380
381
382
383
    else if(selectedConf) {
        dbus_hang_up_conference(selectedConf);
    }

384
    calltree_update_call(history, selectedCall, NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
385
386
387
}


Alexandre Savard's avatar
Alexandre Savard committed
388
389
390
391
392
393
394
395
396
397
void
sflphone_conference_hang_up()
{
    conference_obj_t * selectedConf = calltab_get_selected_conf();

    if(selectedConf)
	dbus_hang_up_conference(selectedConf);
}


Emmanuel Milou's avatar
Emmanuel Milou committed
398
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
399
400
sflphone_pick_up()
{
Alexandre Savard's avatar
Alexandre Savard committed
401
    DEBUG("sflphone_pick_up\n");
402
403
404
    callable_obj_t * selectedCall = NULL;
    selectedCall = calltab_get_selected_call(active_calltree);
    
Emmanuel Milou's avatar
Emmanuel Milou committed
405
406
    if(selectedCall)
    {
407
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
408
409
410
411
412
        {
            case CALL_STATE_DIALING:
                sflphone_place_call (selectedCall);
                break;
            case CALL_STATE_INCOMING:
413
                selectedCall->_history_state = INCOMING;
414
                calltree_update_call( history, selectedCall, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
415
                dbus_accept (selectedCall);
416
                DEBUG("from sflphone_pick_up : "); stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
417
418
419
420
421
422
                break;
            case CALL_STATE_HOLD:
                sflphone_new_call();
                break;
            case CALL_STATE_TRANSFERT:
                dbus_transfert (selectedCall);
423
                set_timestamp (&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
424
425
426
427
428
429
430
431
432
                break;
            case CALL_STATE_CURRENT:
            case CALL_STATE_RECORD:
                sflphone_new_call();
                break;
            case CALL_STATE_RINGING:
                sflphone_new_call();
                break;
            default:
433
                WARN("Should not happen in sflphone_pick_up()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
434
435
436
                break;
        }
    }
437
438
439
    else {
        sflphone_new_call();
    }
440

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
441
442
}

Emmanuel Milou's avatar
Emmanuel Milou committed
443
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
444
445
sflphone_on_hold ()
{
446
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
447
448
449
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

    DEBUG("sflphone_on_hold");
Emmanuel Milou's avatar
Emmanuel Milou committed
450
451
    if(selectedCall)
    {
452
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
453
454
455
456
457
458
459
460
461
        {
            case CALL_STATE_CURRENT:
                dbus_hold (selectedCall);
                break;
            case CALL_STATE_RECORD:
                dbus_hold (selectedCall);
                break;

            default:
462
                WARN("Should not happen in sflphone_on_hold!");
Emmanuel Milou's avatar
Emmanuel Milou committed
463
464
465
                break;
        }
    }
466
467
468
    else if (selectedConf) {
        dbus_hold_conference(selectedConf);
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
469
470
}

Emmanuel Milou's avatar
Emmanuel Milou committed
471
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
472
473
sflphone_off_hold ()
{
474
    DEBUG("sflphone_off_hold");
475
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
476
477
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

Emmanuel Milou's avatar
Emmanuel Milou committed
478
479
    if(selectedCall)
    {
480
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
481
482
483
484
485
        {
            case CALL_STATE_HOLD:
                dbus_unhold (selectedCall);
                break;
            default:
486
                WARN("Should not happen in sflphone_off_hold ()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
487
488
489
                break;
        }
    }
490
    else if (selectedConf) {
Julien Bonjean's avatar
Julien Bonjean committed
491

492
493
494
495
        
        dbus_unhold_conference(selectedConf);
    }
    /*
496
    if(dbus_get_is_recording(selectedCall))
497
    {
498
        DEBUG("Currently recording!");
499
    }
500
    else
501
    {
502
        DEBUG("Not recording currently");
503
    }
504
    */
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
505
506
507
}


Emmanuel Milou's avatar
Emmanuel Milou committed
508
    void
509
sflphone_fail( callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
510
{
511
    c->_state = CALL_STATE_FAILURE;
512
    calltree_update_call(current_calls, c, NULL);
513
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
514
515
}

Emmanuel Milou's avatar
Emmanuel Milou committed
516
    void
517
sflphone_busy( callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
518
{
519
    c->_state = CALL_STATE_BUSY;
520
    calltree_update_call(current_calls, c, NULL);
521
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
522
523
}

Emmanuel Milou's avatar
Emmanuel Milou committed
524
    void
525
sflphone_current( callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
526
{
527

528
529
    if( c->_state != CALL_STATE_HOLD )
        set_timestamp (&c->_time_start);
530
    c->_state = CALL_STATE_CURRENT;
531
    calltree_update_call(current_calls, c, NULL);
532
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
533
534
}

Emmanuel Milou's avatar
Emmanuel Milou committed
535
    void
536
sflphone_record( callable_obj_t * c )
alexandresavard's avatar
alexandresavard committed
537
{
538
539
    if( c->_state != CALL_STATE_HOLD )
        set_timestamp (&c->_time_start);
540
    c->_state = CALL_STATE_RECORD;
541
    calltree_update_call(current_calls, c, NULL);
542
    update_actions();
alexandresavard's avatar
alexandresavard committed
543
544
}

Emmanuel Milou's avatar
Emmanuel Milou committed
545
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
546
sflphone_set_transfert()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
547
{
548
    callable_obj_t * c = calltab_get_selected_call(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
549
550
    if(c)
    {
551
        c->_state = CALL_STATE_TRANSFERT;
552
        c->_trsft_to = g_strdup("");
553
        calltree_update_call(current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
554
    }
555
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
556
557
}

Emmanuel Milou's avatar
Emmanuel Milou committed
558
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
559
560
sflphone_unset_transfert()
{
561
    callable_obj_t * c = calltab_get_selected_call(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
562
563
    if(c)
    {
564
        c->_state = CALL_STATE_CURRENT;
565
        c->_trsft_to = g_strdup("");
566
        calltree_update_call(current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
567
    }
568
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
569
}
Emmanuel Milou's avatar
Emmanuel Milou committed
570

571
    void
572
573
574
575
576
sflphone_display_transfer_status(const gchar* message)
{
    statusbar_push_message( message , __MSG_ACCOUNT_DEFAULT);
}

Emmanuel Milou's avatar
Emmanuel Milou committed
577
    void
578
sflphone_incoming_call (callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
579
{
580
581
	gchar *msg = "";

582
    c->_history_state = MISSED;
Julien Bonjean's avatar
Julien Bonjean committed
583
584
    calllist_add ( current_calls, c );
    calllist_add( history, c );
585
    calltree_add_call( current_calls, c, NULL);
586
    update_actions();
Julien Bonjean's avatar
Julien Bonjean committed
587
    calltree_display (current_calls);
588
589
590
591
592
593
594
595
	
	// Change the status bar if we are dealing with a direct SIP call
    if(_is_direct_call(c)) {
		msg = g_markup_printf_escaped (_("Direct SIP call"));
        statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
        statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT);
        g_free(msg);
	}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
596
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
597

Emmanuel Milou's avatar
Emmanuel Milou committed
598
    void
599
process_dialing(callable_obj_t * c, guint keyval, gchar * key)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
600
{
Emmanuel Milou's avatar
Emmanuel Milou committed
601
    // We stop the tone
602
    if(strlen(c->_peer_number) == 0 && c->_state != CALL_STATE_TRANSFERT){
Emmanuel Milou's avatar
Emmanuel Milou committed
603
604
605
        dbus_start_tone( FALSE , 0 );
        //dbus_play_dtmf( key );
    }
606

607
608
    DEBUG("process_dialing : keyval : %i",keyval);
    DEBUG("process_dialing : key : %s",key);
Emmanuel Milou's avatar
Emmanuel Milou committed
609
610
611
612
613
614
615
616
617
618
619
620

    switch (keyval)
    {
        case 65293: /* ENTER */
        case 65421: /* ENTER numpad */
            sflphone_place_call(c);
            break;
        case 65307: /* ESCAPE */
            sflphone_hang_up(c);
            break;
        case 65288: /* BACKSPACE */
            {  /* Brackets mandatory because of local vars */
621
622
                gchar * before = c->_peer_number;
                if(strlen(c->_peer_number) >= 1){
Emmanuel Milou's avatar
Emmanuel Milou committed
623

624
625
626
627
628
629
630
631
632
					if (c->_state == CALL_STATE_TRANSFERT)
					{
						c->_trsft_to = g_strndup (c->_trsft_to, strlen(c->_trsft_to) - 1);
					}
					else
					{
						c->_peer_number = g_strndup(c->_peer_number, strlen(c->_peer_number) -1);
						g_free(before);
						DEBUG("TO: backspace %s", c->_peer_number);
Emmanuel Milou's avatar
Emmanuel Milou committed
633
                    }
634
					calltree_update_call(current_calls, c, NULL);
Julien Bonjean's avatar
Julien Bonjean committed
635
                }
636
                else if(strlen(c->_peer_number) == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
637
                {
638
                    if(c->_state != CALL_STATE_TRANSFERT)
Emmanuel Milou's avatar
Emmanuel Milou committed
639
640
641
642
643
644
645
646
647
648
649
650
651
                        dbus_hang_up(c);
                }
            }
            break;
        case 65289: /* TAB */
        case 65513: /* ALT */
        case 65507: /* CTRL */
        case 65515: /* SUPER */
        case 65509: /* CAPS */
            break;
        default:
            // if (keyval < 255 || (keyval >65453 && keyval < 65466))
            if (keyval < 127 || (keyval > 65400 && keyval < 65466))
Julien Bonjean's avatar
Julien Bonjean committed
652
            {
Emmanuel Milou's avatar
Emmanuel Milou committed
653

654
655
656
657
658
659
                if (c->_state == CALL_STATE_TRANSFERT)
                {
                    c->_trsft_to = g_strconcat(c->_trsft_to, key, NULL);
                }
                else
                {
Emmanuel Milou's avatar
Emmanuel Milou committed
660
                    dbus_play_dtmf( key );
661
662
                    c->_peer_number = g_strconcat(c->_peer_number, key, NULL);
                }
Emmanuel Milou's avatar
Emmanuel Milou committed
663

664
                if(c->_state == CALL_STATE_DIALING)
Emmanuel Milou's avatar
Emmanuel Milou committed
665
                {
666
667
                    //g_free(c->_peer_name);
                    //c->_peer_name = g_strconcat("\"\" <", c->_peer_number, ">", NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
668
                }
669
                calltree_update_call(current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
670
671
672
            }
            break;
    }
673
674
}

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

676
    callable_obj_t *
areversat's avatar
areversat committed
677
sflphone_new_call()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
678
{
Julien Bonjean's avatar
Julien Bonjean committed
679

680
    callable_obj_t *c;
681
    callable_obj_t * current_selected_call;
682
    gchar *peer_name, *peer_number;
683

684
    DEBUG("sflphone_new_call");
685
686
687

    current_selected_call = calltab_get_selected_call(current_calls);

688
    if ((current_selected_call != NULL) && (current_selected_call->_confID == NULL))
689
	sflphone_on_hold();
690

Emmanuel Milou's avatar
Emmanuel Milou committed
691
    // Play a tone when creating a new call
Julien Bonjean's avatar
Julien Bonjean committed
692
    if( calllist_get_size(current_calls) == 0 )
693
        dbus_start_tone( TRUE , (current_account_has_new_message ()  > 0)? TONE_WITH_MESSAGE : TONE_WITHOUT_MESSAGE) ;
Emmanuel Milou's avatar
Emmanuel Milou committed
694

695
696
697
    peer_number = g_strdup("");
    peer_name = g_strdup ("");
    create_new_call (CALL, CALL_STATE_DIALING, "", "", peer_name, peer_number, &c);
Emmanuel Milou's avatar
Emmanuel Milou committed
698

699
    calllist_add (current_calls,c);
700
    calltree_add_call (current_calls, c, NULL);
701
    update_actions();
702

Emmanuel Milou's avatar
Emmanuel Milou committed
703
    return c;
704
705
}

areversat's avatar
areversat committed
706

Emmanuel Milou's avatar
Emmanuel Milou committed
707
    void
areversat's avatar
areversat committed
708
709
sflphone_keypad( guint keyval, gchar * key)
{
710
    callable_obj_t * c = calltab_get_selected_call(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
711
712
713

    if((active_calltree != current_calls) || (active_calltree == current_calls && !c))
    {
714
        DEBUG("Not in a call, not dialing, create a new call");
Emmanuel Milou's avatar
Emmanuel Milou committed
715
716
717
718
719
720
721
722
        //dbus_play_dtmf(key);
        switch (keyval)
        {
            case 65293: /* ENTER */
            case 65421: /* ENTER numpad */
            case 65307: /* ESCAPE */
                break;
            default:
Julien Bonjean's avatar
Julien Bonjean committed
723
                calltree_display (current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
724
725
726
727
728
729
                process_dialing(sflphone_new_call(), keyval, key);
                break;
        }
    }
    else if(c)
    {
730
        DEBUG("Call is non-zero");
731
        switch(c->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
732
733
        {
            case CALL_STATE_DIALING: // Currently dialing => edit number
734
                DEBUG("Writing a number");
Emmanuel Milou's avatar
Emmanuel Milou committed
735
736
737
738
739
740
741
742
                process_dialing(c, keyval, key);
                break;
            case CALL_STATE_RECORD:
            case CALL_STATE_CURRENT:
                switch (keyval)
                {
                    case 65307: /* ESCAPE */
                        dbus_hang_up(c);
743
                        set_timestamp (&c->_time_stop);
744
                        calltree_update_call(history, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
745
746
747
748
749
750
751
752
753
754
755
                        break;
                    default:
                        // To play the dtmf when calling mail box for instance
                        dbus_play_dtmf(key);
                        if (keyval < 255 || (keyval >65453 && keyval < 65466))
                        {
                            //gchar * temp = g_strconcat(call_get_number(c), key, NULL);
                            //gchar * before = c->from;
                            //c->from = g_strconcat("\"",call_get_name(c) ,"\" <", temp, ">", NULL);
                            //g_free(before);
                            //g_free(temp);
756
                            //update_callable_obj_tree(current_calls,c);
Emmanuel Milou's avatar
Emmanuel Milou committed
757
758
759
760
761
762
763
764
765
                        }
                        break;
                }
                break;
            case CALL_STATE_INCOMING:
                switch (keyval)
                {
                    case 65293: /* ENTER */
                    case 65421: /* ENTER numpad */
766
                        c->_history_state = INCOMING;
767
                        calltree_update_call(history, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
768
                        dbus_accept(c);
769
                        DEBUG("from sflphone_keypad ( enter ) : "); stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
770
771
772
                        break;
                    case 65307: /* ESCAPE */
                        dbus_refuse(c);
773
                        DEBUG("from sflphone_keypad ( escape ) : "); stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
774
775
776
777
778
779
780
781
782
                        break;
                }
                break;
            case CALL_STATE_TRANSFERT:
                switch (keyval)
                {
                    case 65293: /* ENTER */
                    case 65421: /* ENTER numpad */
                        dbus_transfert(c);
783
                        set_timestamp (&c->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
784
785
786
787
                        break;
                    case 65307: /* ESCAPE */
                        sflphone_unset_transfert(c);
                        break;
788
                    default: // When a call is on transfert, typing new numbers will add it to c->_peer_number
Emmanuel Milou's avatar
Emmanuel Milou committed
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
                        process_dialing(c, keyval, key);
                        break;
                }
                break;
            case CALL_STATE_HOLD:
                switch (keyval)
                {
                    case 65293: /* ENTER */
                    case 65421: /* ENTER numpad */
                        dbus_unhold(c);
                        break;
                    case 65307: /* ESCAPE */
                        dbus_hang_up(c);
                        break;
                    default: // When a call is on hold, typing new numbers will create a new call
                        process_dialing(sflphone_new_call(), keyval, key);
                        break;
                }
                break;
            case CALL_STATE_RINGING:
            case CALL_STATE_BUSY:
            case CALL_STATE_FAILURE:
811
                //c->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
812
813
814
815
                switch (keyval)
                {
                    case 65307: /* ESCAPE */
                        dbus_hang_up(c);
816
                        //c->_stop = 0;
817
                        calltree_update_call(history, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
818
819
820
821
822
823
                        break;
                }
                break;
            default:
                break;
        }
824

Alexandre Savard's avatar
Alexandre Savard committed
825
826
    }
    else {
827
        sflphone_new_call();
Emmanuel Milou's avatar
Emmanuel Milou committed
828
829
    }
}
830

831
832
833
834
835
836
837
838
static int _place_direct_call(const callable_obj_t * c) {
    if (c->_state == CALL_STATE_DIALING) {
        dbus_place_call (c);
    } else {
        return -1;
    }
    return 0;
}
Julien Bonjean's avatar
Julien Bonjean committed
839

840
static int _place_registered_call(callable_obj_t * c) {
841

842
843
    account_t * current = NULL;
  
844
845
846
847
848
    if(c == NULL) {
        DEBUG("callable_obj_t is NULL in _place_registered_call");
        return -1;
    }
    
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
    if (c->_state != CALL_STATE_DIALING) {
        return -1;
    }
  
    if(g_strcasecmp(c->_peer_number, "") == 0) {
        return -1;
    }
    
    if( account_list_get_size() == 0 ) {
        notify_no_accounts();
        sflphone_fail(c);
        return -1;
    } 
    
    if( account_list_get_by_state( ACCOUNT_STATE_REGISTERED ) == NULL ) {
        notify_no_registered_accounts();
        sflphone_fail(c);
        return -1;
    }
    
869
870
871
872
873
    if(g_strcasecmp(c->_accountID, "") != 0) {
        current = account_list_get_by_id(c->_accountID);
    } else {
        current = account_list_get_current();
    }
874

875
    if(current == NULL) { 
876
        DEBUG("Unexpected condition: account_t is NULL in %s at %d for accountID %s", __FILE__, __LINE__, c->_accountID);
877
878
        return -1;
    }   
879
                        
880
881
882
883
884
885
886
887
888
889
    if(g_strcasecmp(g_hash_table_lookup( current->properties, "Status"),"REGISTERED")==0) {
        /* The call is made with the current account */
        c->_accountID = current->accountID;
        dbus_place_call(c);
    } else {
       /* Place the call with the first registered account
        * and switch the current account.
        * If we are here, we can be sure that there is at least one. 
        */
        current = account_list_get_by_state( ACCOUNT_STATE_REGISTERED );
890
        c->_accountID = current->accountID;
891
892
893
894
895
896
897
898
        dbus_place_call(c);
        notify_current_account( current );
    }        

    c->_history_state = OUTGOING;
    calllist_add(history, c);                
    return 0;
}
899

900
901
902
    void
sflphone_place_call ( callable_obj_t * c )
{
903
904
	gchar *msg = "";

905
906
907
908
909
910
    DEBUG("Placing call with %s @ %s and accountid %s", c->_peer_name, c->_peer_number, c->_accountID);
    
    if(c == NULL) {
        DEBUG("Unexpected condition: callable_obj_t is null in %s at %d", __FILE__, __LINE__);
        return;
    }
911

912
    if(_is_direct_call(c)) {
913
914
915
916
		msg = g_markup_printf_escaped (_("Direct SIP call"));
        statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
        statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT);
        g_free(msg);
917
918
919
920
921
922
923
924
        if(_place_direct_call(c) < 0) {
            DEBUG("An error occured while placing direct call in %s at %d", __FILE__, __LINE__);
            return;
        }
    } else {
        if(_place_registered_call(c) < 0) {
            DEBUG("An error occured while placing registered call in %s at %d", __FILE__, __LINE__);
            return;
925
        }
Emmanuel Milou's avatar
Emmanuel Milou committed
926
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
927
928
}

Alexandre Savard's avatar
Alexandre Savard committed
929

930
    void
931
sflphone_detach_participant(const gchar* callID)
932
{
933
    DEBUG("sflphone detach participant from conference");
934

935
936
    

937
938
    if(callID == NULL) {
        callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
939
940
941
942
	DEBUG("    sflphone_detach_participant %s\n", selectedCall->_callID);

	calltree_remove_call(current_calls, selectedCall, NULL);
	calltree_add_call(current_calls, selectedCall, NULL);
943
944
945