managerimpl.cpp 92.8 KB
Newer Older
jpbl's avatar
jpbl committed
1
/*
2
3
 *  Copyright (C) 2004-2007 Savoir-Faire Linux inc.
 *  Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
jpbl's avatar
jpbl committed
4
 *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
5
 *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
6
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
7
 *  Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@savoirfairelinux.com>
8
 *
jpbl's avatar
jpbl committed
9
10
 *  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
11
 *  the Free Software Foundation; either version 3 of the License, or
jpbl's avatar
jpbl committed
12
 *  (at your option) any later version.
13
 *
jpbl's avatar
jpbl committed
14
15
16
17
 *  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.
18
 *
jpbl's avatar
jpbl committed
19
20
21
22
23
24
25
26
27
28
 *  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.
 */

#include <errno.h>
#include <time.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
29
#include <sstream>
jpbl's avatar
jpbl committed
30
31
32
33
34
35
36
37
#include <sys/types.h> // mkdir(2)
#include <sys/stat.h>	// mkdir(2)

#include <cc++/socket.h>   // why do I need this here?
#include <ccrtp/channel.h> // why do I need this here?
#include <ccrtp/rtp.h>     // why do I need this here?
#include <cc++/file.h>

38
39
#include "conference.h"

jpbl's avatar
jpbl committed
40
#include "manager.h"
41
#include "account.h"
42
#include "sipaccount.h"
jpbl's avatar
jpbl committed
43
#include "audio/audiolayer.h"
44
45
#include "audio/alsalayer.h"
#include "audio/pulselayer.h"
jpbl's avatar
jpbl committed
46
47
#include "audio/tonelist.h"

yanmorin's avatar
   
yanmorin committed
48
#include "accountcreator.h" // create new account
49
50
#include "sipvoiplink.h"

jpbl's avatar
jpbl committed
51
52
53
54
55
56
57
#include "user_cfg.h"

#define fill_config_str(name, value) \
  (_config.addConfigTreeItem(section, Conf::ConfigTreeItem(std::string(name), std::string(value), type_str)))
#define fill_config_int(name, value) \
  (_config.addConfigTreeItem(section, Conf::ConfigTreeItem(std::string(name), std::string(value), type_int)))

58
ManagerImpl::ManagerImpl (void)
59
        : _hasTriedToRegister (false)
Yun Liu's avatar
Yun Liu committed
60
        , _config()
61
        , _currentCallId2()
62
        , _currentCallMutex()
63
64
65
        , _codecBuilder (NULL)
        , _audiodriver (NULL)
        , _dtmfKey (NULL)
Yun Liu's avatar
Yun Liu committed
66
        , _codecDescriptorMap()
67
        , _toneMutex()
68
        , _telephoneTone (NULL)
Yun Liu's avatar
Yun Liu committed
69
        , _audiofile()
70
71
        , _spkr_volume (0)
        , _mic_volume (0)
72
        , _mutex()
73
        , _dbus (NULL)
Yun Liu's avatar
Yun Liu committed
74
        , _waitingCall()
75
        , _waitingCallMutex()
76
77
78
79
        , _nbIncomingWaitingCall (0)
        , _path ("")
        , _exist (0)
        , _setupLoaded (false)
Yun Liu's avatar
Yun Liu committed
80
        , _firewallPort()
81
82
        , _firewallAddr ("")
        , _hasZeroconf (false)
Yun Liu's avatar
Yun Liu committed
83
        , _callAccountMap()
84
        , _callAccountMapMutex()
Emmanuel Milou's avatar
Emmanuel Milou committed
85
        , _callConfigMap()
Yun Liu's avatar
Yun Liu committed
86
        , _accountMap()
87
        , _cleaner (NULL)
88
        , _history (NULL)
jpbl's avatar
jpbl committed
89
{
90

91
    // initialize random generator for call id
92
    srand (time (NULL));
yanmorin's avatar
   
yanmorin committed
93

94
    _cleaner = new NumberCleaner ();
95
    _history = new HistoryManager ();
96

yanmorin's avatar
   
yanmorin committed
97
#ifdef TEST
98
99
100
101
    testAccountMap();
    loadAccountMap();
    testCallAccountMap();
    unloadAccountMap();
yanmorin's avatar
   
yanmorin committed
102
103
#endif

104
105
    // should be call before initConfigFile
    // loadAccountMap();, called in init() now.
jpbl's avatar
jpbl committed
106
107
108
}

// never call if we use only the singleton...
109
ManagerImpl::~ManagerImpl (void)
jpbl's avatar
jpbl committed
110
{
111
    // terminate();
112
113
114
    delete _cleaner;
    _cleaner=0;
    _debug ("%s stop correctly.\n", PROGNAME);
jpbl's avatar
jpbl committed
115
116
}

117
void
118
ManagerImpl::init()
jpbl's avatar
jpbl committed
119
{
120
121
    // Load accounts, init map
    loadAccountMap();
122

123
    initVolume();
124

125
    if (_exist == 0) {
126
        _debug ("Cannot create config file in your home directory\n");
127
    }
128

129
    initAudioDriver();
130

131
    selectAudioDriver();
jpbl's avatar
jpbl committed
132

133
134
    // Initialize the list of supported audio codecs
    initAudioCodec();
135

136
    AudioLayer *audiolayer = getAudioDriver();
137

138
    if (audiolayer != 0) {
139
        unsigned int sampleRate = audiolayer->getSampleRate();
jpbl's avatar
jpbl committed
140

141
142
143
        _debugInit ("Load Telephone Tone");
        std::string country = getConfigString (PREFERENCES, ZONE_TONE);
        _telephoneTone = new TelephoneTone (country, sampleRate);
jpbl's avatar
jpbl committed
144

145
146
        _debugInit ("Loading DTMF key");
        _dtmfKey = new DTMF (sampleRate);
147
    }
148
149

    if (audiolayer == 0)
150
        audiolayer->stopStream();
151
152
153


    // Load the history
154
    _history->load_history (getConfigInt (PREFERENCES, CONFIG_HISTORY_LIMIT));
jpbl's avatar
jpbl committed
155
156
157
158
}

void ManagerImpl::terminate()
{
159
    _debug ("ManagerImpl::terminate \n");
160
    saveConfig();
jpbl's avatar
jpbl committed
161

162
    unloadAccountMap();
163

164
    _debug ("Unload DTMF Key \n");
165
    delete _dtmfKey;
jpbl's avatar
jpbl committed
166

167
168
169
    _debug ("Unload Audio Driver \n");
    delete _audiodriver;
    _audiodriver = NULL;
jpbl's avatar
jpbl committed
170

171
172
173
    _debug ("Unload Telephone Tone \n");
    delete _telephoneTone;
    _telephoneTone = NULL;
174

175
    _debug ("Unload Audio Codecs \n");
176
    _codecDescriptorMap.deleteHandlePointer();
177

jpbl's avatar
jpbl committed
178
179
}

yanmorin's avatar
   
yanmorin committed
180
bool
181
182
183
ManagerImpl::isCurrentCall (const CallID& callId)
{
    return (_currentCallId2 == callId ? true : false);
jpbl's avatar
jpbl committed
184
185
}

yanmorin's avatar
   
yanmorin committed
186
bool
187
188
189
190
191
192
193
194
195
ManagerImpl::hasCurrentCall()
{
    _debug ("Current call ID = %s\n", _currentCallId2.c_str());

    if (_currentCallId2 != "") {
        return true;
    }

    return false;
jpbl's avatar
jpbl committed
196
197
}

198
const CallID&
199
200
201
ManagerImpl::getCurrentCallId()
{
    return _currentCallId2;
jpbl's avatar
jpbl committed
202
203
204
}

void
205
206
207
208
ManagerImpl::switchCall (const CallID& id)
{
    ost::MutexLock m (_currentCallMutex);
    _currentCallId2 = id;
jpbl's avatar
jpbl committed
209
210
211
212
213
214
}


///////////////////////////////////////////////////////////////////////////////
// Management of events' IP-phone user
///////////////////////////////////////////////////////////////////////////////
215
/* Main Thread */
Emmanuel Milou's avatar
Emmanuel Milou committed
216

217
218
bool
ManagerImpl::outgoingCall (const std::string& accountid, const CallID& id, const std::string& to)
yanmorin's avatar
   
yanmorin committed
219
{
220
    std::string pattern, to_cleaned;
Emmanuel Milou's avatar
Emmanuel Milou committed
221
222
    Call::CallConfiguration callConfig;
    SIPVoIPLink *siplink;
223

224
    _debug ("ManagerImpl::outgoingCall(%s)\n", id.c_str());
225

226
227
    if (getConfigString (HOOKS, PHONE_NUMBER_HOOK_ENABLED) ==  "1")
        _cleaner->set_phone_number_prefix (getConfigString (HOOKS, PHONE_NUMBER_HOOK_ADD_PREFIX));
228
229
    else
        _cleaner->set_phone_number_prefix ("");
230

231
    to_cleaned = _cleaner->clean (to);
Emmanuel Milou's avatar
Emmanuel Milou committed
232
233

    /* Check what kind of call we are dealing with */
234
    check_call_configuration (id, to_cleaned, &callConfig);
235

Emmanuel Milou's avatar
Emmanuel Milou committed
236
237
238
    if (callConfig == Call::IPtoIP) {
        _debug ("Start IP to IP call\n");
        /* We need to retrieve the sip voiplink instance */
239
240
        siplink = SIPVoIPLink::instance ("");

241
        if (siplink->new_ip_to_ip_call (id, to_cleaned)) {
Emmanuel Milou's avatar
Emmanuel Milou committed
242
243
            switchCall (id);
            return true;
244
        } else {
Emmanuel Milou's avatar
Emmanuel Milou committed
245
246
            callFailure (id);
        }
247

Emmanuel Milou's avatar
Emmanuel Milou committed
248
        return false;
249
    }
250

251
252
    if (!accountExists (accountid)) {
        _debug ("! Manager Error: Outgoing Call: account doesn't exist\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
253
254
        return false;
    }
255

256
257
    if (getAccountFromCall (id) != AccountNULL) {
        _debug ("! Manager Error: Outgoing Call: call id already exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
258
259
        return false;
    }
260

Emmanuel Milou's avatar
Emmanuel Milou committed
261
    if (hasCurrentCall()) {
262
263
        _debug ("* Manager Info: there is currently a call, try to hold it\n");
        onHoldCall (getCurrentCallId());
Emmanuel Milou's avatar
Emmanuel Milou committed
264
    }
265

266
267
268
269
270
271
    _debug ("- Manager Action: Adding Outgoing Call %s on account %s\n", id.data(), accountid.data());

    associateCallToAccount (id, accountid);

    if (getAccountLink (accountid)->newOutgoingCall (id, to_cleaned)) {
        switchCall (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
272
273
        return true;
    } else {
274
275
        callFailure (id);
        _debug ("! Manager Error: An error occur, the call was not created\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
276
    }
277

Emmanuel Milou's avatar
Emmanuel Milou committed
278
    return false;
jpbl's avatar
jpbl committed
279
280
}

yanmorin's avatar
   
yanmorin committed
281
//THREAD=Main : for outgoing Call
282
283
bool
ManagerImpl::answerCall (const CallID& id)
jpbl's avatar
jpbl committed
284
{
285
286

    _debug("ManagerImpl::answerCall(%s)", id.c_str());
287
288

    stopTone (true);
289

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
    AccountID currentAccountId;
    currentAccountId = getAccountFromCall (id);
    if(currentAccountId == AccountNULL) {
        _debug("ManagerImpl::answerCall : AccountId is null\n");
        return false;
    }
    
    Call* currentCall = NULL;
    currentCall = getAccountLink (currentAccountId)->getCall (id);
    if (currentCall == NULL) {
        _debug("ManagerImpl::answerCall : currentCall is null\n");
    }
    
    Call* lastCall = NULL;
    if (!getCurrentCallId().empty()) {
        lastCall = getAccountLink (currentAccountId)->getCall (getCurrentCallId());
        if (lastCall == NULL) {
            _debug("ManagerImpl::answerCall : lastCall is null\n");
        }
309
    }
310

311
312
    _debug ("ManagerImpl::answerCall :: current call->getState %i \n", currentCall->getState());
    _debug ("Try to answer call: %s\n", id.data());
Yun Liu's avatar
Yun Liu committed
313

314
    if (lastCall != NULL ) {
315
        if (lastCall->getState() == Call::Active && !participToConference(getCurrentCallId())) {
316
317
318
            _debug ("* Manager Info: there is currently a call, try to hold it\n");
            onHoldCall (getCurrentCallId());
        }
319
320
	else
	{
321
	    _debug("Current call particips to a conference! Do not hold it!\n");
322
	}
323
324
    }

325
    if (!getAccountLink (currentAccountId)->answer (id)) {
326
327
328
329
        // error when receiving...
        removeCallAccount (id);
        return false;
    }
Alexandre Savard's avatar
Alexandre Savard committed
330

331
332
    // if it was waiting, it's waiting no more
    if (_dbus) _dbus->getCallManager()->callStateChanged (id, "CURRENT");
333
334
335
336
        
    std::string codecName = Manager::instance().getCurrentCodecName (id);
    if (_dbus) _dbus->getCallManager()->currentSelectedCodec (id,codecName.c_str());
        
337
    removeWaitingCall (id);
338

339
340
341
    switchCall (id);

    return true;
jpbl's avatar
jpbl committed
342
343
}

yanmorin's avatar
   
yanmorin committed
344
//THREAD=Main
345
346
bool
ManagerImpl::hangupCall (const CallID& id)
jpbl's avatar
jpbl committed
347
{
348
    _debug ("ManagerImpl::hangupCall()\n");
349
350
351
    PulseLayer *pulselayer;
    AccountID accountid;
    bool returnValue;
352
    AudioLayer *audiolayer;
Emmanuel Milou's avatar
Emmanuel Milou committed
353

354
    stopTone (false);
355
    switchCall (id);
yanmorin's avatar
   
yanmorin committed
356

357
    /* Broadcast a signal over DBus */
358

359
    _debug("ManagerImpl::hangupCall: Send DBUS call state change (HUNGUP) for id %s\n", id.c_str());
360
361
    if (_dbus) _dbus->getCallManager()->callStateChanged (id, "HUNGUP");

362
363
    int nbCalls = getCallList().size();

364
    audiolayer = getAudioDriver();
365
    // stop streamx
366
367
368
    if (! (nbCalls >= 1))
    {
	_debug("ManagerImpl::stop audio stream, ther is only %i call(s) remaining\n", nbCalls);
369
        audiolayer->stopStream();
370
    }
371

Emmanuel Milou's avatar
Emmanuel Milou committed
372
373
    /* Direct IP to IP call */
    if (getConfigFromCall (id) == Call::IPtoIP) {
374
        returnValue = SIPVoIPLink::instance (AccountNULL)->hangup (id);
375
    }
376

Emmanuel Milou's avatar
Emmanuel Milou committed
377
    /* Classic call, attached to an account */
378
    else {
379
380
        accountid = getAccountFromCall (id);

381
382
        if (accountid == AccountNULL) 
	{
383
            _debug ("! Manager Hangup Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
384
385
            return false;
        }
386
387
388
389

        returnValue = getAccountLink (accountid)->hangup (id);

        removeCallAccount (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
390
    }
391

392
    _debug("ManagerImpl::hangupCall CURRENT CALL ID %s\n", getCurrentCallId().c_str());
393

394
    switchCall ("");
395

396
    _debug("ManagerImpl::hangupCall CURRENT CALL ID %s\n", getCurrentCallId().c_str());
397

398
    if (_audiodriver->getLayerType() == PULSEAUDIO && getConfigInt (PREFERENCES , CONFIG_PA_VOLUME_CTRL)) {
399
        pulselayer = dynamic_cast<PulseLayer *> (getAudioDriver());
400
401

        if (pulselayer)  pulselayer->restorePulseAppsVolume();
402
    }
403

404
405
406
407
408
    if(participToConference(id))
    {
	removeParticipant(id);
    }

409
    return returnValue;
jpbl's avatar
jpbl committed
410
411
}

yanmorin's avatar
   
yanmorin committed
412
//THREAD=Main
413
bool
yanmorin's avatar
   
yanmorin committed
414
ManagerImpl::cancelCall (const CallID& id)
jpbl's avatar
jpbl committed
415
{
Emmanuel Milou's avatar
Emmanuel Milou committed
416
417
    AccountID accountid;
    bool returnValue;
yanmorin's avatar
   
yanmorin committed
418

419
    stopTone (true);
420

Emmanuel Milou's avatar
Emmanuel Milou committed
421
    /* Direct IP to IP call */
422

Emmanuel Milou's avatar
Emmanuel Milou committed
423
    if (getConfigFromCall (id) == Call::IPtoIP) {
424
        returnValue = SIPVoIPLink::instance (AccountNULL)->cancel (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
425
426
427
    }

    /* Classic call, attached to an account */
428
    else {
429
430
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
431
        if (accountid == AccountNULL) {
432
            _debug ("! Manager Cancel Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
433
434
            return false;
        }
435
436
437
438

        returnValue = getAccountLink (accountid)->cancel (id);

        removeCallAccount (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
439
    }
440

Emmanuel Milou's avatar
Emmanuel Milou committed
441
    // it could be a waiting call?
442
443
444
    removeWaitingCall (id);

    switchCall ("");
Emmanuel Milou's avatar
Emmanuel Milou committed
445
446

    return returnValue;
jpbl's avatar
jpbl committed
447
448
}

yanmorin's avatar
   
yanmorin committed
449
//THREAD=Main
450
451
bool
ManagerImpl::onHoldCall (const CallID& id)
jpbl's avatar
jpbl committed
452
{
Emmanuel Milou's avatar
Emmanuel Milou committed
453
454
    AccountID accountid;
    bool returnValue;
455
    CallID call_id;
yanmorin's avatar
   
yanmorin committed
456

457
    stopTone (true);
458

459
460
    call_id = id;

461
    switchCall (id);
462

Emmanuel Milou's avatar
Emmanuel Milou committed
463
    /* Direct IP to IP call */
464

Emmanuel Milou's avatar
Emmanuel Milou committed
465
    if (getConfigFromCall (id) == Call::IPtoIP) {
466
        returnValue = SIPVoIPLink::instance (AccountNULL)-> onhold (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
467
    }
468

Emmanuel Milou's avatar
Emmanuel Milou committed
469
    /* Classic call, attached to an account */
470
    else {
471
472
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
473
        if (accountid == AccountNULL) {
474
            _debug ("Manager On Hold Call: Account ID %s or callid %s doesn't exists\n", accountid.c_str(), id.c_str());
Emmanuel Milou's avatar
Emmanuel Milou committed
475
476
            return false;
        }
477
478

        returnValue = getAccountLink (accountid)->onhold (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
479
    }
480

481
482
483
    removeWaitingCall (id);

    switchCall ("");
484

485
    if (_dbus) _dbus->getCallManager()->callStateChanged (call_id, "HOLD");
486

Emmanuel Milou's avatar
Emmanuel Milou committed
487
    return returnValue;
yanmorin's avatar
   
yanmorin committed
488
489
490
}

//THREAD=Main
491
492
bool
ManagerImpl::offHoldCall (const CallID& id)
yanmorin's avatar
   
yanmorin committed
493
{
494

Emmanuel Milou's avatar
Emmanuel Milou committed
495
496
497
    AccountID accountid;
    bool returnValue, rec;
    std::string codecName;
498
    CallID call_id, current_call_id;
499

500
    stopTone (false);
501

502
    call_id = id;
503
    current_call_id = getCurrentCallId();
Emmanuel Milou's avatar
Emmanuel Milou committed
504
    //Place current call on hold if it isn't
505

506
507
    if (hasCurrentCall() && !participToConference(current_call_id)) 
    {
508
        _debug ("Put the current call (ID=%s) on hold\n", getCurrentCallId().c_str());
509
        onHoldCall (current_call_id);
Emmanuel Milou's avatar
Emmanuel Milou committed
510
    }
511

512
513
    switchCall(id);

Emmanuel Milou's avatar
Emmanuel Milou committed
514
515
516
    /* Direct IP to IP call */
    if (getConfigFromCall (id) == Call::IPtoIP) {
        rec = SIPVoIPLink::instance (AccountNULL)-> isRecording (id);
517
        returnValue = SIPVoIPLink::instance (AccountNULL)-> offhold (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
518
    }
alexandresavard's avatar
alexandresavard committed
519

Emmanuel Milou's avatar
Emmanuel Milou committed
520
    /* Classic call, attached to an account */
521
    else {
522
523
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
524
        if (accountid == AccountNULL) {
525
            _debug ("Manager OffHold Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
526
527
            return false;
        }
528
529
530
531
532

        _debug ("Setting OFFHOLD, Account %s, callid %s\n", accountid.c_str(), id.c_str());

        rec = getAccountLink (accountid)->isRecording (id);
        returnValue = getAccountLink (accountid)->offhold (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
533
    }
alexandresavard's avatar
alexandresavard committed
534

535

536
    if (_dbus) {
Emmanuel Milou's avatar
Emmanuel Milou committed
537
        if (rec)
538
            _dbus->getCallManager()->callStateChanged (call_id, "UNHOLD_RECORD");
539
        else
540
            _dbus->getCallManager()->callStateChanged (call_id, "UNHOLD_CURRENT");
541

Emmanuel Milou's avatar
Emmanuel Milou committed
542
    }
543

544
    // switchCall (id);
545

546
    codecName = getCurrentCodecName (id);
547
    // _debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str());
548
549

    if (_dbus) _dbus->getCallManager()->currentSelectedCodec (id,codecName.c_str());
550

Emmanuel Milou's avatar
Emmanuel Milou committed
551
    return returnValue;
jpbl's avatar
jpbl committed
552
553
}

yanmorin's avatar
   
yanmorin committed
554
//THREAD=Main
555
556
bool
ManagerImpl::transferCall (const CallID& id, const std::string& to)
jpbl's avatar
jpbl committed
557
{
Emmanuel Milou's avatar
Emmanuel Milou committed
558
559
    AccountID accountid;
    bool returnValue;
560

561
    stopTone (true);
562

Emmanuel Milou's avatar
Emmanuel Milou committed
563
    /* Direct IP to IP call */
564

Emmanuel Milou's avatar
Emmanuel Milou committed
565
    if (getConfigFromCall (id) == Call::IPtoIP) {
566
        returnValue = SIPVoIPLink::instance (AccountNULL)-> transfer (id, to);
Emmanuel Milou's avatar
Emmanuel Milou committed
567
568
569
    }

    /* Classic call, attached to an account */
570
    else {
571
572
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
573
        if (accountid == AccountNULL) {
574
            _debug ("! Manager Transfer Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
575
576
            return false;
        }
577
578
579
580

        returnValue = getAccountLink (accountid)->transfer (id, to);

        removeCallAccount (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
581
    }
582

583
584
585
586
587
    removeWaitingCall (id);

    switchCall ("");

    if (_dbus) _dbus->getCallManager()->callStateChanged (id, "HUNGUP");
588

Emmanuel Milou's avatar
Emmanuel Milou committed
589
    return returnValue;
jpbl's avatar
jpbl committed
590
591
}

592
593
void ManagerImpl::transferFailed()
{
594
    if (_dbus) _dbus->getCallManager()->transferFailed();
595
596
597
598
}

void ManagerImpl::transferSucceded()
{
599
    if (_dbus) _dbus->getCallManager()->transferSucceded();
600
601
602
603

}


yanmorin's avatar
   
yanmorin committed
604
//THREAD=Main : Call:Incoming
605
bool
yanmorin's avatar
   
yanmorin committed
606
ManagerImpl::refuseCall (const CallID& id)
jpbl's avatar
jpbl committed
607
{
Emmanuel Milou's avatar
Emmanuel Milou committed
608
609
    AccountID accountid;
    bool returnValue;
610

611
612
613
    stopTone (true);

    /* Direct IP to IP call */
Emmanuel Milou's avatar
Emmanuel Milou committed
614
615

    if (getConfigFromCall (id) == Call::IPtoIP) {
616
        returnValue = SIPVoIPLink::instance (AccountNULL)-> refuse (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
617
618
619
    }

    /* Classic call, attached to an account */
620
    else {
621
622
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
623
        if (accountid == AccountNULL) {
624
            _debug ("! Manager OffHold Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
625
626
            return false;
        }
627
628
629
630

        returnValue = getAccountLink (accountid)->refuse (id);

        removeCallAccount (id);
631
632
    }

Emmanuel Milou's avatar
Emmanuel Milou committed
633
634
635
    // if the call was outgoing or established, we didn't refuse it
    // so the method did nothing
    if (returnValue) {
636
637
638
639
640
        removeWaitingCall (id);

        if (_dbus) _dbus->getCallManager()->callStateChanged (id, "HUNGUP");

        switchCall ("");
Emmanuel Milou's avatar
Emmanuel Milou committed
641
    }
642

Emmanuel Milou's avatar
Emmanuel Milou committed
643
    return returnValue;
jpbl's avatar
jpbl committed
644
645
}

646
647

void
648
ManagerImpl::createConference(const CallID& id1, const CallID& id2)
649
650
{
    _debug("ManagerImpl::createConference()\n");
651
652
    
    Conference* conf = new Conference();
653

654
655
    _conferencecall.insert(pair<CallID, Conference*>(id1, conf));
    _conferencecall.insert(pair<CallID, Conference*>(id2, conf));
656
    _conferencemap.insert(pair<CallID, Conference*>(default_conf, conf));
657

658
659
    conf->add(id1);
    conf->add(id2);
660

661
    // broadcast a signal over dbus
662
    _dbus->getCallManager()->conferenceCreated(default_conf);
663

664
665
666
}

void
667
ManagerImpl::removeConference(const ConfID& conference_id)
668
{
669
670
671

    _debug("ManagerImpl::removeConference(%s)\n", conference_id.c_str());

672
673
674
675
    Conference* conf;
    conf = NULL;

    _debug("ManagerImpl:: _conferencemap.size: %i\n", _conferencemap.size());
676
677
    ConferenceMap::iterator iter = _conferencemap.find(conference_id);

678
    if (iter != _conferencemap.end()) {
679
680
681
682
683
684
	_debug("Found conference id %s in conferencemap\n", conference_id.c_str());
        conf = iter->second;
    }

    if(conf == NULL)
	return;
685

686
687
    ConferenceCallMap temp_map = _conferencecall;

688
    _debug("ManagerImpl:: _conferencecall.size: %i\n", _conferencecall.size());
689
    ConferenceCallMap::iterator iter_p = temp_map.begin();
690
691
692
    while (iter_p != temp_map.end()) {

	if(iter_p->second == conf) {
693
	    _debug("ManagerImpl:: remove particiant (%s) from conference %s\n", iter_p->first.c_str(), conference_id.c_str());
694
	    _conferencecall.erase(iter_p->first);
695
	}
696
697

	iter_p++;
698
699
    }

700
701
    

702
703
704
705
706
    _debug("ManagerImpl:: remove conference %s\n", conference_id.c_str());
    if (_conferencemap.erase(conference_id) == 1)
        _debug("ManagerImpl:: conference %s removed succesfully\n", conference_id.c_str());
    else
	_debug("ManagerImpl:: error cannot remove conference id: %s\n", conference_id.c_str());
707

708
    // broadcast a signal over dbus
709
710
    _debug("ManagerImpl:: broadcast call removed on dbus: %s\n", conference_id.c_str());
    _dbus->getCallManager()->conferenceRemoved(conference_id);
711

712
713
}

714
715
716
717
718
719
720
721
722
723
724
725
726
void
ManagerImpl::holdConference(const CallID& id)
{
    
}


void
ManagerImpl::unHoldConference(const CallID& id)
{

}

727
728
729
730
731
732
733
734
735
736
737
738
bool
ManagerImpl::isConference(const CallID& id)
{
    ConferenceMap::iterator iter = _conferencemap.find(id);
    if(iter == _conferencemap.end()) {
	return false;
    }
    else {
	return true;
    }
}

739
740
741
742
bool
ManagerImpl::participToConference(const CallID& call_id)
{
    ConferenceCallMap::iterator iter = _conferencecall.find(call_id);
743
744

    if(iter == _conferencecall.end()) {
745
746
	return false;
    }
747
    else {
748
749
750
	return true;
    }
}
751
752


753
void
754
ManagerImpl::addParticipant(const CallID& call_id, const CallID& conference_id)
755
{
756
757
    _debug("ManagerImpl::addParticipant(%s, %s)\n", call_id.c_str(), conference_id.c_str());
    // _debug("    Current call ID %s\n", getCurrentCallId().c_str());
758

759
760
    std::map<std::string, std::string> call_details = getCallDetails(call_id);

761
    ConferenceMap::iterator iter = _conferencemap.find(conference_id);
762
    std::map<std::string, std::string>::iterator iter_details;
763
764

    if(iter == _conferencemap.end()) {
765

766
	_debug("NO CONFERENCE YET, CREATE ONE\n");
767
	// createConference(call_id, getCurrentCallId());
768

769
	// answerCall(call_id);
770

771
    }
772
773
774
    else {

	_debug("ADD PARTICIPANT TO CONFERENCE\n");
775
	Conference* conf = iter->second;
776

777
778
779
	conf->add(call_id);
	
	_conferencecall.insert(pair<CallID, Conference*>(call_id, conf));
780

781
782
783
784
785
786
787
788
789
790
791
792
793
794
	iter_details = call_details.find("CALL_STATE");

	if (iter_details->second == "HOLD")
	 {
	     _debug("    OFFHOLD %s\n", call_id.c_str());
	     offHoldCall(call_id);
	 }
	 else if(iter_details->second == "INCOMING")
	 {
	     _debug("    ANSWER %s\n", call_id.c_str());
	     answerCall(call_id);
	 }

	_dbus->getCallManager()->conferenceChanged(conference_id);
795
796
    }
    
797
}
798

799

800
801
802
803
804
805
void
ManagerImpl::joinParticipant(const CallID& call_id1, const CallID& call_id2)
{
    _debug("ManagerImpl::joinParticipant(%s, %s)\n", call_id1.c_str(), call_id2.c_str());
    // _debug("    Current call ID %s\n", getCurrentCallId().c_str());

806
807
808
    std::map<std::string, std::string> call1_details = getCallDetails(call_id1);
    std::map<std::string, std::string> call2_details = getCallDetails(call_id2);

809
    ConferenceMap::iterator iter = _conferencemap.find(default_conf);
810
    std::map<std::string, std::string>::iterator iter_details;