actions.c 11.3 KB
Newer Older
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
1
2
/*
 *  Copyright (C) 2007 Savoir-Faire Linux inc.
3
 *  Author: Pierre-Luc Beaudoin <pierre-luc@squidy.info>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 *                                                                              
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *                                                                                
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *                                                                              
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
19

20
#include <accountlist.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
21
#include <actions.h>
22
23
#include <calltree.h>
#include <dbus.h>
24
#include <mainwindow.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
25
#include <menus.h>
26
27
#include <screen.h>
#include <statusicon.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
28

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

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

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
void
sflphone_notify_voice_mail (guint count)
{
  if(count > 0)
  {
    gchar * message = g_new0(gchar, 50);
    g_sprintf(message, "%d new voice mail%s", count, (count > 1? "s" : "")); 
    status_bar_message(message);
    g_free(message);
  }
  else
  {
    status_bar_message("");
  }
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
gboolean
sflphone_quit ()
{
  gboolean quit = FALSE;
  guint count = call_list_get_size();
  if(count > 0){
    quit = main_window_ask_quit();
  }
  else{
    quit = TRUE;
  }
  
  if (quit)
  {
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
67
    dbus_unregister(getpid());
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
68
69
    dbus_clean ();
    //call_list_clean(); TODO
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
70
    //account_list_clean()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
71
72
73
74
75
76
77
78
79
    gtk_main_quit ();
  }
  return quit;
}

void 
sflphone_hold(call_t * c )
{
  c->state = CALL_STATE_HOLD;
80
  update_call_tree(c);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
81
  update_menus();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
82
83
84
  screen_clear();
}

85
86
87
88
89
void 
sflphone_ringing(call_t * c )
{
  c->state = CALL_STATE_RINGING;
  update_call_tree(c);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
90
  update_menus();
91
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
92

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
93
/** Internal to actions: Fill account list */
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
94
95
96
void
sflphone_fill_account_list()
{
97
98
  account_list_clear ( );
  
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  gchar ** array = (gchar **)dbus_account_list();
  gchar ** accountID;
  for (accountID = array; *accountID; accountID++)
  {
    account_t * a = g_new0(account_t,1);
    a->accountID = g_strdup(*accountID);
    account_list_add(a);
  }
  g_strfreev (array);
  
  int i;
  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);
    a->properties = details;
    
    gchar * status = g_hash_table_lookup(details, "Status");
    if(strcmp(status, "REGISTERED") == 0)
    {
      a->state = ACCOUNT_STATE_REGISTERED;
    }
    else if(strcmp(status, "UNREGISTERED") == 0)
    {
      a->state = ACCOUNT_STATE_UNREGISTERED;
    }
125
126
127
128
    else if(strcmp(status, "TRYING") == 0)
    {
      a->state = ACCOUNT_STATE_TRYING;
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
129
130
131
132
    else if(strcmp(status, "ERROR") == 0)
    {
      a->state = ACCOUNT_STATE_ERROR;
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
133
134
135
136
137
138
139
    else
    {
      a->state = ACCOUNT_STATE_INVALID;
    }
    
  }
  
140
	toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
141
142
143
144
145
146
147
148
149
}

gboolean
sflphone_init()
{
  call_list_init ();
  account_list_init ();
  if(!dbus_connect ())
  {
150
    main_window_error_message("Unable to connect to the SFLphone server.\nMake sure the daemon is running.");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
151
152
153
154
    return FALSE;
  }
  else 
  {
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
155
    dbus_register(getpid(), "Gtk+ Client");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
156
157
158
159
160
161
    sflphone_fill_account_list();
    return TRUE;
  }
}

void 
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
162
sflphone_hang_up()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
163
{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  call_t * selectedCall = call_get_selected();
  if(selectedCall)
  {
    switch(selectedCall->state)
    {
      case CALL_STATE_CURRENT:
      case CALL_STATE_HOLD:
      case CALL_STATE_DIALING:
      case CALL_STATE_RINGING:
      case CALL_STATE_BUSY:
      case CALL_STATE_FAILURE:
        dbus_hang_up (selectedCall);
        break;
      case CALL_STATE_INCOMING:  
        dbus_refuse (selectedCall);
        break;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
180
181
182
      case CALL_STATE_TRANSFERT:  
        dbus_hang_up (selectedCall);
        break;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
183
      default:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
184
        g_warning("Should not happen in sflphone_hang_up()!");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
        break;
    }
  }
}


void 
sflphone_pick_up()
{
  call_t * selectedCall = call_get_selected();
  if(selectedCall)
  {
    switch(selectedCall->state)
    {
      case CALL_STATE_DIALING:
        sflphone_place_call (selectedCall);
        break;
      case CALL_STATE_INCOMING:
        dbus_accept (selectedCall);
        break;
      case CALL_STATE_HOLD:
        dbus_unhold (selectedCall);
        break;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
208
209
210
      case CALL_STATE_TRANSFERT:
        dbus_transfert (selectedCall);
        break;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
211
      default:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
212
        g_warning("Should not happen in sflphone_pick_up()!");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
213
214
215
        break;
    }
  }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
216
217
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
218
219
220
221
222
223
224
225
226
227
228
229
void 
sflphone_on_hold ()
{
  call_t * selectedCall = call_get_selected();
  if(selectedCall)
  {
    switch(selectedCall->state)
    {
      case CALL_STATE_CURRENT:
        dbus_hold (selectedCall);
        break;
      default:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
230
        g_warning("Should not happen in sflphone_on_hold!");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
        break;
    }
  }
}

void 
sflphone_off_hold ()
{
  call_t * selectedCall = call_get_selected();
  if(selectedCall)
  {
    switch(selectedCall->state)
    {
      case CALL_STATE_HOLD:
        dbus_unhold (selectedCall);
        break;
      default:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
248
        g_warning("Should not happen in sflphone_off_hold ()!");
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
249
250
251
252
253
254
        break;
      }
  }
}


Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
255
256
257
258
259
void 
sflphone_fail( call_t * c )
{
  c->state = CALL_STATE_FAILURE;
  update_call_tree(c);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
260
  update_menus();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
261
262
263
264
265
266
267
268
  screen_set_call(c);
}

void 
sflphone_busy( call_t * c )
{
  c->state = CALL_STATE_BUSY;
  update_call_tree(c);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
269
  update_menus();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
270
271
272
  screen_set_call(c);
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
273
274
275
276
void 
sflphone_current( call_t * c )
{
  c->state = CALL_STATE_CURRENT;
277
  update_call_tree(c);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
278
  update_menus();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
279
280
281
282
  screen_set_call(c);
}

void 
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
283
sflphone_set_transfert()
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
284
{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
285
286
287
288
289
290
291
292
293
  call_t * c = call_get_selected();
  if(c)
  {
    c->state = CALL_STATE_TRANSFERT;
    c->to = g_strdup("");
    screen_set_call(c);
    update_call_tree(c);
    update_menus();
  }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
294
  toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
295
296
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
297
298
299
300
301
302
303
304
305
306
307
308
309
310
void 
sflphone_unset_transfert()
{
  call_t * c = call_get_selected();
  if(c)
  {
    c->state = CALL_STATE_CURRENT;
    c->to = g_strdup("");
    screen_set_call(c);
    update_call_tree(c);
    update_menus();
  }
  toolbar_update_buttons();
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
311
312
313
314
void
sflphone_incoming_call (call_t * c) 
{
  call_list_add ( c );
315
  status_icon_unminimize();
316
  update_call_tree_add(c);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
317
  update_menus();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
318
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
319

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
320
321
322
323
void 
sflphone_hung_up (call_t * c )
{
  call_list_remove(c->callID);
324
  update_call_tree_remove(c);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
325
  update_menus();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
326
327
328
  screen_clear();
}

329
void process_dialing(call_t * c, guint keyval, gchar * key)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
330
{
331
  switch (keyval)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
332
  {
333
334
335
336
337
338
339
340
341
342
343
344
  case 65293: /* ENTER */
  case 65421: /* ENTER numpad */
    sflphone_place_call(c);
    break;
  case 65307: /* ESCAPE */
    dbus_hang_up(c);
    break;
  case 65288: /* BACKSPACE */
    {  /* Brackets mandatory because of local vars */
      gchar * before = c->to;
      if(strlen(c->to) > 1){
        c->to = g_strndup(c->to, strlen(c->to) -1);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
345
346
        g_free(before);
        g_print("TO: %s\n", c->to);
347
      
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
348
349
350
351
352
        if(c->state == CALL_STATE_DIALING)
        {
          g_free(c->from);
          c->from = g_strconcat("\"\" <", c->to, ">", NULL);
        }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
353
        screen_set_call(c);
354
        update_call_tree(c);
355
356
357
358
      } 
      else if(strlen(c->to) == 1)
      {
        dbus_hang_up(c);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
359
360
      }
    }
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
    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))
    { 
      gchar * before = c->to;
      c->to = g_strconcat(c->to, key, NULL);
      g_free(before);
      g_print("TO: %s\n", c->to);
      
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
376
377
378
379
380
      if(c->state == CALL_STATE_DIALING)
      {
        g_free(c->from);
        c->from = g_strconcat("\"\" <", c->to, ">", NULL);
      }
381
382
383
384
      screen_set_call(c);
      update_call_tree(c);
    }
    break;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
385
  }
386
387
388
  
}

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

call_t * sflphone_new_call()
{
  call_t * c = g_new0 (call_t, 1);
  c->state = CALL_STATE_DIALING;
  c->from = g_strconcat("\"\" <>", NULL);
  
  c->callID = g_new0(gchar, 30);
  g_sprintf(c->callID, "%d", rand()); 
  
  c->to = g_strdup("");
  
  call_list_add(c);
  screen_set_call(c);
  update_call_tree_add(c);  
  update_menus();
  
  return c;
407
408
409
410
411
412
413
}

void 
sflphone_keypad( guint keyval, gchar * key)
{
  call_t * c = call_get_selected();
  if(c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
414
  {
415
  
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
416
    switch(c->state) 
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
417
    {
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
418
      case CALL_STATE_DIALING: // Currently dialing => edit number
419
        process_dialing(c, keyval, key);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
420
        break;
421
      case CALL_STATE_CURRENT:
422
423
424
425
426
        switch (keyval)
        {
        case 65307: /* ESCAPE */
          dbus_hang_up(c);
          break;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
427
        default:  // TODO should this be here?
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
428
          dbus_play_dtmf(key);
429
430
431
432
433
434
435
436
437
438
439
          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);
            screen_set_call(c);
            update_call_tree(c);
          }
          break;
440
        }
441
442
443
444
445
446
447
448
449
450
451
        break;
      case CALL_STATE_INCOMING:
        switch (keyval)
        {
        case 65293: /* ENTER */
        case 65421: /* ENTER numpad */
          dbus_accept(c);
          break;
        case 65307: /* ESCAPE */
          dbus_refuse(c);
          break;
452
        }
453
        break;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
454
455
456
457
458
459
460
461
      case CALL_STATE_TRANSFERT:
        switch (keyval)
        {
        case 65293: /* ENTER */
        case 65421: /* ENTER numpad */
          dbus_transfert(c);
          break;
        case 65307: /* ESCAPE */
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
462
          sflphone_hang_up(c); 
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
463
464
465
466
467
468
          break;
        default: // When a call is on transfert, typing new numbers will add it to c->to
          process_dialing(c, keyval, key);
          break;
        }
        break;
469
470
471
472
473
474
475
476
477
478
479
      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
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
480
          process_dialing(sflphone_new_call(), keyval, key);
481
482
483
          break;
        }
        break;
484
      case CALL_STATE_RINGING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
485
486
      case CALL_STATE_BUSY:
      case CALL_STATE_FAILURE:
487
488
489
490
491
492
493
        switch (keyval)
        {
        case 65307: /* ESCAPE */
          dbus_hang_up(c);
          break;
        }
        break;
494
495
496
497
498
499
      default:
        break;
     } 
  }
  else 
  { // Not in a call, not dialing, create a new call 
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
500
501
502
503
504
505
506
507
508
509
510
511
    switch (keyval)
    {
    case 65293: /* ENTER */
    case 65421: /* ENTER numpad */
    case 65307: /* ESCAPE */
      break;
    default:
      process_dialing(sflphone_new_call(), keyval, key);
      break;
    }
        
     
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
512
513
514
  }
} 

515

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
void 
sflphone_place_call ( call_t * c )
{
  if(c->state == CALL_STATE_DIALING)
  {
    account_t * a = account_list_get_by_state (ACCOUNT_STATE_REGISTERED);
    if(a)
    {
      c->accountID = a->accountID;
      dbus_place_call(c);
    }
    else
    {
      main_window_error_message("There are no registered accounts to make this call with.");
    }
    
  }
}