actions.c 38.4 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
35
36
37
38
39
40
41
42
43
44
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>



45
GHashTable * ip2ip_profile=NULL;
46

Emmanuel Milou's avatar
Emmanuel Milou committed
47
    void
48
sflphone_notify_voice_mail (const gchar* accountID , guint count)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
49
{
50
    gchar *id;
51
52
    gchar *current_id;
	account_t *current;
Emmanuel Milou's avatar
Emmanuel Milou committed
53

54
55
56
57
58
    // 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)
59
60
        return;

61
62
63
	// Set the number of voice messages for the current account
	current_account_set_message_number (count);
	current = account_list_get_current ();
64

65
66
	// Update the voicemail tool button
	update_voicemail_status ();
Emmanuel Milou's avatar
Emmanuel Milou committed
67

68
69
	if (current)
		notify_voice_mails (count, current);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
70
71
}

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
 * 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;
    }

Alexandre Savard's avatar
Alexandre Savard committed
94
95
96
97
    if(g_str_has_prefix (c->_peer_number, "sips:")) {
        return 1;
    }

98
99
100
101
    return 0;
}


Emmanuel Milou's avatar
Emmanuel Milou committed
102
    void
103
status_bar_display_account ()
104
{
105
    gchar* msg;
106
    account_t* acc;
107
108
109
110
111

    statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);

    acc = account_list_get_current ();
    if(acc){
112
	status_tray_icon_online(TRUE);
113
114
        msg = g_markup_printf_escaped("%s %s (%s)" ,
                _("Using account"),
115
116
                (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
117
    }
118
119
    else
    {
120
	status_tray_icon_online(FALSE);
121
        msg = g_markup_printf_escaped(_("No registered accounts"));
122
123
124
    }
    statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT);
    g_free(msg);
125
126
}

Emmanuel Milou's avatar
Emmanuel Milou committed
127
128

    gboolean
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
129
130
sflphone_quit ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
131
    gboolean quit = FALSE;
Julien Bonjean's avatar
Julien Bonjean committed
132
    guint count = calllist_get_size(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
133
134
135
136
137
138
139
140
141
    if(count > 0){
        quit = main_window_ask_quit();
    }
    else{
        quit = TRUE;
    }

    if (quit)
    {
142
143
144
        // Save the history 
        sflphone_save_history ();

Emmanuel Milou's avatar
Emmanuel Milou committed
145
146
147
148
149
150
151
        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
152
153
}

Emmanuel Milou's avatar
Emmanuel Milou committed
154
    void
155
sflphone_hold (callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
156
{
157
    c->_state = CALL_STATE_HOLD;
158
    calltree_update_call(current_calls, c, NULL);
159
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
160
161
}

Emmanuel Milou's avatar
Emmanuel Milou committed
162
    void
163
sflphone_ringing(callable_obj_t * c )
164
{
165
    c->_state = CALL_STATE_RINGING;
166
    calltree_update_call(current_calls, c, NULL);
167
    update_actions();
168
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
169

Emmanuel Milou's avatar
Emmanuel Milou committed
170
    void
171
sflphone_hung_up( callable_obj_t * c)
Emmanuel Milou's avatar
Emmanuel Milou committed
172
{
173
    calllist_remove( current_calls, c->_callID);
174
    calltree_remove_call(current_calls, c, NULL);
175
    c->_state = CALL_STATE_DIALING;
176
    call_remove_all_errors(c);
177
    update_actions();
178
#if GTK_CHECK_VERSION(2,10,0)
Emmanuel Milou's avatar
Emmanuel Milou committed
179
    status_tray_icon_blink( FALSE );
180
#endif
Emmanuel Milou's avatar
Emmanuel Milou committed
181
182
}

183
184
static hashtable_free(gpointer key, gpointer value, gpointer user_data)
{
185
    g_free(key);
186
187
188
    g_free(value);
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
189
/** Internal to actions: Fill account list */
Emmanuel Milou's avatar
Emmanuel Milou committed
190
void sflphone_fill_account_list (void) {
191
192
193
194

    gchar** array;
    gchar** accountID;
    unsigned int i;
195
	int count;
196
	GQueue *codeclist;
197
198

	count = current_account_get_message_number ();
199

Emmanuel Milou's avatar
Emmanuel Milou committed
200
    account_list_clear ();
201

Emmanuel Milou's avatar
Emmanuel Milou committed
202
    array = (gchar **)dbus_account_list();
203
204
    if(array)
    {
Emmanuel Milou's avatar
Emmanuel Milou committed
205
206
207
208
        for (accountID = array; *accountID; accountID++)
        {
            account_t * a = g_new0(account_t,1);
            a->accountID = g_strdup(*accountID);
209
            a->credential_information = NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
210
			// TODO Clean codec list QUEUE
Emmanuel Milou's avatar
Emmanuel Milou committed
211
212
213
            account_list_add(a);
        }
        g_strfreev (array);
214
    }
215

Emmanuel Milou's avatar
Emmanuel Milou committed
216
217
218
219
    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);
220
221
        if( details == NULL )
            break;
Emmanuel Milou's avatar
Emmanuel Milou committed
222
        a->properties = details;
223
                        
224
225
226
        /* As this function might be called numberous time, we should free the 
         * previously allocated space to avoid memory leaks.
         */
227
228
229
230
231
232

        /* 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 {
233
234
235
            a->credential_information = NULL;
        }
        
236
        int credential_index;
237
        for(credential_index = 0; credential_index < number_of_credential; credential_index++) {
238
            GHashTable * credential_information = dbus_get_credential (a->accountID, credential_index);
239
            g_ptr_array_add(a->credential_information, credential_information);
240
        }
Emmanuel Milou's avatar
Emmanuel Milou committed
241

242
        gchar * status = g_hash_table_lookup(details, REGISTRATION_STATUS);
Emmanuel Milou's avatar
Emmanuel Milou committed
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
270
271
272
273
274
275
276
277
278
        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;
        }
279
280
281
		else if (strcmp (status, "READY") == 0) {
			a->state = IP2IP_PROFILE_STATUS;
		}
Emmanuel Milou's avatar
Emmanuel Milou committed
282
283
284
285
286
        else
        {
            a->state = ACCOUNT_STATE_INVALID;
        }

287
288
289
290
291
292
293
        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);
294
295

		// Attach a codec list to each account
296
		// account_create_codec_list (&a);
Emmanuel Milou's avatar
Emmanuel Milou committed
297
298
    }

299
	// Set the current account message number
300
	current_account_set_message_number (count);
301
302

	sflphone_fill_codec_list ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
303
304
}

Emmanuel Milou's avatar
Emmanuel Milou committed
305
306
gboolean sflphone_init() {

Emmanuel Milou's avatar
Emmanuel Milou committed
307
308
309
310
311
312
313
314
    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");
315

316
317
318
		// Init icons factory
		init_icon_factory ();

319
320
321
        current_calls = calltab_init(FALSE, CURRENT_CALLS);
        contacts = calltab_init(TRUE, CONTACTS);
        history = calltab_init(TRUE, HISTORY);
322

Emmanuel Milou's avatar
Emmanuel Milou committed
323
        account_list_init ();
324
        codec_capabilities_load ();
Emmanuel Milou's avatar
Emmanuel Milou committed
325
		conferencelist_init ();
326

327
        // Fetch the configured accounts
Emmanuel Milou's avatar
Emmanuel Milou committed
328
        sflphone_fill_account_list ();
329

330
331
332
        // Fetch the ip2ip profile 
        sflphone_fill_ip2ip_profile();
        
333
        // Fetch the audio codecs at startup.
334
        // sflphone_fill_codec_list();
335

336
		// Fetch the conference list
337
		// sflphone_fill_conference_list();
338

Emmanuel Milou's avatar
Emmanuel Milou committed
339
340
        return TRUE;
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
341
342
}

343
344
345
346
347
void sflphone_fill_ip2ip_profile(void)
{
    ip2ip_profile = (GHashTable *) dbus_get_ip2_ip_details();
}

Emmanuel Milou's avatar
Emmanuel Milou committed
348
void sflphone_get_ip2ip_properties (GHashTable **properties)
349
{
Emmanuel Milou's avatar
Emmanuel Milou committed
350
	*properties	= ip2ip_profile;
351
352
}

Emmanuel Milou's avatar
Emmanuel Milou committed
353
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
354
sflphone_hang_up()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
355
{
356
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
357
358
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

Emmanuel Milou's avatar
Emmanuel Milou committed
359
360
    if(selectedCall)
    {
361
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
362
363
364
365
366
367
        {
            case CALL_STATE_DIALING:
                dbus_hang_up (selectedCall);
                break;
            case CALL_STATE_RINGING:
                dbus_hang_up (selectedCall);
368
                call_remove_all_errors(selectedCall);
369
370
                selectedCall->_state = CALL_STATE_DIALING;
                //selectedCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
371
372
373
374
                break;
            case CALL_STATE_CURRENT:
            case CALL_STATE_HOLD:
            case CALL_STATE_BUSY:
375
            case CALL_STATE_RECORD:
Emmanuel Milou's avatar
Emmanuel Milou committed
376
                dbus_hang_up (selectedCall);
377
                call_remove_all_errors(selectedCall);
378
                selectedCall->_state = CALL_STATE_DIALING;
379
                set_timestamp (&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
380
381
382
                break;
            case CALL_STATE_FAILURE:
                dbus_hang_up (selectedCall);
383
                call_remove_all_errors(selectedCall);
384
                selectedCall->_state = CALL_STATE_DIALING;
Emmanuel Milou's avatar
Emmanuel Milou committed
385
386
387
                break;
            case CALL_STATE_INCOMING:
                dbus_refuse (selectedCall);
388
                call_remove_all_errors(selectedCall);
389
                selectedCall->_state = CALL_STATE_DIALING;
390
                DEBUG("from sflphone_hang_up : "); stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
391
392
393
                break;
            case CALL_STATE_TRANSFERT:
                dbus_hang_up (selectedCall);
394
                call_remove_all_errors(selectedCall);
395
                set_timestamp (&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
396
397
                break;
            default:
398
                WARN("Should not happen in sflphone_hang_up()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
399
400
401
                break;
        }
    }
402
403
404
405
    else if(selectedConf) {
        dbus_hang_up_conference(selectedConf);
    }

406
    calltree_update_call(history, selectedCall, NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
407
408
409
}


Alexandre Savard's avatar
Alexandre Savard committed
410
411
412
413
414
415
416
417
418
419
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
420
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
421
422
sflphone_pick_up()
{
Alexandre Savard's avatar
Alexandre Savard committed
423
    DEBUG("sflphone_pick_up\n");
424
425
426
    callable_obj_t * selectedCall = NULL;
    selectedCall = calltab_get_selected_call(active_calltree);
    
Emmanuel Milou's avatar
Emmanuel Milou committed
427
428
    if(selectedCall)
    {
429
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
430
431
432
433
434
        {
            case CALL_STATE_DIALING:
                sflphone_place_call (selectedCall);
                break;
            case CALL_STATE_INCOMING:
435
                selectedCall->_history_state = INCOMING;
436
                calltree_update_call( history, selectedCall, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
437
                dbus_accept (selectedCall);
438
                DEBUG("from sflphone_pick_up : "); stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
439
440
441
442
443
444
                break;
            case CALL_STATE_HOLD:
                sflphone_new_call();
                break;
            case CALL_STATE_TRANSFERT:
                dbus_transfert (selectedCall);
445
                set_timestamp (&selectedCall->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
446
447
448
449
450
451
452
453
454
                break;
            case CALL_STATE_CURRENT:
            case CALL_STATE_RECORD:
                sflphone_new_call();
                break;
            case CALL_STATE_RINGING:
                sflphone_new_call();
                break;
            default:
455
                WARN("Should not happen in sflphone_pick_up()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
456
457
458
                break;
        }
    }
459
460
461
    else {
        sflphone_new_call();
    }
462

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
463
464
}

Emmanuel Milou's avatar
Emmanuel Milou committed
465
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
466
467
sflphone_on_hold ()
{
468
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
469
470
471
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

    DEBUG("sflphone_on_hold");
Emmanuel Milou's avatar
Emmanuel Milou committed
472
473
    if(selectedCall)
    {
474
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
475
476
477
478
479
480
481
482
483
        {
            case CALL_STATE_CURRENT:
                dbus_hold (selectedCall);
                break;
            case CALL_STATE_RECORD:
                dbus_hold (selectedCall);
                break;

            default:
484
                WARN("Should not happen in sflphone_on_hold!");
Emmanuel Milou's avatar
Emmanuel Milou committed
485
486
487
                break;
        }
    }
488
489
490
    else if (selectedConf) {
        dbus_hold_conference(selectedConf);
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
491
492
}

Emmanuel Milou's avatar
Emmanuel Milou committed
493
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
494
495
sflphone_off_hold ()
{
496
    DEBUG("sflphone_off_hold");
497
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
498
499
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

Emmanuel Milou's avatar
Emmanuel Milou committed
500
501
    if(selectedCall)
    {
502
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
503
504
505
506
507
        {
            case CALL_STATE_HOLD:
                dbus_unhold (selectedCall);
                break;
            default:
508
                WARN("Should not happen in sflphone_off_hold ()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
509
510
511
                break;
        }
    }
512
    else if (selectedConf) {
Julien Bonjean's avatar
Julien Bonjean committed
513

514
515
516
517
        
        dbus_unhold_conference(selectedConf);
    }
    /*
518
    if(dbus_get_is_recording(selectedCall))
519
    {
520
        DEBUG("Currently recording!");
521
    }
522
    else
523
    {
524
        DEBUG("Not recording currently");
525
    }
526
    */
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
527
528
529
}


Emmanuel Milou's avatar
Emmanuel Milou committed
530
    void
531
sflphone_fail( callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
532
{
533
    c->_state = CALL_STATE_FAILURE;
534
    calltree_update_call(current_calls, c, NULL);
535
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
536
537
}

Emmanuel Milou's avatar
Emmanuel Milou committed
538
    void
539
sflphone_busy( callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
540
{
541
    c->_state = CALL_STATE_BUSY;
542
    calltree_update_call(current_calls, c, NULL);
543
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
544
545
}

Emmanuel Milou's avatar
Emmanuel Milou committed
546
    void
547
sflphone_current( callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
548
{
549

550
551
    if( c->_state != CALL_STATE_HOLD )
        set_timestamp (&c->_time_start);
552
    c->_state = CALL_STATE_CURRENT;
553
    calltree_update_call(current_calls, c, NULL);
554
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
555
556
}

Emmanuel Milou's avatar
Emmanuel Milou committed
557
    void
558
sflphone_record( callable_obj_t * c )
alexandresavard's avatar
alexandresavard committed
559
{
560
561
    if( c->_state != CALL_STATE_HOLD )
        set_timestamp (&c->_time_start);
562
    c->_state = CALL_STATE_RECORD;
563
    calltree_update_call(current_calls, c, NULL);
564
    update_actions();
alexandresavard's avatar
alexandresavard committed
565
566
}

Emmanuel Milou's avatar
Emmanuel Milou committed
567
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
568
sflphone_set_transfert()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
569
{
570
    callable_obj_t * c = calltab_get_selected_call(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
571
572
    if(c)
    {
573
        c->_state = CALL_STATE_TRANSFERT;
574
        c->_trsft_to = g_strdup("");
575
        calltree_update_call(current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
576
    }
577
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
578
579
}

Emmanuel Milou's avatar
Emmanuel Milou committed
580
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
581
582
sflphone_unset_transfert()
{
583
    callable_obj_t * c = calltab_get_selected_call(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
584
585
    if(c)
    {
586
        c->_state = CALL_STATE_CURRENT;
587
        c->_trsft_to = g_strdup("");
588
        calltree_update_call(current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
589
    }
590
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
591
}
Emmanuel Milou's avatar
Emmanuel Milou committed
592

593
    void
594
595
596
597
598
sflphone_display_transfer_status(const gchar* message)
{
    statusbar_push_message( message , __MSG_ACCOUNT_DEFAULT);
}

Emmanuel Milou's avatar
Emmanuel Milou committed
599
    void
600
sflphone_incoming_call (callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
601
{
602
603
	gchar *msg = "";

604
    c->_history_state = MISSED;
Julien Bonjean's avatar
Julien Bonjean committed
605
606
    calllist_add ( current_calls, c );
    calllist_add( history, c );
607
    calltree_add_call( current_calls, c, NULL);
608
    update_actions();
Julien Bonjean's avatar
Julien Bonjean committed
609
    calltree_display (current_calls);
610
611
612
613
614
615
616
617
	
	// 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
618
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
619

Emmanuel Milou's avatar
Emmanuel Milou committed
620
    void
621
process_dialing(callable_obj_t * c, guint keyval, gchar * key)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
622
{
Emmanuel Milou's avatar
Emmanuel Milou committed
623
    // We stop the tone
624
    if(strlen(c->_peer_number) == 0 && c->_state != CALL_STATE_TRANSFERT){
Emmanuel Milou's avatar
Emmanuel Milou committed
625
626
627
        dbus_start_tone( FALSE , 0 );
        //dbus_play_dtmf( key );
    }
628

629
630
    DEBUG("process_dialing : keyval : %i",keyval);
    DEBUG("process_dialing : key : %s",key);
Emmanuel Milou's avatar
Emmanuel Milou committed
631
632
633
634
635
636
637
638
639
640
641
642

    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 */
643
644
                gchar * before = c->_peer_number;
                if(strlen(c->_peer_number) >= 1){
Emmanuel Milou's avatar
Emmanuel Milou committed
645

646
647
648
649
650
651
652
653
654
					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
655
                    }
656
					calltree_update_call(current_calls, c, NULL);
Julien Bonjean's avatar
Julien Bonjean committed
657
                }
658
                else if(strlen(c->_peer_number) == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
659
                {
660
                    if(c->_state != CALL_STATE_TRANSFERT)
Emmanuel Milou's avatar
Emmanuel Milou committed
661
662
663
664
665
666
667
668
669
670
671
672
673
                        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
674
            {
Emmanuel Milou's avatar
Emmanuel Milou committed
675

676
677
678
679
680
681
                if (c->_state == CALL_STATE_TRANSFERT)
                {
                    c->_trsft_to = g_strconcat(c->_trsft_to, key, NULL);
                }
                else
                {
Emmanuel Milou's avatar
Emmanuel Milou committed
682
                    dbus_play_dtmf( key );
683
684
                    c->_peer_number = g_strconcat(c->_peer_number, key, NULL);
                }
Emmanuel Milou's avatar
Emmanuel Milou committed
685

686
                if(c->_state == CALL_STATE_DIALING)
Emmanuel Milou's avatar
Emmanuel Milou committed
687
                {
688
689
                    //g_free(c->_peer_name);
                    //c->_peer_name = g_strconcat("\"\" <", c->_peer_number, ">", NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
690
                }
691
                calltree_update_call(current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
692
693
694
            }
            break;
    }
695
696
}

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

698
    callable_obj_t *
areversat's avatar
areversat committed
699
sflphone_new_call()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
700
{
Julien Bonjean's avatar
Julien Bonjean committed
701

702
    callable_obj_t *c;
703
    callable_obj_t * current_selected_call;
704
    gchar *peer_name, *peer_number;
705

706
    DEBUG("sflphone_new_call");
707
708
709

    current_selected_call = calltab_get_selected_call(current_calls);

710
    if ((current_selected_call != NULL) && (current_selected_call->_confID == NULL))
711
	sflphone_on_hold();
712

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

717
718
719
    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
720

721
722
    c->_history_state = OUTGOING;

723
    calllist_add (current_calls,c);
724
    calltree_add_call (current_calls, c, NULL);
725
    update_actions();
726

Emmanuel Milou's avatar
Emmanuel Milou committed
727
    return c;
728
729
}

areversat's avatar
areversat committed
730

Emmanuel Milou's avatar
Emmanuel Milou committed
731
    void
areversat's avatar
areversat committed
732
733
sflphone_keypad( guint keyval, gchar * key)
{
734
    callable_obj_t * c = calltab_get_selected_call(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
735
736
737

    if((active_calltree != current_calls) || (active_calltree == current_calls && !c))
    {
738
        DEBUG("Not in a call, not dialing, create a new call");
Emmanuel Milou's avatar
Emmanuel Milou committed
739
740
741
742
743
744
745
746
        //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
747
                calltree_display (current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
748
749
750
751
752
753
                process_dialing(sflphone_new_call(), keyval, key);
                break;
        }
    }
    else if(c)
    {
754
        DEBUG("Call is non-zero");
755
        switch(c->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
756
757
        {
            case CALL_STATE_DIALING: // Currently dialing => edit number
758
                DEBUG("Writing a number");
Emmanuel Milou's avatar
Emmanuel Milou committed
759
760
761
762
763
764
765
766
                process_dialing(c, keyval, key);
                break;
            case CALL_STATE_RECORD:
            case CALL_STATE_CURRENT:
                switch (keyval)
                {
                    case 65307: /* ESCAPE */
                        dbus_hang_up(c);
767
                        set_timestamp (&c->_time_stop);
768
                        calltree_update_call(history, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
769
770
771
772
773
774
775
776
777
778
779
                        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);
780
                            //update_callable_obj_tree(current_calls,c);
Emmanuel Milou's avatar
Emmanuel Milou committed
781
782
783
784
785
786
787
788
789
                        }
                        break;
                }
                break;
            case CALL_STATE_INCOMING:
                switch (keyval)
                {
                    case 65293: /* ENTER */
                    case 65421: /* ENTER numpad */
790
                        c->_history_state = INCOMING;
791
                        calltree_update_call(history, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
792
                        dbus_accept(c);
793
                        DEBUG("from sflphone_keypad ( enter ) : "); stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
794
795
796
                        break;
                    case 65307: /* ESCAPE */
                        dbus_refuse(c);
797
                        DEBUG("from sflphone_keypad ( escape ) : "); stop_notification();
Emmanuel Milou's avatar
Emmanuel Milou committed
798
799
800
801
802
803
804
805
806
                        break;
                }
                break;
            case CALL_STATE_TRANSFERT:
                switch (keyval)
                {
                    case 65293: /* ENTER */
                    case 65421: /* ENTER numpad */
                        dbus_transfert(c);
807
                        set_timestamp (&c->_time_stop);
Emmanuel Milou's avatar
Emmanuel Milou committed
808
809
810
811
                        break;
                    case 65307: /* ESCAPE */
                        sflphone_unset_transfert(c);
                        break;
812
                    default: // When a call is on transfert, typing new numbers will add it to c->_peer_number
Emmanuel Milou's avatar
Emmanuel Milou committed
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
                        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:
835
                //c->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
836
837
838
839
                switch (keyval)
                {
                    case 65307: /* ESCAPE */
                        dbus_hang_up(c);
840
                        //c->_stop = 0;
841
                        calltree_update_call(history, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
842
843
844
845
846
847
                        break;
                }
                break;
            default:
                break;
        }
848

Alexandre Savard's avatar
Alexandre Savard committed
849
850
    }
    else {
851
        sflphone_new_call();
Emmanuel Milou's avatar
Emmanuel Milou committed
852
853
    }
}
854

855
856
857
858
859
860
861
862
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
863

864
static int _place_registered_call(callable_obj_t * c) {
865

866
867
    account_t * current = NULL;
  
868
869
870
871
872
    if(c == NULL) {
        DEBUG("callable_obj_t is NULL in _place_registered_call");
        return -1;
    }
    
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
    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;
    }
    
893
894
895
896
897
    if(g_strcasecmp(c->_accountID, "") != 0) {
        current = account_list_get_by_id(c->_accountID);
    } else {
        current = account_list_get_current();
    }
898

899
    if(current == NULL) { 
900
        DEBUG("Unexpected condition: account_t is NULL in %s at %d for accountID %s", __FILE__, __LINE__, c->_accountID);
901
902
        return -1;
    }   
903
                        
904
905
906
907
908
909
910
911
912
913
    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 );
914
        c->_accountID = current->accountID;
915
916
917
918
919
920
921
922
        dbus_place_call(c);
        notify_current_account( current );
    }        

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

924
925
926
    void
sflphone_place_call ( callable_obj_t * c )
{
927
928
	gchar *msg = "";

929
930
931
932
933
934
    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;
    }
935

936
    if(_is_direct_call(c)) {
937
938
939
940
		msg = g_markup_printf_escaped (_("Direct SIP call"));
        statusbar_pop_message(__MSG_ACCOUNT_DEFAULT);
        statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT);
        g_free(msg);
941
942
943
944
945
946
947
948
        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;
949
        }
Emmanuel Milou's avatar