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);
Emmanuel Milou's avatar
Emmanuel Milou committed
294
295
    }

296
	// Set the current account message number
297
	current_account_set_message_number (count);
298
299

	sflphone_fill_codec_list ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
300
301
}

Emmanuel Milou's avatar
Emmanuel Milou committed
302
303
gboolean sflphone_init() {

Emmanuel Milou's avatar
Emmanuel Milou committed
304
305
306
307
308
309
310
311
    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");
312

313
314
315
		// Init icons factory
		init_icon_factory ();

316
317
318
        current_calls = calltab_init(FALSE, CURRENT_CALLS);
        contacts = calltab_init(TRUE, CONTACTS);
        history = calltab_init(TRUE, HISTORY);
319

Emmanuel Milou's avatar
Emmanuel Milou committed
320
        account_list_init ();
321
        codec_capabilities_load ();
Emmanuel Milou's avatar
Emmanuel Milou committed
322
		conferencelist_init ();
323

324
        // Fetch the configured accounts
Emmanuel Milou's avatar
Emmanuel Milou committed
325
        sflphone_fill_account_list ();
326

327
328
329
        // Fetch the ip2ip profile 
        sflphone_fill_ip2ip_profile();
        
330
		// Fetch the conference list
331
		// sflphone_fill_conference_list();
332

Emmanuel Milou's avatar
Emmanuel Milou committed
333
334
        return TRUE;
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
335
336
}

337
338
339
340
341
void sflphone_fill_ip2ip_profile(void)
{
    ip2ip_profile = (GHashTable *) dbus_get_ip2_ip_details();
}

Emmanuel Milou's avatar
Emmanuel Milou committed
342
void sflphone_get_ip2ip_properties (GHashTable **properties)
343
{
Emmanuel Milou's avatar
Emmanuel Milou committed
344
	*properties	= ip2ip_profile;
345
346
}

Emmanuel Milou's avatar
Emmanuel Milou committed
347
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
348
sflphone_hang_up()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
349
{
350
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
351
352
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

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

400
    calltree_update_call(history, selectedCall, NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
401
402
403
}


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

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
457
458
}

Emmanuel Milou's avatar
Emmanuel Milou committed
459
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
460
461
sflphone_on_hold ()
{
462
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
463
464
465
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

    DEBUG("sflphone_on_hold");
Emmanuel Milou's avatar
Emmanuel Milou committed
466
467
    if(selectedCall)
    {
468
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
469
470
471
472
473
474
475
476
477
        {
            case CALL_STATE_CURRENT:
                dbus_hold (selectedCall);
                break;
            case CALL_STATE_RECORD:
                dbus_hold (selectedCall);
                break;

            default:
478
                WARN("Should not happen in sflphone_on_hold!");
Emmanuel Milou's avatar
Emmanuel Milou committed
479
480
481
                break;
        }
    }
482
483
484
    else if (selectedConf) {
        dbus_hold_conference(selectedConf);
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
485
486
}

Emmanuel Milou's avatar
Emmanuel Milou committed
487
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
488
489
sflphone_off_hold ()
{
490
    DEBUG("sflphone_off_hold");
491
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
492
493
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);

Emmanuel Milou's avatar
Emmanuel Milou committed
494
495
    if(selectedCall)
    {
496
        switch(selectedCall->_state)
Emmanuel Milou's avatar
Emmanuel Milou committed
497
498
499
500
501
        {
            case CALL_STATE_HOLD:
                dbus_unhold (selectedCall);
                break;
            default:
502
                WARN("Should not happen in sflphone_off_hold ()!");
Emmanuel Milou's avatar
Emmanuel Milou committed
503
504
505
                break;
        }
    }
506
    else if (selectedConf) {
Julien Bonjean's avatar
Julien Bonjean committed
507

508
509
510
511
        
        dbus_unhold_conference(selectedConf);
    }
    /*
512
    if(dbus_get_is_recording(selectedCall))
513
    {
514
        DEBUG("Currently recording!");
515
    }
516
    else
517
    {
518
        DEBUG("Not recording currently");
519
    }
520
    */
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
521
522
523
}


Emmanuel Milou's avatar
Emmanuel Milou committed
524
    void
525
sflphone_fail( callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
526
{
527
    c->_state = CALL_STATE_FAILURE;
528
    calltree_update_call(current_calls, c, NULL);
529
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
530
531
}

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

Emmanuel Milou's avatar
Emmanuel Milou committed
540
    void
541
sflphone_current( callable_obj_t * c )
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
542
{
543

544
545
    if( c->_state != CALL_STATE_HOLD )
        set_timestamp (&c->_time_start);
546
    c->_state = CALL_STATE_CURRENT;
547
    calltree_update_call(current_calls, c, NULL);
548
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
549
550
}

Emmanuel Milou's avatar
Emmanuel Milou committed
551
    void
552
sflphone_record( callable_obj_t * c )
alexandresavard's avatar
alexandresavard committed
553
{
554
555
    if( c->_state != CALL_STATE_HOLD )
        set_timestamp (&c->_time_start);
556
    c->_state = CALL_STATE_RECORD;
557
    calltree_update_call(current_calls, c, NULL);
558
    update_actions();
alexandresavard's avatar
alexandresavard committed
559
560
}

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

Emmanuel Milou's avatar
Emmanuel Milou committed
574
    void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
575
576
sflphone_unset_transfert()
{
577
    callable_obj_t * c = calltab_get_selected_call(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
578
579
    if(c)
    {
580
        c->_state = CALL_STATE_CURRENT;
581
        c->_trsft_to = g_strdup("");
582
        calltree_update_call(current_calls, c, NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
583
    }
584
    update_actions();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
585
}
Emmanuel Milou's avatar
Emmanuel Milou committed
586

587
    void
588
589
590
591
592
sflphone_display_transfer_status(const gchar* message)
{
    statusbar_push_message( message , __MSG_ACCOUNT_DEFAULT);
}

Emmanuel Milou's avatar
Emmanuel Milou committed
593
    void
594
sflphone_incoming_call (callable_obj_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
595
{
596
597
	gchar *msg = "";

598
    c->_history_state = MISSED;
Julien Bonjean's avatar
Julien Bonjean committed
599
600
    calllist_add ( current_calls, c );
    calllist_add( history, c );
601
    calltree_add_call( current_calls, c, NULL);
602
    update_actions();
Julien Bonjean's avatar
Julien Bonjean committed
603
    calltree_display (current_calls);
604
605
606
607
608
609
610
611
	
	// 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
612
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
613

Emmanuel Milou's avatar
Emmanuel Milou committed
614
    void
615
process_dialing(callable_obj_t * c, guint keyval, gchar * key)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
616
{
Emmanuel Milou's avatar
Emmanuel Milou committed
617
    // We stop the tone
618
    if(strlen(c->_peer_number) == 0 && c->_state != CALL_STATE_TRANSFERT){
Emmanuel Milou's avatar
Emmanuel Milou committed
619
620
621
        dbus_start_tone( FALSE , 0 );
        //dbus_play_dtmf( key );
    }
622

623
624
    DEBUG("process_dialing : keyval : %i",keyval);
    DEBUG("process_dialing : key : %s",key);
Emmanuel Milou's avatar
Emmanuel Milou committed
625
626
627
628
629
630
631
632
633
634
635
636

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

640
641
					if (c->_state == CALL_STATE_TRANSFERT)
					{
642
643
644
                                                // Process backspace if and only if string not NULL
                                                if(strlen(c->_trsft_to) > 0)
                                                     c->_trsft_to = g_strndup (c->_trsft_to, strlen(c->_trsft_to) - 1);
645
646
647
648
649
650
					}
					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
651
                    }
652
					calltree_update_call(current_calls, c, NULL);
Julien Bonjean's avatar
Julien Bonjean committed
653
                }
654
                else if(strlen(c->_peer_number) == 0)
Emmanuel Milou's avatar
Emmanuel Milou committed
655
                {
656
                    if(c->_state != CALL_STATE_TRANSFERT)
Emmanuel Milou's avatar
Emmanuel Milou committed
657
658
659
660
661
662
663
664
665
666
667
668
669
                        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
670
            {
Emmanuel Milou's avatar
Emmanuel Milou committed
671

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

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

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

694
    callable_obj_t *
areversat's avatar
areversat committed
695
sflphone_new_call()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
696
{
Julien Bonjean's avatar
Julien Bonjean committed
697

698
    callable_obj_t *c;
699
    callable_obj_t * current_selected_call;
700
    gchar *peer_name, *peer_number;
701

702
    DEBUG("sflphone_new_call");
703
704
705

    current_selected_call = calltab_get_selected_call(current_calls);

706
    if ((current_selected_call != NULL) && (current_selected_call->_confID == NULL))
707
	sflphone_on_hold();
708

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

713
714
715
    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
716

717
718
    c->_history_state = OUTGOING;

719
    calllist_add (current_calls,c);
720
    calltree_add_call (current_calls, c, NULL);
721
    update_actions();
722

Emmanuel Milou's avatar
Emmanuel Milou committed
723
    return c;
724
725
}

areversat's avatar
areversat committed
726

Emmanuel Milou's avatar
Emmanuel Milou committed
727
    void
areversat's avatar
areversat committed
728
729
sflphone_keypad( guint keyval, gchar * key)
{
730
    callable_obj_t * c = calltab_get_selected_call(current_calls);
Emmanuel Milou's avatar
Emmanuel Milou committed
731
732
733

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

Alexandre Savard's avatar
Alexandre Savard committed
845
846
    }
    else {
847
        sflphone_new_call();
Emmanuel Milou's avatar
Emmanuel Milou committed
848
849
    }
}
850

851
852
853
854
855
856
857
858
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
859

860
static int _place_registered_call(callable_obj_t * c) {
861

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

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

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

920
921
922
    void
sflphone_place_call ( callable_obj_t * c )
{
923
924
	gchar *msg = "";

925
926
927
928
929
930
    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;
    }
931

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

Alexandre Savard's avatar
Alexandre Savard committed
949