managerimpl.cpp 97.6 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
ManagerImpl::hasCurrentCall()
{
189
    _debug ("ManagerImpl::hasCurrentCall current call ID = %s\n", _currentCallId2.c_str());
190
191
192
193
194
195

    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
ManagerImpl::switchCall (const CallID& id)
{
    ost::MutexLock m (_currentCallMutex);
208
    _debug("------------------------- SWITCH %s ---------------------------\n", id.c_str());
209
    _currentCallId2 = id;
jpbl's avatar
jpbl committed
210
211
212
213
214
215
}


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

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

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

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

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

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

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    if (hasCurrentCall()) {
	
	_debug ("ManagerImpl::outgoingCall() Has current call (id %s) put it onhold\n", getCurrentCallId().c_str());	
	// if this is not a conferenceand this and is not a conference participant
	if (!isConference(getCurrentCallId()) && !participToConference(getCurrentCallId()))
	{
	    _debug ("ManagerImpl::outgoingCall() Put the current call (ID=%s) on hold\n", getCurrentCallId().c_str());
	    onHoldCall (getCurrentCallId());
	}
	else 
	{
	    _debug ("ManagerImpl::outgoingCall() Put the current conference (ID=%s) on hold\n", getCurrentCallId().c_str());
	    detachParticipant();
	}
    }

Emmanuel Milou's avatar
Emmanuel Milou committed
253
    if (callConfig == Call::IPtoIP) {
254
        _debug ("ManagerImpl::outgoingCall Start IP to IP call\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
255
        /* We need to retrieve the sip voiplink instance */
256
257
        siplink = SIPVoIPLink::instance ("");

258
        if (siplink->new_ip_to_ip_call (id, to_cleaned)) {
Emmanuel Milou's avatar
Emmanuel Milou committed
259
260
            switchCall (id);
            return true;
261
        } else {
Emmanuel Milou's avatar
Emmanuel Milou committed
262
263
            callFailure (id);
        }
264

Emmanuel Milou's avatar
Emmanuel Milou committed
265
        return false;
266
    }
267

268
269
    if (!accountExists (accountid)) {
        _debug ("! Manager Error: Outgoing Call: account doesn't exist\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
270
271
        return false;
    }
272

273
274
    if (getAccountFromCall (id) != AccountNULL) {
        _debug ("! Manager Error: Outgoing Call: call id already exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
275
276
        return false;
    }
277
278


279
280
281
282
283
284
    _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
285
286
        return true;
    } else {
287
288
        callFailure (id);
        _debug ("! Manager Error: An error occur, the call was not created\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
289
    }
290

Emmanuel Milou's avatar
Emmanuel Milou committed
291
    return false;
jpbl's avatar
jpbl committed
292
293
}

yanmorin's avatar
   
yanmorin committed
294
//THREAD=Main : for outgoing Call
295
296
bool
ManagerImpl::answerCall (const CallID& id)
jpbl's avatar
jpbl committed
297
{
298
299

    _debug("ManagerImpl::answerCall(%s)", id.c_str());
300
301

    stopTone (true);
302

303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
    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");
        }
322
    }
323

324
325
    _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
326

327
    if (lastCall != NULL ) {
328
        if (lastCall->getState() == Call::Active && !participToConference(getCurrentCallId())) {
329
330
331
            _debug ("* Manager Info: there is currently a call, try to hold it\n");
            onHoldCall (getCurrentCallId());
        }
332
333
	else
	{
334
	    _debug("Current call particips to a conference! Do not hold it!\n");
335
	}
336
337
    }

338
    if (!getAccountLink (currentAccountId)->answer (id)) {
339
340
341
342
        // error when receiving...
        removeCallAccount (id);
        return false;
    }
Alexandre Savard's avatar
Alexandre Savard committed
343

344
345
    // if it was waiting, it's waiting no more
    if (_dbus) _dbus->getCallManager()->callStateChanged (id, "CURRENT");
346
347
348
349
        
    std::string codecName = Manager::instance().getCurrentCodecName (id);
    if (_dbus) _dbus->getCallManager()->currentSelectedCodec (id,codecName.c_str());
        
350
    removeWaitingCall (id);
351

352
353
354
    switchCall (id);

    return true;
jpbl's avatar
jpbl committed
355
356
}

yanmorin's avatar
   
yanmorin committed
357
//THREAD=Main
358
359
bool
ManagerImpl::hangupCall (const CallID& id)
jpbl's avatar
jpbl committed
360
{
361
    _debug ("ManagerImpl::hangupCall()\n");
362
363
364
    PulseLayer *pulselayer;
    AccountID accountid;
    bool returnValue;
365
    AudioLayer *audiolayer;
Emmanuel Milou's avatar
Emmanuel Milou committed
366

367
    stopTone (false);
368
    switchCall (id);
yanmorin's avatar
   
yanmorin committed
369

370
    /* Broadcast a signal over DBus */
371

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

375
376
    int nbCalls = getCallList().size();

377
    audiolayer = getAudioDriver();
378
    // stop streamx
379
380
381
    if (! (nbCalls >= 1))
    {
	_debug("ManagerImpl::stop audio stream, ther is only %i call(s) remaining\n", nbCalls);
382
        audiolayer->stopStream();
383
    }
384

Emmanuel Milou's avatar
Emmanuel Milou committed
385
386
    /* Direct IP to IP call */
    if (getConfigFromCall (id) == Call::IPtoIP) {
387
        returnValue = SIPVoIPLink::instance (AccountNULL)->hangup (id);
388
    }
389

Emmanuel Milou's avatar
Emmanuel Milou committed
390
    /* Classic call, attached to an account */
391
    else {
392
393
        accountid = getAccountFromCall (id);

394
395
        if (accountid == AccountNULL) 
	{
396
            _debug ("! Manager Hangup Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
397
398
            return false;
        }
399
400
401
402

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

        removeCallAccount (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
403
    }
404

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

407
    switchCall ("");
408

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

411
    if (_audiodriver->getLayerType() == PULSEAUDIO && getConfigInt (PREFERENCES , CONFIG_PA_VOLUME_CTRL)) {
412
        pulselayer = dynamic_cast<PulseLayer *> (getAudioDriver());
413
414

        if (pulselayer)  pulselayer->restorePulseAppsVolume();
415
    }
416

417
418
419
420
421
    if(participToConference(id))
    {
	removeParticipant(id);
    }

422
    return returnValue;
jpbl's avatar
jpbl committed
423
424
}

Alexandre Savard's avatar
Alexandre Savard committed
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
452
453
454
455
456
457
458
459
460

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++;

	}

    }

461
462
    switchCall ("");

Alexandre Savard's avatar
Alexandre Savard committed
463
464
465
466
    return true;
}


yanmorin's avatar
   
yanmorin committed
467
//THREAD=Main
468
bool
yanmorin's avatar
   
yanmorin committed
469
ManagerImpl::cancelCall (const CallID& id)
jpbl's avatar
jpbl committed
470
{
Emmanuel Milou's avatar
Emmanuel Milou committed
471
472
    AccountID accountid;
    bool returnValue;
yanmorin's avatar
   
yanmorin committed
473

474
    stopTone (true);
475

Emmanuel Milou's avatar
Emmanuel Milou committed
476
    /* Direct IP to IP call */
477

Emmanuel Milou's avatar
Emmanuel Milou committed
478
    if (getConfigFromCall (id) == Call::IPtoIP) {
479
        returnValue = SIPVoIPLink::instance (AccountNULL)->cancel (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
480
481
482
    }

    /* Classic call, attached to an account */
483
    else {
484
485
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
486
        if (accountid == AccountNULL) {
487
            _debug ("! Manager Cancel Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
488
489
            return false;
        }
490
491
492
493

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

        removeCallAccount (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
494
    }
495

Emmanuel Milou's avatar
Emmanuel Milou committed
496
    // it could be a waiting call?
497
498
499
    removeWaitingCall (id);

    switchCall ("");
Emmanuel Milou's avatar
Emmanuel Milou committed
500
501

    return returnValue;
jpbl's avatar
jpbl committed
502
503
}

yanmorin's avatar
   
yanmorin committed
504
//THREAD=Main
505
506
bool
ManagerImpl::onHoldCall (const CallID& id)
jpbl's avatar
jpbl committed
507
{
Emmanuel Milou's avatar
Emmanuel Milou committed
508
509
    AccountID accountid;
    bool returnValue;
510
    CallID call_id;
yanmorin's avatar
   
yanmorin committed
511

512
    stopTone (true);
513

514
515
    call_id = id;

516
    switchCall (id);
517

Emmanuel Milou's avatar
Emmanuel Milou committed
518
    /* Direct IP to IP call */
519

Emmanuel Milou's avatar
Emmanuel Milou committed
520
    if (getConfigFromCall (id) == Call::IPtoIP) {
521
        returnValue = SIPVoIPLink::instance (AccountNULL)-> onhold (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
522
    }
523

Emmanuel Milou's avatar
Emmanuel Milou committed
524
    /* Classic call, attached to an account */
525
    else {
526
527
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
528
        if (accountid == AccountNULL) {
529
            _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
530
531
            return false;
        }
532
533

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

536
537
538
    removeWaitingCall (id);

    switchCall ("");
539

540
    if (_dbus) _dbus->getCallManager()->callStateChanged (call_id, "HOLD");
541

Emmanuel Milou's avatar
Emmanuel Milou committed
542
    return returnValue;
yanmorin's avatar
   
yanmorin committed
543
544
545
}

//THREAD=Main
546
547
bool
ManagerImpl::offHoldCall (const CallID& id)
yanmorin's avatar
   
yanmorin committed
548
{
549

Emmanuel Milou's avatar
Emmanuel Milou committed
550
551
552
    AccountID accountid;
    bool returnValue, rec;
    std::string codecName;
553
    CallID call_id, current_call_id;
554

555
    stopTone (false);
556

557
    call_id = id;
558
    current_call_id = getCurrentCallId();
Emmanuel Milou's avatar
Emmanuel Milou committed
559
    //Place current call on hold if it isn't
560

561
    if (hasCurrentCall()) 
562
    {
563
564
565
566
567
568
569
570
571
572
573
	// if this is not a conferenceand this and is not a conference participant
	if (!isConference(current_call_id) && !participToConference(current_call_id))
	{
	    _debug ("Put the current call (ID=%s) on hold\n", getCurrentCallId().c_str());
	    onHoldCall (current_call_id);
	}
	else 
	{
	    _debug ("Put the current conference (ID=%s) on hold\n", getCurrentCallId().c_str());
	    detachParticipant();
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
574
    }
575

576
577
    switchCall(id);

Emmanuel Milou's avatar
Emmanuel Milou committed
578
579
580
    /* Direct IP to IP call */
    if (getConfigFromCall (id) == Call::IPtoIP) {
        rec = SIPVoIPLink::instance (AccountNULL)-> isRecording (id);
581
        returnValue = SIPVoIPLink::instance (AccountNULL)-> offhold (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
582
    }
alexandresavard's avatar
alexandresavard committed
583

Emmanuel Milou's avatar
Emmanuel Milou committed
584
    /* Classic call, attached to an account */
585
    else {
586
587
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
588
        if (accountid == AccountNULL) {
589
            _debug ("Manager OffHold Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
590
591
            return false;
        }
592
593
594
595
596

        _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
597
    }
alexandresavard's avatar
alexandresavard committed
598

599

600
    if (_dbus) {
Emmanuel Milou's avatar
Emmanuel Milou committed
601
        if (rec)
602
            _dbus->getCallManager()->callStateChanged (call_id, "UNHOLD_RECORD");
603
        else
604
            _dbus->getCallManager()->callStateChanged (call_id, "UNHOLD_CURRENT");
605

Emmanuel Milou's avatar
Emmanuel Milou committed
606
    }
607

608
    // switchCall (id);
609

610
    codecName = getCurrentCodecName (id);
611
    // _debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str());
612
613

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

Emmanuel Milou's avatar
Emmanuel Milou committed
615
    return returnValue;
jpbl's avatar
jpbl committed
616
617
}

yanmorin's avatar
   
yanmorin committed
618
//THREAD=Main
619
620
bool
ManagerImpl::transferCall (const CallID& id, const std::string& to)
jpbl's avatar
jpbl committed
621
{
Emmanuel Milou's avatar
Emmanuel Milou committed
622
623
    AccountID accountid;
    bool returnValue;
624

625
    stopTone (true);
626

Emmanuel Milou's avatar
Emmanuel Milou committed
627
    /* Direct IP to IP call */
628

Emmanuel Milou's avatar
Emmanuel Milou committed
629
    if (getConfigFromCall (id) == Call::IPtoIP) {
630
        returnValue = SIPVoIPLink::instance (AccountNULL)-> transfer (id, to);
Emmanuel Milou's avatar
Emmanuel Milou committed
631
632
633
    }

    /* Classic call, attached to an account */
634
    else {
635
636
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
637
        if (accountid == AccountNULL) {
638
            _debug ("! Manager Transfer Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
639
640
            return false;
        }
641
642
643
644

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

        removeCallAccount (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
645
    }
646

647
648
649
650
651
    removeWaitingCall (id);

    switchCall ("");

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

Emmanuel Milou's avatar
Emmanuel Milou committed
653
    return returnValue;
jpbl's avatar
jpbl committed
654
655
}

656
657
void ManagerImpl::transferFailed()
{
658
    if (_dbus) _dbus->getCallManager()->transferFailed();
659
660
661
662
}

void ManagerImpl::transferSucceded()
{
663
    if (_dbus) _dbus->getCallManager()->transferSucceded();
664
665
666
667

}


yanmorin's avatar
   
yanmorin committed
668
//THREAD=Main : Call:Incoming
669
bool
yanmorin's avatar
   
yanmorin committed
670
ManagerImpl::refuseCall (const CallID& id)
jpbl's avatar
jpbl committed
671
{
Emmanuel Milou's avatar
Emmanuel Milou committed
672
673
    AccountID accountid;
    bool returnValue;
674

675
676
677
    stopTone (true);

    /* Direct IP to IP call */
Emmanuel Milou's avatar
Emmanuel Milou committed
678
679

    if (getConfigFromCall (id) == Call::IPtoIP) {
680
        returnValue = SIPVoIPLink::instance (AccountNULL)-> refuse (id);
Emmanuel Milou's avatar
Emmanuel Milou committed
681
682
683
    }

    /* Classic call, attached to an account */
684
    else {
685
686
        accountid = getAccountFromCall (id);

Emmanuel Milou's avatar
Emmanuel Milou committed
687
        if (accountid == AccountNULL) {
688
            _debug ("! Manager OffHold Call: Call doesn't exists\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
689
690
            return false;
        }
691
692
693
694

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

        removeCallAccount (id);
695
696
    }

Emmanuel Milou's avatar
Emmanuel Milou committed
697
698
699
    // if the call was outgoing or established, we didn't refuse it
    // so the method did nothing
    if (returnValue) {
700
701
702
703
704
        removeWaitingCall (id);

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

        switchCall ("");
Emmanuel Milou's avatar
Emmanuel Milou committed
705
    }
706

Emmanuel Milou's avatar
Emmanuel Milou committed
707
    return returnValue;
jpbl's avatar
jpbl committed
708
709
}

710
711

void
712
ManagerImpl::createConference(const CallID& id1, const CallID& id2)
713
714
{
    _debug("ManagerImpl::createConference()\n");
715
716
    
    Conference* conf = new Conference();
717

718
719
    _conferencecall.insert(pair<CallID, Conference*>(id1, conf));
    _conferencecall.insert(pair<CallID, Conference*>(id2, conf));
720
    _conferencemap.insert(pair<CallID, Conference*>(default_conf, conf));
721

722
723
    conf->add(id1);
    conf->add(id2);
724

725
    // broadcast a signal over dbus
726
    _dbus->getCallManager()->conferenceCreated(default_conf);
727

728
729
730
}

void
731
ManagerImpl::removeConference(const ConfID& conference_id)
732
{
733
734
735

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

736
737
738
739
    Conference* conf;
    conf = NULL;

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

742
    if (iter != _conferencemap.end()) {
743
744
745
746
747
748
	_debug("Found conference id %s in conferencemap\n", conference_id.c_str());
        conf = iter->second;
    }

    if(conf == NULL)
	return;
749

750
751
    ConferenceCallMap temp_map = _conferencecall;

752
    _debug("ManagerImpl:: _conferencecall.size: %i\n", _conferencecall.size());
753
    ConferenceCallMap::iterator iter_p = temp_map.begin();
754
755
756
    while (iter_p != temp_map.end()) {

	if(iter_p->second == conf) {
757
	    _debug("ManagerImpl:: remove particiant (%s) from conference %s\n", iter_p->first.c_str(), conference_id.c_str());
758
	    _conferencecall.erase(iter_p->first);
759
	}
760
761

	iter_p++;
762
763
    }

764
765
    

766
767
768
769
770
    _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());
771

772
    // broadcast a signal over dbus
773
774
    _debug("ManagerImpl:: broadcast call removed on dbus: %s\n", conference_id.c_str());
    _dbus->getCallManager()->conferenceRemoved(conference_id);
775

776
777
}

778
779
780
void
ManagerImpl::holdConference(const CallID& id)
{
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
    _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())
	{
798
	    _debug("ManagerImpl::holdConference participant %s\n", iter_participant->first.c_str());
799
800
801
802
	    currentAccountId = getAccountFromCall (iter_participant->first);
	    call = getAccountLink (currentAccountId)->getCall (iter_participant->first);

	    if(call->getConfId() == id)
803
804
	    {
		switchCall(iter_participant->first);
805
	        onHoldCall (iter_participant->first);
806
	    }
807
808
809
810
811
812
813

	    iter_participant++;

	}

    }

814
815
816
817
818
819
820
821
    
}


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

822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
    _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())
	{
839
	    _debug("ManagerImpl::unholdConference participant %s\n", iter_participant->first.c_str());
840
841
842
843
844
845
846
847
848
849
850
851
	    currentAccountId = getAccountFromCall (iter_participant->first);
	    call = getAccountLink (currentAccountId)->getCall (iter_participant->first);

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

	    iter_participant++;

	}

    }

852
853
}

854
855
856
857
858
859
860
861
862
863
864
865
bool
ManagerImpl::isConference(const CallID& id)
{
    ConferenceMap::iterator iter = _conferencemap.find(id);
    if(iter == _conferencemap.end()) {
	return false;
    }
    else {
	return true;
    }
}

866
867
868
869
bool
ManagerImpl::participToConference(const CallID& call_id)
{
    ConferenceCallMap::iterator iter = _conferencecall.find(call_id);
870
871

    if(iter == _conferencecall.end()) {
872
873
	return false;
    }
874
    else {
875
876
877
	return true;
    }
}
878
879