managerimpl.cpp 95.9 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
}

Alexandre Savard's avatar
Alexandre Savard committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

bool
ManagerImpl::hangupConference (const ConfID& id)
{
    _debug ("ManagerImpl::hangupConference()\n");

    Conference *conf;
    ConferenceMap::iterator iter_conf = _conferencemap.find(id);

    ConferenceCallMap tempmap = _conferencecall;

    AccountID currentAccountId;

    Call* call = NULL;

    if(iter_conf != _conferencemap.end())
    {
	conf = iter_conf->second;
 
	ConferenceCallMap::iterator iter_participant = tempmap.begin();

	while(iter_participant != tempmap.end())
	{
	    _debug("ManagerImpl::hangupConference participant %s\n", iter_participant->first.c_str());
	    currentAccountId = getAccountFromCall (iter_participant->first);
	    call = getAccountLink (currentAccountId)->getCall (iter_participant->first);

	    if(call->getConfId() == id)
	        hangupCall (iter_participant->first);

	    iter_participant++;

	}

    }

    return true;
}


yanmorin's avatar
   
yanmorin committed
452
//THREAD=Main
453
bool
yanmorin's avatar
   
yanmorin committed
454
ManagerImpl::cancelCall (const CallID& id)
jpbl's avatar
jpbl committed
455
{
Emmanuel Milou's avatar
Emmanuel Milou committed
456
457
    AccountID accountid;
    bool returnValue;
yanmorin's avatar
   
yanmorin committed
458

459
    stopTone (true);
460

Emmanuel Milou's avatar
Emmanuel Milou committed
461
    /* Direct IP to IP call */
462

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

    /* Classic call, attached to an account */
468
    else {
469
470
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
471
        if (accountid == AccountNULL) {
472
            _debug ("! Manager Cancel Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
473
474
            return false;
        }
475
476
477
478

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

        removeCallAccount (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
479
    }
480

Emmanuel Milou's avatar
Emmanuel Milou committed
481
    // it could be a waiting call?
482
483
484
    removeWaitingCall (id);

    switchCall ("");
Emmanuel Milou's avatar
Emmanuel Milou committed
485
486

    return returnValue;
jpbl's avatar
jpbl committed
487
488
}

yanmorin's avatar
   
yanmorin committed
489
//THREAD=Main
490
491
bool
ManagerImpl::onHoldCall (const CallID& id)
jpbl's avatar
jpbl committed
492
{
Emmanuel Milou's avatar
Emmanuel Milou committed
493
494
    AccountID accountid;
    bool returnValue;
495
    CallID call_id;
yanmorin's avatar
   
yanmorin committed
496

497
    stopTone (true);
498

499
500
    call_id = id;

501
    switchCall (id);
502

Emmanuel Milou's avatar
Emmanuel Milou committed
503
    /* Direct IP to IP call */
504

Emmanuel Milou's avatar
Emmanuel Milou committed
505
    if (getConfigFromCall (id) == Call::IPtoIP) {
506
        returnValue = SIPVoIPLink::instance (AccountNULL)-> onhold (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
507
    }
508

Emmanuel Milou's avatar
Emmanuel Milou committed
509
    /* Classic call, attached to an account */
510
    else {
511
512
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
513
        if (accountid == AccountNULL) {
514
            _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
515
516
            return false;
        }
517
518

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

521
522
523
    removeWaitingCall (id);

    switchCall ("");
524

525
    if (_dbus) _dbus->getCallManager()->callStateChanged (call_id, "HOLD");
526

Emmanuel Milou's avatar
Emmanuel Milou committed
527
    return returnValue;
yanmorin's avatar
   
yanmorin committed
528
529
530
}

//THREAD=Main
531
532
bool
ManagerImpl::offHoldCall (const CallID& id)
yanmorin's avatar
   
yanmorin committed
533
{
534

Emmanuel Milou's avatar
Emmanuel Milou committed
535
536
537
    AccountID accountid;
    bool returnValue, rec;
    std::string codecName;
538
    CallID call_id, current_call_id;
539

540
    stopTone (false);
541

542
    call_id = id;
543
    current_call_id = getCurrentCallId();
Emmanuel Milou's avatar
Emmanuel Milou committed
544
    //Place current call on hold if it isn't
545

546
547
    if (hasCurrentCall() && !participToConference(current_call_id)) 
    {
548
        _debug ("Put the current call (ID=%s) on hold\n", getCurrentCallId().c_str());
549
        onHoldCall (current_call_id);
Emmanuel Milou's avatar
Emmanuel Milou committed
550
    }
551

552
553
    switchCall(id);

Emmanuel Milou's avatar
Emmanuel Milou committed
554
555
556
    /* Direct IP to IP call */
    if (getConfigFromCall (id) == Call::IPtoIP) {
        rec = SIPVoIPLink::instance (AccountNULL)-> isRecording (id);
557
        returnValue = SIPVoIPLink::instance (AccountNULL)-> offhold (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
558
    }
alexandresavard's avatar
alexandresavard committed
559

Emmanuel Milou's avatar
Emmanuel Milou committed
560
    /* Classic call, attached to an account */
561
    else {
562
563
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
564
        if (accountid == AccountNULL) {
565
            _debug ("Manager OffHold Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
566
567
            return false;
        }
568
569
570
571
572

        _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
573
    }
alexandresavard's avatar
alexandresavard committed
574

575

576
    if (_dbus) {
Emmanuel Milou's avatar
Emmanuel Milou committed
577
        if (rec)
578
            _dbus->getCallManager()->callStateChanged (call_id, "UNHOLD_RECORD");
579
        else
580
            _dbus->getCallManager()->callStateChanged (call_id, "UNHOLD_CURRENT");
581

Emmanuel Milou's avatar
Emmanuel Milou committed
582
    }
583

584
    // switchCall (id);
585

586
    codecName = getCurrentCodecName (id);
587
    // _debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str());
588
589

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

Emmanuel Milou's avatar
Emmanuel Milou committed
591
    return returnValue;
jpbl's avatar
jpbl committed
592
593
}

yanmorin's avatar
   
yanmorin committed
594
//THREAD=Main
595
596
bool
ManagerImpl::transferCall (const CallID& id, const std::string& to)
jpbl's avatar
jpbl committed
597
{
Emmanuel Milou's avatar
Emmanuel Milou committed
598
599
    AccountID accountid;
    bool returnValue;
600

601
    stopTone (true);
602

Emmanuel Milou's avatar
Emmanuel Milou committed
603
    /* Direct IP to IP call */
604

Emmanuel Milou's avatar
Emmanuel Milou committed
605
    if (getConfigFromCall (id) == Call::IPtoIP) {
606
        returnValue = SIPVoIPLink::instance (AccountNULL)-> transfer (id, to);
Emmanuel Milou's avatar
Emmanuel Milou committed
607
608
609
    }

    /* Classic call, attached to an account */
610
    else {
611
612
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
613
        if (accountid == AccountNULL) {
614
            _debug ("! Manager Transfer Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
615
616
            return false;
        }
617
618
619
620

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

        removeCallAccount (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
621
    }
622

623
624
625
626
627
    removeWaitingCall (id);

    switchCall ("");

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

Emmanuel Milou's avatar
Emmanuel Milou committed
629
    return returnValue;
jpbl's avatar
jpbl committed
630
631
}

632
633
void ManagerImpl::transferFailed()
{
634
    if (_dbus) _dbus->getCallManager()->transferFailed();
635
636
637
638
}

void ManagerImpl::transferSucceded()
{
639
    if (_dbus) _dbus->getCallManager()->transferSucceded();
640
641
642
643

}


yanmorin's avatar
   
yanmorin committed
644
//THREAD=Main : Call:Incoming
645
bool
yanmorin's avatar
   
yanmorin committed
646
ManagerImpl::refuseCall (const CallID& id)
jpbl's avatar
jpbl committed
647
{
Emmanuel Milou's avatar
Emmanuel Milou committed
648
649
    AccountID accountid;
    bool returnValue;
650

651
652
653
    stopTone (true);

    /* Direct IP to IP call */
Emmanuel Milou's avatar
Emmanuel Milou committed
654
655

    if (getConfigFromCall (id) == Call::IPtoIP) {
656
        returnValue = SIPVoIPLink::instance (AccountNULL)-> refuse (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
657
658
659
    }

    /* Classic call, attached to an account */
660
    else {
661
662
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
663
        if (accountid == AccountNULL) {
664
            _debug ("! Manager OffHold Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
665
666
            return false;
        }
667
668
669
670

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

        removeCallAccount (id);
671
672
    }

Emmanuel Milou's avatar
Emmanuel Milou committed
673
674
675
    // if the call was outgoing or established, we didn't refuse it
    // so the method did nothing
    if (returnValue) {
676
677
678
679
680
        removeWaitingCall (id);

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

        switchCall ("");
Emmanuel Milou's avatar
Emmanuel Milou committed
681
    }
682

Emmanuel Milou's avatar
Emmanuel Milou committed
683
    return returnValue;
jpbl's avatar
jpbl committed
684
685
}

686
687

void
688
ManagerImpl::createConference(const CallID& id1, const CallID& id2)
689
690
{
    _debug("ManagerImpl::createConference()\n");
691
692
    
    Conference* conf = new Conference();
693

694
695
    _conferencecall.insert(pair<CallID, Conference*>(id1, conf));
    _conferencecall.insert(pair<CallID, Conference*>(id2, conf));
696
    _conferencemap.insert(pair<CallID, Conference*>(default_conf, conf));
697

698
699
    conf->add(id1);
    conf->add(id2);
700

701
    // broadcast a signal over dbus
702
    _dbus->getCallManager()->conferenceCreated(default_conf);
703

704
705
706
}

void
707
ManagerImpl::removeConference(const ConfID& conference_id)
708
{
709
710
711

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

712
713
714
715
    Conference* conf;
    conf = NULL;

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

718
    if (iter != _conferencemap.end()) {
719
720
721
722
723
724
	_debug("Found conference id %s in conferencemap\n", conference_id.c_str());
        conf = iter->second;
    }

    if(conf == NULL)
	return;
725

726
727
    ConferenceCallMap temp_map = _conferencecall;

728
    _debug("ManagerImpl:: _conferencecall.size: %i\n", _conferencecall.size());
729
    ConferenceCallMap::iterator iter_p = temp_map.begin();
730
731
732
    while (iter_p != temp_map.end()) {

	if(iter_p->second == conf) {
733
	    _debug("ManagerImpl:: remove particiant (%s) from conference %s\n", iter_p->first.c_str(), conference_id.c_str());
734
	    _conferencecall.erase(iter_p->first);
735
	}
736
737

	iter_p++;
738
739
    }

740
741
    

742
743
744
745
746
    _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());
747

748
    // broadcast a signal over dbus
749
750
    _debug("ManagerImpl:: broadcast call removed on dbus: %s\n", conference_id.c_str());
    _dbus->getCallManager()->conferenceRemoved(conference_id);
751

752
753
}

754
755
756
void
ManagerImpl::holdConference(const CallID& id)
{
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
    _debug ("ManagerImpl::holdConference()\n");

    Conference *conf;
    ConferenceMap::iterator iter_conf = _conferencemap.find(id);

    AccountID currentAccountId;

    Call* call = NULL;

    if(iter_conf != _conferencemap.end())
    {
	conf = iter_conf->second;
 
	ConferenceCallMap::iterator iter_participant = _conferencecall.begin();

	while(iter_participant != _conferencecall.end())
	{
	    _debug("ManagerImpl::hangupConference participant %s\n", iter_participant->first.c_str());
	    currentAccountId = getAccountFromCall (iter_participant->first);
	    call = getAccountLink (currentAccountId)->getCall (iter_participant->first);

	    if(call->getConfId() == id)
	        onHoldCall (iter_participant->first);

	    iter_participant++;

	}

    }

787
788
789
790
791
792
793
794
    
}


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

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
    _debug ("ManagerImpl::unHoldConference()\n");

    Conference *conf;
    ConferenceMap::iterator iter_conf = _conferencemap.find(id);

    AccountID currentAccountId;

    Call* call = NULL;

    if(iter_conf != _conferencemap.end())
    {
	conf = iter_conf->second;
 
	ConferenceCallMap::iterator iter_participant = _conferencecall.begin();

	while(iter_participant != _conferencecall.end())
	{
	    _debug("ManagerImpl::hangupConference participant %s\n", iter_participant->first.c_str());
	    currentAccountId = getAccountFromCall (iter_participant->first);
	    call = getAccountLink (currentAccountId)->getCall (iter_participant->first);

	    if(call->getConfId() == id)
	        offHoldCall (iter_participant->first);

	    iter_participant++;

	}

    }

825
826
}

827
828
829
830
831
832
833
834
835
836
837
838
bool
ManagerImpl::isConference(const CallID& id)
{
    ConferenceMap::iterator iter = _conferencemap.find(id);
    if(iter == _conferencemap.end()) {
	return false;
    }
    else {
	return true;
    }
}

839
840
841
842
bool
ManagerImpl::participToConference(const CallID& call_id)
{
    ConferenceCallMap::iterator iter = _conferencecall.find(call_id);
843
844

    if(iter == _conferencecall.end()) {
845
846
	return false;
    }
847
    else {
848
849
850
	return true;
    }
}
851
852


853
void
854
ManagerImpl::addParticipant(const CallID& call_id, const CallID& conference_id)
855
{
856
857
    _debug("ManagerImpl::addParticipant(%s, %s)\n", call_id.c_str(), conference_id.c_str());
    // _debug("    Current call ID %s\n", getCurrentCallId().c_str());
858

859
860
    std::map<std::string, std::string> call_details = getCallDetails(call_id);

861
    ConferenceMap::iterator iter = _conferencemap.find(conference_id);
862
    std::map<std::string, std::string>::iterator iter_details;
863
864

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

866
	_debug("NO CONFERENCE YET, CREATE ONE\n");
867
	// createConference(call_id, getCurrentCallId());
868

869
	// answerCall(call_id);