~ubuntu-branches/debian/sid/sflphone/sid

« back to all changes in this revision

Viewing changes to daemon/src/managerimpl.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
 
2
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3
3
 *  Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
4
4
 *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
5
5
 *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
40
40
#include "managerimpl.h"
41
41
#include "account_schema.h"
42
42
 
43
 
#include "dbus/callmanager.h"
44
43
#include "global.h"
45
44
#include "fileutils.h"
46
45
#include "map_utils.h"
48
47
#include "sip/sipaccount.h"
49
48
#include "sip/sipcall.h"
50
49
#include "im/instant_messaging.h"
 
50
#include "sip/sippresence.h"
51
51
 
52
52
#if HAVE_IAX
53
53
#include "iax/iaxaccount.h"
58
58
#include "numbercleaner.h"
59
59
#include "config/yamlparser.h"
60
60
#include "config/yamlemitter.h"
 
61
 
 
62
#ifndef __ANDROID__
61
63
#include "audio/alsa/alsalayer.h"
 
64
#endif
 
65
 
62
66
#include "audio/sound/tonelist.h"
63
67
#include "audio/sound/audiofile.h"
64
68
#include "audio/sound/dtmf.h"
65
69
#include "history/historynamecache.h"
 
70
#include "history/history.h"
66
71
#include "manager.h"
67
72
 
68
 
#include "dbus/configurationmanager.h"
 
73
#include "client/configurationmanager.h"
 
74
#include "client/callmanager.h"
 
75
 
69
76
#ifdef SFL_VIDEO
70
 
#include "dbus/video_controls.h"
 
77
#include "client/video_controls.h"
71
78
#endif
72
79
 
73
80
#include "conference.h"
74
 
#include "scoped_lock.h"
75
81
 
76
82
#include <cerrno>
77
83
#include <algorithm>
78
84
#include <ctime>
79
85
#include <cstdlib>
80
86
#include <iostream>
81
 
#include <tr1/functional>
82
 
#include <iterator>
83
87
#include <fstream>
84
88
#include <sstream>
85
89
#include <sys/types.h> // mkdir(2)
88
92
ManagerImpl::ManagerImpl() :
89
93
    preferences(), voipPreferences(),
90
94
    hookPreference(),  audioPreference(), shortcutPreferences(),
91
 
    hasTriedToRegister_(false), audioCodecFactory(), dbus_(), config_(),
 
95
    hasTriedToRegister_(false), audioCodecFactory(), client_(),
 
96
        config_(),
92
97
    currentCallId_(), currentCallMutex_(), audiodriver_(0), dtmfKey_(),
93
98
    toneMutex_(), telephoneTone_(), audiofile_(), audioLayerMutex_(),
94
 
    waitingCall_(), waitingCallMutex_(), nbIncomingWaitingCall_(0), path_(),
 
99
    waitingCalls_(), waitingCallsMutex_(), path_(),
95
100
    IPToIPMap_(), mainBuffer_(), conferenceMap_(), history_(), finished_(false)
96
101
{
97
 
    pthread_mutex_init(&currentCallMutex_, NULL);
98
 
    pthread_mutex_init(&toneMutex_, NULL);
99
 
    pthread_mutex_init(&audioLayerMutex_, NULL);
100
 
    pthread_mutex_init(&waitingCallMutex_, NULL);
101
102
    // initialize random generator for call id
102
 
    srand(time(NULL));
 
103
    srand(time(nullptr));
103
104
}
104
105
 
105
106
ManagerImpl::~ManagerImpl()
106
107
{
107
 
    // destroy in reverse order of initialization
108
 
    pthread_mutex_destroy(&waitingCallMutex_);
109
 
    pthread_mutex_destroy(&audioLayerMutex_);
110
 
    pthread_mutex_destroy(&toneMutex_);
111
 
    pthread_mutex_destroy(&currentCallMutex_);
112
108
}
113
109
 
114
110
namespace {
115
 
    // Creates a backup of the file at "path" with a .bak suffix appended
116
 
    void make_backup(const std::string &path)
 
111
 
 
112
    void copy_over(const std::string &srcPath, const std::string &destPath)
117
113
    {
118
 
        const std::string backup_path(path + ".bak");
119
 
        std::ifstream src(path.c_str());
120
 
        std::ofstream dest(backup_path.c_str());
 
114
        std::ifstream src(srcPath.c_str());
 
115
        std::ofstream dest(destPath.c_str());
121
116
        dest << src.rdbuf();
122
117
        src.close();
123
118
        dest.close();
124
119
    }
 
120
    // Creates a backup of the file at "path" with a .bak suffix appended
 
121
    void make_backup(const std::string &path)
 
122
    {
 
123
        const std::string backup_path(path + ".bak");
 
124
        copy_over(path, backup_path);
 
125
    }
 
126
    // Restore last backup of the configuration file
 
127
    void restore_backup(const std::string &path)
 
128
    {
 
129
        const std::string backup_path(path + ".bak");
 
130
        copy_over(backup_path, path);
 
131
    }
125
132
}
126
133
 
127
 
 
128
 
void ManagerImpl::init(const std::string &config_file)
 
134
bool ManagerImpl::parseConfiguration()
129
135
{
130
 
    path_ = config_file.empty() ? createConfigFile() : config_file;
131
 
    DEBUG("Configuration file path: %s", path_.c_str());
 
136
    bool result = true;
132
137
 
133
 
    bool no_errors = true;
 
138
    FILE *file = fopen(path_.c_str(), "rb");
134
139
 
135
140
    try {
136
 
        FILE *file = fopen(path_.c_str(), "rb");
137
 
 
138
141
        if (file) {
139
142
            Conf::YamlParser parser(file);
140
143
            parser.serializeEvents();
144
147
            fclose(file);
145
148
            if (error_count > 0) {
146
149
                WARN("Errors while parsing %s", path_.c_str());
147
 
                no_errors = false;
 
150
                result = false;
148
151
            }
149
152
        } else {
150
153
            WARN("Config file not found: creating default account map");
151
154
            loadDefaultAccountMap();
152
155
        }
153
156
    } catch (const Conf::YamlParserException &e) {
 
157
        // we only want to close the local file here and then rethrow the exception
 
158
        fclose(file);
 
159
        throw;
 
160
    }
 
161
 
 
162
    return result;
 
163
}
 
164
 
 
165
void ManagerImpl::init(const std::string &config_file)
 
166
{
 
167
    path_ = config_file.empty() ? retrieveConfigPath() : config_file;
 
168
    DEBUG("Configuration file path: %s", path_.c_str());
 
169
 
 
170
    bool no_errors = true;
 
171
 
 
172
    // manager can restart without being recreated (android)
 
173
    finished_ = false;
 
174
 
 
175
    try {
 
176
        no_errors = parseConfiguration();
 
177
    } catch (const Conf::YamlParserException &e) {
154
178
        ERROR("%s", e.what());
155
179
        no_errors = false;
156
180
    }
157
181
 
158
182
    // always back up last error-free configuration
159
 
    if (no_errors)
 
183
    if (no_errors) {
160
184
        make_backup(path_);
 
185
    } else {
 
186
        // restore previous configuration
 
187
        WARN("Restoring last working configuration");
 
188
        try {
 
189
            // remove accounts from broken configuration
 
190
            removeAccounts();
 
191
            restore_backup(path_);
 
192
            parseConfiguration();
 
193
        } catch (const Conf::YamlParserException &e) {
 
194
            ERROR("%s", e.what());
 
195
            WARN("Restoring backup failed, creating default account map");
 
196
            loadDefaultAccountMap();
 
197
        }
 
198
    }
161
199
 
162
200
    initAudioDriver();
163
201
 
164
202
    {
165
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
203
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
166
204
        if (audiodriver_) {
167
205
            {
168
 
                sfl::ScopedLock toneLock(toneMutex_);
 
206
                std::lock_guard<std::mutex> toneLock(toneMutex_);
169
207
                telephoneTone_.reset(new TelephoneTone(preferences.getZoneToneChoice(), audiodriver_->getSampleRate()));
170
208
            }
171
209
            dtmfKey_.reset(new DTMF(getMainBuffer().getInternalSamplingRate()));
176
214
    registerAccounts();
177
215
}
178
216
 
179
 
void ManagerImpl::run()
180
 
{
181
 
    DEBUG("Starting DBus event loop");
182
 
    dbus_.exec();
 
217
void ManagerImpl::setPath(const std::string &path) {
 
218
        history_.setPath(path);
 
219
}
 
220
 
 
221
#if HAVE_DBUS
 
222
int ManagerImpl::run()
 
223
{
 
224
    DEBUG("Starting client event loop");
 
225
    return client_.event_loop();
 
226
}
 
227
#endif
 
228
 
 
229
int ManagerImpl::interrupt()
 
230
{
 
231
    return client_.exit();
183
232
}
184
233
 
185
234
void ManagerImpl::finish()
188
237
        return;
189
238
 
190
239
    finished_ = true;
191
 
    // Unset signal handlers
192
 
    signal(SIGHUP, SIG_DFL);
193
 
    signal(SIGINT, SIG_DFL);
194
 
    signal(SIGTERM, SIG_DFL);
195
 
 
196
 
    std::vector<std::string> callList(getCallList());
197
 
    DEBUG("Hangup %zu remaining call(s)", callList.size());
198
 
 
199
 
    for (std::vector<std::string>::iterator iter = callList.begin();
200
 
            iter != callList.end(); ++iter)
201
 
        hangupCall(*iter);
202
 
 
203
 
    saveConfig();
204
 
 
205
 
    unregisterAllAccounts();
206
 
 
207
 
    SIPVoIPLink::destroy();
 
240
 
 
241
    try {
 
242
 
 
243
        std::vector<std::string> callList(getCallList());
 
244
        DEBUG("Hangup %zu remaining call(s)", callList.size());
 
245
 
 
246
        for (const auto &item : callList)
 
247
            hangupCall(item);
 
248
 
 
249
        saveConfig();
 
250
 
 
251
        unregisterAllAccounts();
 
252
 
 
253
        SIPVoIPLink::destroy();
208
254
#if HAVE_IAX
209
 
    IAXVoIPLink::unloadAccountMap();
 
255
        IAXVoIPLink::unloadAccountMap();
210
256
#endif
211
257
 
212
 
    {
213
 
        sfl::ScopedLock lock(audioLayerMutex_);
214
 
 
215
 
        delete audiodriver_;
216
 
        audiodriver_ = NULL;
 
258
        {
 
259
            std::lock_guard<std::mutex> lock(audioLayerMutex_);
 
260
 
 
261
            delete audiodriver_;
 
262
            audiodriver_ = nullptr;
 
263
        }
 
264
 
 
265
        saveHistory();
 
266
    } catch (const VoipLinkException &err) {
 
267
        ERROR("%s", err.what());
217
268
    }
218
 
 
219
 
    dbus_.exit();
220
269
}
221
270
 
222
271
bool ManagerImpl::isCurrentCall(const std::string& callId) const
242
291
 
243
292
void ManagerImpl::switchCall(const std::string& id)
244
293
{
245
 
    sfl::ScopedLock m(currentCallMutex_);
 
294
    std::lock_guard<std::mutex> m(currentCallMutex_);
246
295
    DEBUG("----- Switch current call id to %s -----", id.c_str());
247
296
    currentCallId_ = id;
248
297
}
322
371
        return false;
323
372
    }
324
373
 
325
 
    getMainBuffer().dumpInfo();
326
 
 
327
374
    return true;
328
375
}
329
376
 
333
380
    bool result = true;
334
381
    Call *call = getCallFromCallID(call_id);
335
382
 
336
 
    if (call == NULL) {
 
383
    if (call == nullptr) {
337
384
        ERROR("Call %s is NULL", call_id.c_str());
338
385
        return false;
339
386
    }
341
388
    // If sflphone is ringing
342
389
    stopTone();
343
390
 
344
 
    // set playback mode to VOICE
345
 
    AudioLayer *al = getAudioDriver();
346
 
    if(al) al->setPlaybackMode(AudioLayer::VOICE);
347
 
 
348
391
    // store the current call id
349
392
    std::string current_call_id(getCurrentCallId());
350
393
 
384
427
    // Connect streams
385
428
    addStream(call_id);
386
429
 
387
 
    getMainBuffer().dumpInfo();
388
 
 
389
430
    // Start recording if set in preference
390
431
    if (audioPreference.getIsAlwaysRecording())
391
 
        setRecordingCall(call_id);
392
 
 
393
 
    // update call state on client side
394
 
    dbus_.getCallManager()->callStateChanged(call_id, "CURRENT");
 
432
        toggleRecordingCall(call_id);
 
433
 
 
434
    client_.getCallManager()->callStateChanged(call_id, "CURRENT");
 
435
 
395
436
    return result;
396
437
}
397
438
 
398
439
void ManagerImpl::checkAudio()
399
440
{
400
441
    if (getCallList().empty()) {
401
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
442
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
402
443
        if (audiodriver_)
403
444
            audiodriver_->stopStream();
404
445
    }
 
446
 
405
447
}
406
448
 
407
449
//THREAD=Main
412
454
 
413
455
    stopTone();
414
456
 
415
 
    // set playback mode to NONE
416
 
    AudioLayer *al = getAudioDriver();
417
 
    if(al) al->setPlaybackMode(AudioLayer::NONE);
418
 
 
419
 
    /* Broadcast a signal over DBus */
420
 
    DEBUG("Send DBUS call state change (HUNGUP) for id %s", callId.c_str());
421
 
    dbus_.getCallManager()->callStateChanged(callId, "HUNGUP");
 
457
    DEBUG("Send call state change (HUNGUP) for id %s", callId.c_str());
 
458
    client_.getCallManager()->callStateChanged(callId, "HUNGUP");
422
459
 
423
460
    /* We often get here when the call was hungup before being created */
424
461
    if (not isValidCall(callId) and not isIPToIP(callId)) {
425
462
        DEBUG("Could not hang up call %s, call not valid", callId.c_str());
 
463
        checkAudio();
426
464
        return false;
427
465
    }
428
466
 
462
500
        }
463
501
    }
464
502
 
465
 
    getMainBuffer().dumpInfo();
466
503
    return true;
467
504
}
468
505
 
478
515
        if (conf) {
479
516
            ParticipantSet participants(conf->getParticipantList());
480
517
 
481
 
            for (ParticipantSet::const_iterator iter = participants.begin();
482
 
                    iter != participants.end(); ++iter)
483
 
                hangupCall(*iter);
 
518
            for (const auto &item : participants)
 
519
                hangupCall(item);
484
520
        } else {
485
521
            ERROR("No such conference %s", id.c_str());
486
522
            return false;
489
525
 
490
526
    unsetCurrentCall();
491
527
 
492
 
    getMainBuffer().dumpInfo();
493
 
 
494
528
    return true;
495
529
}
496
530
 
534
568
    if (current_call_id == callId)
535
569
        unsetCurrentCall();
536
570
 
537
 
    dbus_.getCallManager()->callStateChanged(callId, "HOLD");
 
571
    client_.getCallManager()->callStateChanged(callId, "HOLD");
538
572
 
539
 
    getMainBuffer().dumpInfo();
540
573
    return result;
541
574
}
542
575
 
560
593
            detachParticipant(MainBuffer::DEFAULT_ID);
561
594
    }
562
595
 
563
 
    if (isIPToIP(callId))
564
 
        SIPVoIPLink::instance()->offhold(callId);
565
 
    else {
566
 
        /* Classic call, attached to an account */
567
 
        Call * call = getCallFromCallID(callId);
 
596
    try {
 
597
        if (isIPToIP(callId))
 
598
            SIPVoIPLink::instance()->offhold(callId);
 
599
        else {
 
600
            /* Classic call, attached to an account */
 
601
            Call * call = getCallFromCallID(callId);
568
602
 
569
 
        if (call)
570
 
            getAccountLink(call->getAccountId())->offhold(callId);
571
 
        else
572
 
            result = false;
 
603
            if (call)
 
604
                getAccountLink(call->getAccountId())->offhold(callId);
 
605
            else
 
606
                result = false;
 
607
        }
 
608
    } catch (const VoipLinkException &e) {
 
609
        ERROR("%s", e.what());
 
610
        return false;
573
611
    }
574
612
 
575
 
    dbus_.getCallManager()->callStateChanged(callId, "UNHOLD");
 
613
    client_.getCallManager()->callStateChanged(callId, "UNHOLD");
576
614
 
577
615
    if (isConferenceParticipant(callId)) {
578
616
        Call *call = getCallFromCallID(callId);
585
623
 
586
624
    addStream(callId);
587
625
 
588
 
    getMainBuffer().dumpInfo();
589
626
    return result;
590
627
}
591
628
 
613
650
    // remove waiting call in case we make transfer without even answer
614
651
    removeWaitingCall(callId);
615
652
 
616
 
    getMainBuffer().dumpInfo();
617
 
 
618
653
    return true;
619
654
}
620
655
 
621
656
void ManagerImpl::transferFailed()
622
657
{
623
 
    dbus_.getCallManager()->transferFailed();
 
658
    client_.getCallManager()->transferFailed();
624
659
}
625
660
 
626
661
void ManagerImpl::transferSucceeded()
627
662
{
628
 
    dbus_.getCallManager()->transferSucceeded();
 
663
    client_.getCallManager()->transferSucceeded();
629
664
}
630
665
 
631
666
bool ManagerImpl::attendedTransfer(const std::string& transferID, const std::string& targetID)
651
686
    stopTone();
652
687
 
653
688
    if (getCallList().size() <= 1) {
654
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
689
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
655
690
        audiodriver_->stopStream();
656
691
    }
657
692
 
672
707
    }
673
708
 
674
709
    removeWaitingCall(id);
675
 
    dbus_.getCallManager()->callStateChanged(id, "HUNGUP");
 
710
 
 
711
    client_.getCallManager()->callStateChanged(id, "HUNGUP");
676
712
 
677
713
    // Disconnect streams
678
714
    removeStream(id);
679
715
 
680
 
    getMainBuffer().dumpInfo();
681
716
    return true;
682
717
}
683
718
 
694
729
    // Add conference to map
695
730
    conferenceMap_.insert(std::make_pair(conf->getConfID(), conf));
696
731
 
697
 
    // broadcast a signal over dbus
698
 
    dbus_.getCallManager()->conferenceCreated(conf->getConfID());
 
732
    client_.getCallManager()->conferenceCreated(conf->getConfID());
699
733
 
700
734
    return conf;
701
735
}
716
750
        return;
717
751
    }
718
752
 
719
 
    // broadcast a signal over dbus
720
 
    dbus_.getCallManager()->conferenceRemoved(conference_id);
 
753
    client_.getCallManager()->conferenceRemoved(conference_id);
721
754
 
722
755
    // We now need to bind the audio to the remain participant
723
756
 
746
779
{
747
780
    Call *call = getCallFromCallID(call_id);
748
781
    if (!call)
749
 
        return NULL;
 
782
        return nullptr;
750
783
 
751
784
    ConferenceMap::const_iterator iter(conferenceMap_.find(call->getConfId()));
752
785
 
753
786
    if (iter != conferenceMap_.end())
754
787
        return iter->second;
755
788
    else
756
 
        return NULL;
 
789
        return nullptr;
757
790
}
758
791
 
759
792
bool
772
805
 
773
806
    ParticipantSet participants(conf->getParticipantList());
774
807
 
775
 
    for (ParticipantSet::const_iterator iter = participants.begin();
776
 
            iter != participants.end(); ++iter) {
777
 
        switchCall(*iter);
778
 
        onHoldCall(*iter);
 
808
    for (const auto &item : participants) {
 
809
        switchCall(item);
 
810
        onHoldCall(item);
779
811
    }
780
812
 
781
813
    conf->setState(isRec ? Conference::HOLD_REC : Conference::HOLD);
782
 
    dbus_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
 
814
 
 
815
    client_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
 
816
 
783
817
    return true;
784
818
}
785
819
 
799
833
 
800
834
    ParticipantSet participants(conf->getParticipantList());
801
835
 
802
 
    for (ParticipantSet::const_iterator iter = participants.begin(); iter!= participants.end(); ++iter) {
803
 
        Call *call = getCallFromCallID(*iter);
 
836
    for (const auto &item : participants) {
 
837
        Call *call = getCallFromCallID(item);
804
838
        if (call) {
805
839
            // if one call is currently recording, the conference is in state recording
806
840
            isRec |= call->isRecording();
807
841
 
808
 
            switchCall(*iter);
809
 
            offHoldCall(*iter);
 
842
            switchCall(item);
 
843
            offHoldCall(item);
810
844
        }
811
845
    }
812
846
 
813
847
    conf->setState(isRec ? Conference::ACTIVE_ATTACHED_REC : Conference::ACTIVE_ATTACHED);
814
 
    dbus_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
 
848
 
 
849
    client_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
 
850
 
815
851
    return true;
816
852
}
817
853
 
838
874
    }
839
875
 
840
876
    Call *call = getCallFromCallID(callId);
841
 
    if (call == NULL) {
 
877
    if (call == nullptr) {
842
878
        ERROR("Call id %s is not valid", callId.c_str());
843
879
        return false;
844
880
    }
893
929
    if (participants.empty())
894
930
        ERROR("Participant list is empty for this conference");
895
931
 
896
 
    // reset ring buffer for all conference participant
897
 
    // flush conference participants only
898
 
    for (ParticipantSet::const_iterator p = participants.begin();
899
 
            p != participants.end(); ++p)
900
 
        getMainBuffer().flush(*p);
901
 
 
902
 
    getMainBuffer().flush(MainBuffer::DEFAULT_ID);
903
 
 
904
932
    // Connect stream
905
933
    addStream(callId);
906
934
    return true;
919
947
    }
920
948
 
921
949
    {
922
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
950
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
923
951
 
924
952
        ConferenceMap::const_iterator iter = conferenceMap_.find(conference_id);
925
953
 
930
958
 
931
959
        ParticipantSet participants(conf->getParticipantList());
932
960
 
933
 
        for (ParticipantSet::const_iterator iter_p = participants.begin();
934
 
                iter_p != participants.end(); ++iter_p) {
935
 
            getMainBuffer().bindCallID(*iter_p, MainBuffer::DEFAULT_ID);
 
961
        for (const auto &item_p : participants) {
 
962
            getMainBuffer().bindCallID(item_p, MainBuffer::DEFAULT_ID);
936
963
            // Reset ringbuffer's readpointers
937
 
            getMainBuffer().flush(*iter_p);
 
964
            getMainBuffer().flush(item_p);
938
965
        }
939
966
 
940
967
        getMainBuffer().flush(MainBuffer::DEFAULT_ID);
946
973
        else
947
974
            WARN("Invalid conference state while adding main participant");
948
975
 
949
 
        dbus_.getCallManager()->conferenceChanged(conference_id, conf->getStateStr());
 
976
        client_.getCallManager()->conferenceChanged(conference_id, conf->getStateStr());
950
977
    }
951
978
 
952
979
    switchCall(conference_id);
956
983
Call *
957
984
ManagerImpl::getCallFromCallID(const std::string &callID)
958
985
{
959
 
    Call *call = NULL;
 
986
    Call *call = nullptr;
960
987
 
961
988
    call = SIPVoIPLink::instance()->getSipCall(callID);
962
989
#if HAVE_IAX
963
 
    if (call != NULL)
 
990
    if (call != nullptr)
964
991
        return call;
965
992
 
966
993
    call = IAXVoIPLink::getIaxCall(callID);
980
1007
    // Set corresponding conference ids for call 1
981
1008
    Call *call1 = getCallFromCallID(callId1);
982
1009
 
983
 
    if (call1 == NULL) {
 
1010
    if (call1 == nullptr) {
984
1011
        ERROR("Could not find call %s", callId1.c_str());
985
1012
        return false;
986
1013
    }
988
1015
    // Set corresponding conderence details
989
1016
    Call *call2 = getCallFromCallID(callId2);
990
1017
 
991
 
    if (call2 == NULL) {
 
1018
    if (call2 == nullptr) {
992
1019
        ERROR("Could not find call %s", callId2.c_str());
993
1020
        return false;
994
1021
    }
1065
1092
 
1066
1093
    // set recording sampling rate
1067
1094
    {
1068
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
1095
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
1069
1096
        if (audiodriver_)
1070
1097
            conf->setRecordingSmplRate(audiodriver_->getSampleRate());
1071
1098
    }
1072
1099
 
1073
 
    getMainBuffer().dumpInfo();
1074
1100
    return true;
1075
1101
}
1076
1102
 
1086
1112
 
1087
1113
    int successCounter = 0;
1088
1114
 
1089
 
    for (std::vector<std::string>::const_iterator p = participantList.begin();
1090
 
         p != participantList.end(); ++p) {
1091
 
        std::string numberaccount(*p);
 
1115
    for (const auto &p : participantList) {
 
1116
        std::string numberaccount(p);
1092
1117
        std::string tostr(numberaccount.substr(0, numberaccount.find(",")));
1093
1118
        std::string account(numberaccount.substr(numberaccount.find(",") + 1, numberaccount.size()));
1094
1119
 
1106
1131
        if (!callSuccess)
1107
1132
            conf->remove(generatedCallID);
1108
1133
        else {
1109
 
            dbus_.getCallManager()->newCallCreated(account, generatedCallID, tostr);
 
1134
            client_.getCallManager()->newCallCreated(account, generatedCallID, tostr);
1110
1135
            successCounter++;
1111
1136
        }
1112
1137
    }
1114
1139
    // Create the conference if and only if at least 2 calls have been successfully created
1115
1140
    if (successCounter >= 2) {
1116
1141
        conferenceMap_[conf->getConfID()] = conf;
1117
 
        dbus_.getCallManager()->conferenceCreated(conf->getConfID());
 
1142
        client_.getCallManager()->conferenceCreated(conf->getConfID());
1118
1143
 
1119
1144
        {
1120
 
            sfl::ScopedLock lock(audioLayerMutex_);
 
1145
            std::lock_guard<std::mutex> lock(audioLayerMutex_);
1121
1146
 
1122
1147
            if (audiodriver_)
1123
1148
                conf->setRecordingSmplRate(audiodriver_->getSampleRate());
1124
1149
        }
1125
1150
 
1126
 
        getMainBuffer().dumpInfo();
1127
1151
    } else {
1128
1152
        delete conf;
1129
1153
    }
1137
1161
    if (call_id != MainBuffer::DEFAULT_ID) {
1138
1162
        Call *call = getCallFromCallID(call_id);
1139
1163
 
1140
 
        if (call == NULL) {
 
1164
        if (call == nullptr) {
1141
1165
            ERROR("Could not find call %s", call_id.c_str());
1142
1166
            return false;
1143
1167
        }
1144
1168
 
1145
1169
        Conference *conf = getConferenceFromCallID(call_id);
1146
1170
 
1147
 
        if (conf == NULL) {
 
1171
        if (conf == nullptr) {
1148
1172
            ERROR("Call is not conferencing, cannot detach");
1149
1173
            return false;
1150
1174
        }
1187
1211
        else
1188
1212
            WARN("Undefined behavior, invalid conference state in detach participant");
1189
1213
 
1190
 
        dbus_.getCallManager()->conferenceChanged(conf->getConfID(),
 
1214
        client_.getCallManager()->conferenceChanged(conf->getConfID(),
1191
1215
                                                  conf->getStateStr());
1192
1216
 
1193
1217
        unsetCurrentCall();
1219
1243
    call->setConfId("");
1220
1244
 
1221
1245
    removeStream(call_id);
1222
 
    getMainBuffer().dumpInfo();
1223
 
    dbus_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
 
1246
 
 
1247
    client_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
 
1248
 
1224
1249
    processRemainingParticipants(*conf);
1225
1250
}
1226
1251
 
1234
1259
 
1235
1260
    if (n > 1) {
1236
1261
        // Reset ringbuffer's readpointers
1237
 
        for (ParticipantSet::const_iterator p = participants.begin();
1238
 
             p != participants.end(); ++p)
1239
 
            getMainBuffer().flush(*p);
 
1262
        for (const auto &p : participants)
 
1263
            getMainBuffer().flush(p);
1240
1264
 
1241
1265
        getMainBuffer().flush(MainBuffer::DEFAULT_ID);
1242
1266
    } else if (n == 1) {
1280
1304
    Conference *conf = conferenceMap_.find(conf_id1)->second;
1281
1305
    ParticipantSet participants(conf->getParticipantList());
1282
1306
 
1283
 
    for (ParticipantSet::const_iterator p = participants.begin();
1284
 
            p != participants.end(); ++p)
1285
 
        addParticipant(*p, conf_id2);
 
1307
    for (const auto &p : participants)
 
1308
        addParticipant(p, conf_id2);
1286
1309
 
1287
1310
    return true;
1288
1311
}
1302
1325
            Conference* conf = iter->second;
1303
1326
 
1304
1327
            conf->bindParticipant(call_id);
1305
 
 
1306
 
            ParticipantSet participants(conf->getParticipantList());
1307
 
 
1308
 
            // reset ring buffer for all conference participant
1309
 
            for (ParticipantSet::const_iterator iter_p = participants.begin();
1310
 
                    iter_p != participants.end(); ++iter_p)
1311
 
                getMainBuffer().flush(*iter_p);
1312
 
 
1313
 
            getMainBuffer().flush(MainBuffer::DEFAULT_ID);
1314
1328
        }
1315
1329
 
1316
1330
    } else {
1319
1333
        // bind to main
1320
1334
        getMainBuffer().bindCallID(call_id, MainBuffer::DEFAULT_ID);
1321
1335
 
1322
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
1336
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
1323
1337
        audiodriver_->flushUrgent();
1324
1338
        audiodriver_->flushMain();
1325
1339
    }
1326
 
 
1327
 
    getMainBuffer().dumpInfo();
1328
1340
}
1329
1341
 
1330
1342
void ManagerImpl::removeStream(const std::string& call_id)
1331
1343
{
1332
1344
    DEBUG("Remove audio stream %s", call_id.c_str());
1333
1345
    getMainBuffer().unBindAll(call_id);
1334
 
    getMainBuffer().dumpInfo();
1335
1346
}
1336
1347
 
1337
1348
//THREAD=Main
1338
1349
void ManagerImpl::saveConfig()
1339
1350
{
1340
1351
    DEBUG("Saving Configuration to XDG directory %s", path_.c_str());
1341
 
    AudioLayer *audiolayer = getAudioDriver();
1342
 
    if (audiolayer != NULL) {
1343
 
        audioPreference.setVolumemic(audiolayer->getCaptureGain());
1344
 
        audioPreference.setVolumespkr(audiolayer->getPlaybackGain());
 
1352
    if (audiodriver_ != nullptr) {
 
1353
        audioPreference.setVolumemic(audiodriver_->getCaptureGain());
 
1354
        audioPreference.setVolumespkr(audiodriver_->getPlaybackGain());
 
1355
        audioPreference.setCaptureMuted(audiodriver_->isCaptureMuted());
 
1356
        audioPreference.setPlaybackMuted(audiodriver_->isPlaybackMuted());
1345
1357
    }
1346
1358
 
1347
1359
    try {
1348
1360
        Conf::YamlEmitter emitter(path_.c_str());
1349
1361
 
1350
 
        for (AccountMap::iterator iter = SIPVoIPLink::instance()->getAccounts().begin();
1351
 
             iter != SIPVoIPLink::instance()->getAccounts().end(); ++iter)
1352
 
            iter->second->serialize(emitter);
 
1362
        for (auto &item : SIPVoIPLink::instance()->getAccounts())
 
1363
            item.second->serialize(emitter);
1353
1364
 
1354
1365
#if HAVE_IAX
1355
 
        for (AccountMap::iterator iter = IAXVoIPLink::getAccounts().begin(); iter != IAXVoIPLink::getAccounts().end(); ++iter)
1356
 
            iter->second->serialize(emitter);
 
1366
        for (auto &item : IAXVoIPLink::getAccounts())
 
1367
            item.second->serialize(emitter);
1357
1368
#endif
1358
1369
 
 
1370
        // FIXME: this is a hack until we get rid of accountOrder
 
1371
        preferences.verifyAccountOrder(getAccountList());
1359
1372
        preferences.serialize(emitter);
1360
1373
        voipPreferences.serialize(emitter);
1361
1374
        hookPreference.serialize(emitter);
1402
1415
        return;
1403
1416
    }
1404
1417
 
1405
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
1418
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
1406
1419
 
1407
1420
    // numbers of int = length in milliseconds / 1000 (number of seconds)
1408
1421
    //                = number of seconds * SAMPLING_RATE by SECONDS
1409
1422
 
1410
1423
    // fast return, no sound, so no dtmf
1411
 
    if (audiodriver_ == NULL || dtmfKey_.get() == 0) {
 
1424
    if (audiodriver_ == nullptr or not dtmfKey_) {
1412
1425
        DEBUG("No audio layer...");
1413
1426
        return;
1414
1427
    }
1421
1434
 
1422
1435
    // this buffer is for mono
1423
1436
    // TODO <-- this should be global and hide if same size
1424
 
    std::vector<SFLDataFormat> buf(size);
 
1437
    //std::vector<SFLAudioSample> buf(size);
 
1438
    AudioBuffer buf(size, 1, 8000);
1425
1439
 
1426
1440
    // Handle dtmf
1427
1441
    dtmfKey_->startTone(code);
1428
1442
 
1429
1443
    // copy the sound
1430
 
    if (dtmfKey_->generateDTMF(buf)) {
 
1444
    if (dtmfKey_->generateDTMF(*buf.getChannel(0))) {
1431
1445
        // Put buffer to urgentRingBuffer
1432
1446
        // put the size in bytes...
1433
1447
        // so size * 1 channel (mono) * sizeof (bytes for the data)
1434
1448
        // audiolayer->flushUrgent();
1435
1449
        audiodriver_->startStream();
1436
 
        audiodriver_->putUrgent(&(*buf.begin()), size * sizeof(SFLDataFormat));
 
1450
 
 
1451
        // FIXME: do real synchronization
 
1452
        int tries = 10;
 
1453
        while (not audiodriver_->isStarted() and tries--) {
 
1454
            WARN("Audio layer not ready yet");
 
1455
            usleep(10000);
 
1456
        }
 
1457
        audiodriver_->putUrgent(buf);
1437
1458
    }
1438
1459
 
1439
1460
    // TODO Cache the DTMF
1440
1461
}
1441
1462
 
1442
1463
// Multi-thread
1443
 
bool ManagerImpl::incomingCallWaiting() const
 
1464
bool ManagerImpl::incomingCallsWaiting()
1444
1465
{
1445
 
    return nbIncomingWaitingCall_ > 0;
 
1466
    std::lock_guard<std::mutex> m(waitingCallsMutex_);
 
1467
    return not waitingCalls_.empty();
1446
1468
}
1447
1469
 
1448
1470
void ManagerImpl::addWaitingCall(const std::string& id)
1449
1471
{
1450
 
    sfl::ScopedLock m(waitingCallMutex_);
1451
 
    waitingCall_.insert(id);
1452
 
    nbIncomingWaitingCall_++;
 
1472
    std::lock_guard<std::mutex> m(waitingCallsMutex_);
 
1473
    waitingCalls_.insert(id);
1453
1474
}
1454
1475
 
1455
1476
void ManagerImpl::removeWaitingCall(const std::string& id)
1456
1477
{
1457
 
    sfl::ScopedLock m(waitingCallMutex_);
1458
 
 
1459
 
    if (waitingCall_.erase(id))
1460
 
        nbIncomingWaitingCall_--;
 
1478
    std::lock_guard<std::mutex> m(waitingCallsMutex_);
 
1479
    waitingCalls_.erase(id);
1461
1480
}
1462
1481
 
1463
1482
///////////////////////////////////////////////////////////////////////////////
1485
1504
 
1486
1505
    if (not hasCurrentCall()) {
1487
1506
        call.setConnectionState(Call::RINGING);
1488
 
        ringtone(accountId);
 
1507
        playRingtone(accountId);
1489
1508
    }
1490
1509
 
1491
1510
    addWaitingCall(callID);
1493
1512
    std::string number(call.getPeerNumber());
1494
1513
 
1495
1514
    std::string from("<" + number + ">");
1496
 
    dbus_.getCallManager()->incomingCall(accountId, callID, call.getDisplayName() + " " + from);
 
1515
 
 
1516
    client_.getCallManager()->incomingCall(accountId, callID, call.getDisplayName() + " " + from);
1497
1517
}
1498
1518
 
1499
1519
 
1508
1528
 
1509
1529
        ParticipantSet participants(conf->getParticipantList());
1510
1530
 
1511
 
        for (ParticipantSet::const_iterator iter_p = participants.begin();
1512
 
                iter_p != participants.end(); ++iter_p) {
 
1531
        for (const auto &item_p : participants) {
1513
1532
 
1514
 
            if (*iter_p == callID)
 
1533
            if (item_p == callID)
1515
1534
                continue;
1516
1535
 
1517
 
            std::string accountId(getAccountFromCall(*iter_p));
 
1536
            std::string accountId(getAccountFromCall(item_p));
1518
1537
 
1519
 
            DEBUG("Send message to %s, (%s)", (*iter_p).c_str(), accountId.c_str());
 
1538
            DEBUG("Send message to %s, (%s)", item_p.c_str(), accountId.c_str());
1520
1539
 
1521
1540
            Account *account = getAccount(accountId);
1522
1541
 
1529
1548
        }
1530
1549
 
1531
1550
        // in case of a conference we must notify client using conference id
1532
 
        dbus_.getCallManager()->incomingMessage(conf->getConfID(), from, message);
 
1551
        client_.getCallManager()->incomingMessage(conf->getConfID(), from, message);
1533
1552
 
1534
1553
    } else
1535
 
        dbus_.getCallManager()->incomingMessage(callID, from, message);
 
1554
        client_.getCallManager()->incomingMessage(callID, from, message);
1536
1555
}
1537
1556
 
1538
1557
//THREAD=VoIP
1552
1571
 
1553
1572
        ParticipantSet participants(conf->getParticipantList());
1554
1573
 
1555
 
        for (ParticipantSet::const_iterator iter_p = participants.begin();
1556
 
                iter_p != participants.end(); ++iter_p) {
 
1574
        for (const auto &participant : participants) {
1557
1575
 
1558
 
            std::string accountId = getAccountFromCall(*iter_p);
 
1576
            std::string accountId = getAccountFromCall(participant);
1559
1577
 
1560
1578
            Account *account = getAccount(accountId);
1561
1579
 
1564
1582
                return false;
1565
1583
            }
1566
1584
 
1567
 
            account->getVoIPLink()->sendTextMessage(*iter_p, message, from);
 
1585
            account->getVoIPLink()->sendTextMessage(participant, message, from);
1568
1586
        }
1569
1587
 
1570
1588
        return true;
1579
1597
 
1580
1598
        ParticipantSet participants(conf->getParticipantList());
1581
1599
 
1582
 
        for (ParticipantSet::const_iterator iter_p = participants.begin();
1583
 
                iter_p != participants.end(); ++iter_p) {
 
1600
        for (const auto &item_p : participants) {
1584
1601
 
1585
 
            const std::string accountId(getAccountFromCall(*iter_p));
 
1602
            const std::string accountId(getAccountFromCall(item_p));
1586
1603
 
1587
1604
            Account *account = getAccount(accountId);
1588
1605
 
1591
1608
                return false;
1592
1609
            }
1593
1610
 
1594
 
            account->getVoIPLink()->sendTextMessage(*iter_p, message, from);
 
1611
            account->getVoIPLink()->sendTextMessage(item_p, message, from);
1595
1612
        }
1596
1613
    } else {
1597
1614
        Account *account = getAccount(getAccountFromCall(callID));
1613
1630
    DEBUG("Peer answered call %s", id.c_str());
1614
1631
 
1615
1632
    // The if statement is usefull only if we sent two calls at the same time.
1616
 
    if (isCurrentCall(id)) {
 
1633
    if (isCurrentCall(id))
1617
1634
        stopTone();
1618
1635
 
1619
 
        // set playback mode to VOICE
1620
 
        AudioLayer *al = getAudioDriver();
1621
 
        if(al) al->setPlaybackMode(AudioLayer::VOICE);
1622
 
    }
1623
 
 
1624
1636
    // Connect audio streams
1625
1637
    addStream(id);
1626
1638
 
1627
 
    {
1628
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
1639
    if (audiodriver_) {
 
1640
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
1629
1641
        audiodriver_->flushMain();
1630
1642
        audiodriver_->flushUrgent();
1631
1643
    }
1632
1644
 
1633
1645
    if (audioPreference.getIsAlwaysRecording())
1634
 
        setRecordingCall(id);
 
1646
        toggleRecordingCall(id);
1635
1647
 
1636
 
    dbus_.getCallManager()->callStateChanged(id, "CURRENT");
 
1648
    client_.getCallManager()->callStateChanged(id, "CURRENT");
1637
1649
}
1638
1650
 
1639
1651
//THREAD=VoIP Call=Outgoing
1644
1656
    if (isCurrentCall(id))
1645
1657
        ringback();
1646
1658
 
1647
 
    dbus_.getCallManager()->callStateChanged(id, "RINGING");
 
1659
    client_.getCallManager()->callStateChanged(id, "RINGING");
1648
1660
}
1649
1661
 
1650
1662
//THREAD=VoIP Call=Outgoing/Ingoing
1657
1669
    } else if (isCurrentCall(call_id)) {
1658
1670
        stopTone();
1659
1671
        unsetCurrentCall();
1660
 
 
1661
 
        // set playback mode to NONE
1662
 
        AudioLayer *al = getAudioDriver();
1663
 
        if(al) al->setPlaybackMode(AudioLayer::NONE);
1664
1672
    }
1665
1673
 
1666
1674
    /* Direct IP to IP call */
1681
1689
        }
1682
1690
    }
1683
1691
 
1684
 
    /* Broadcast a signal over DBus */
1685
 
    dbus_.getCallManager()->callStateChanged(call_id, "HUNGUP");
 
1692
    client_.getCallManager()->callStateChanged(call_id, "HUNGUP");
1686
1693
 
1687
1694
    removeWaitingCall(call_id);
1688
 
    checkAudio();
 
1695
    if (not incomingCallsWaiting())
 
1696
        stopTone();
 
1697
 
1689
1698
    removeStream(call_id);
1690
1699
}
1691
1700
 
1692
1701
//THREAD=VoIP
1693
1702
void ManagerImpl::callBusy(const std::string& id)
1694
1703
{
1695
 
    DEBUG("Call %s busy", id.c_str());
1696
 
    dbus_.getCallManager()->callStateChanged(id, "BUSY");
 
1704
    client_.getCallManager()->callStateChanged(id, "BUSY");
1697
1705
 
1698
1706
    if (isCurrentCall(id)) {
1699
1707
        playATone(Tone::TONE_BUSY);
1707
1715
//THREAD=VoIP
1708
1716
void ManagerImpl::callFailure(const std::string& call_id)
1709
1717
{
1710
 
    dbus_.getCallManager()->callStateChanged(call_id, "FAILURE");
 
1718
    client_.getCallManager()->callStateChanged(call_id, "FAILURE");
1711
1719
 
1712
1720
    if (isCurrentCall(call_id)) {
1713
1721
        playATone(Tone::TONE_BUSY);
1728
1736
void ManagerImpl::startVoiceMessageNotification(const std::string& accountId,
1729
1737
        int nb_msg)
1730
1738
{
1731
 
    dbus_.getCallManager()->voiceMailNotify(accountId, nb_msg);
 
1739
    client_.getCallManager()->voiceMailNotify(accountId, nb_msg);
1732
1740
}
1733
1741
 
1734
1742
/**
1740
1748
        return;
1741
1749
 
1742
1750
    {
1743
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
1751
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
1744
1752
 
1745
 
        if (audiodriver_ == NULL) {
 
1753
        if (audiodriver_ == nullptr) {
1746
1754
            ERROR("Audio layer not initialized");
1747
1755
            return;
1748
1756
        }
1752
1760
    }
1753
1761
 
1754
1762
    {
1755
 
        sfl::ScopedLock lock(toneMutex_);
1756
 
        if (telephoneTone_.get() != 0)
 
1763
        std::lock_guard<std::mutex> lock(toneMutex_);
 
1764
        if (telephoneTone_)
1757
1765
            telephoneTone_->setCurrentTone(toneId);
1758
1766
    }
1759
1767
}
1766
1774
    if (not voipPreferences.getPlayTones())
1767
1775
        return;
1768
1776
 
1769
 
    sfl::ScopedLock lock(toneMutex_);
1770
 
    if (telephoneTone_.get() != NULL)
 
1777
    std::lock_guard<std::mutex> lock(toneMutex_);
 
1778
    if (telephoneTone_)
1771
1779
        telephoneTone_->setCurrentTone(Tone::TONE_NULL);
1772
1780
 
1773
 
    if (audiofile_.get()) {
 
1781
    if (audiofile_) {
1774
1782
        std::string filepath(audiofile_->getFilePath());
1775
 
        dbus_.getCallManager()->recordPlaybackStopped(filepath);
 
1783
 
 
1784
        client_.getCallManager()->recordPlaybackStopped(filepath);
1776
1785
        audiofile_.reset();
1777
1786
    }
1778
1787
}
1809
1818
    playATone(Tone::TONE_RINGTONE);
1810
1819
}
1811
1820
 
 
1821
// Caller must hold toneMutex
 
1822
void
 
1823
ManagerImpl::updateAudioFile(const std::string &file, int sampleRate)
 
1824
{
 
1825
    audiofile_.reset(new AudioFile(file, sampleRate));
 
1826
}
 
1827
 
1812
1828
/**
1813
1829
 * Multi Thread
1814
1830
 */
1815
 
void ManagerImpl::ringtone(const std::string& accountID)
 
1831
void ManagerImpl::playRingtone(const std::string& accountID)
1816
1832
{
1817
1833
    Account *account = getAccount(accountID);
1818
1834
 
1837
1853
 
1838
1854
    int audioLayerSmplr = 8000;
1839
1855
    {
1840
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
1856
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
1841
1857
 
1842
1858
        if (!audiodriver_) {
1843
1859
            ERROR("no audio layer in ringtone");
1847
1863
        audioLayerSmplr = audiodriver_->getSampleRate();
1848
1864
    }
1849
1865
 
 
1866
    bool doFallback = false;
 
1867
 
1850
1868
    {
1851
 
        sfl::ScopedLock m(toneMutex_);
 
1869
        std::lock_guard<std::mutex> m(toneMutex_);
1852
1870
 
1853
 
        if (audiofile_.get()) {
1854
 
            dbus_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath());
 
1871
        if (audiofile_) {
 
1872
            client_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath());
1855
1873
            audiofile_.reset();
1856
1874
        }
1857
1875
 
1858
1876
        try {
1859
 
            if (ringchoice.find(".wav") != std::string::npos)
1860
 
                audiofile_.reset(new WaveFile(ringchoice, audioLayerSmplr));
1861
 
            else {
1862
 
                sfl::AudioCodec *codec;
1863
 
                if (ringchoice.find(".ul") != std::string::npos or ringchoice.find(".au") != std::string::npos)
1864
 
                    codec = audioCodecFactory.getCodec(PAYLOAD_CODEC_ULAW);
1865
 
                else
1866
 
                    throw AudioFileException("Couldn't guess an appropriate decoder");
1867
 
 
1868
 
                audiofile_.reset(new RawFile(ringchoice, static_cast<sfl::AudioCodec *>(codec), audioLayerSmplr));
1869
 
            }
 
1877
            updateAudioFile(ringchoice, audioLayerSmplr);
1870
1878
        } catch (const AudioFileException &e) {
1871
 
            ERROR("Exception: %s", e.what());
 
1879
            WARN("Ringtone error: %s", e.what());
 
1880
            doFallback = true; // do ringback once lock is out of scope
1872
1881
        }
1873
1882
    } // leave mutex
1874
1883
 
1875
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
1884
    if (doFallback) {
 
1885
        ringback();
 
1886
        return;
 
1887
    }
 
1888
 
 
1889
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
1876
1890
    // start audio if not started AND flush all buffers (main and urgent)
1877
1891
    audiodriver_->startStream();
1878
1892
}
1879
1893
 
1880
1894
AudioLoop* ManagerImpl::getTelephoneTone()
1881
1895
{
1882
 
    sfl::ScopedLock m(toneMutex_);
1883
 
    if (telephoneTone_.get())
 
1896
    std::lock_guard<std::mutex> m(toneMutex_);
 
1897
    if (telephoneTone_)
1884
1898
        return telephoneTone_->getCurrentTone();
1885
1899
    else
1886
 
        return NULL;
 
1900
        return nullptr;
1887
1901
}
1888
1902
 
1889
1903
AudioLoop*
1890
1904
ManagerImpl::getTelephoneFile()
1891
1905
{
1892
 
    sfl::ScopedLock m(toneMutex_);
 
1906
    std::lock_guard<std::mutex> m(toneMutex_);
1893
1907
    return audiofile_.get();
1894
1908
}
1895
1909
 
1899
1913
/**
1900
1914
 * Initialization: Main Thread
1901
1915
 */
1902
 
std::string ManagerImpl::createConfigFile() const
 
1916
std::string ManagerImpl::retrieveConfigPath() const
1903
1917
{
 
1918
#ifdef __ANDROID__
 
1919
    std::string configdir = "/data/data/org.sflphone";
 
1920
#else
1904
1921
    std::string configdir = fileutils::get_home_dir() + DIR_SEPARATOR_STR +
1905
1922
                            ".config" + DIR_SEPARATOR_STR + PACKAGE;
 
1923
#endif
1906
1924
 
1907
1925
    const std::string xdg_env(XDG_CONFIG_HOME);
1908
1926
    if (not xdg_env.empty())
1911
1929
    if (mkdir(configdir.data(), 0700) != 0) {
1912
1930
        // If directory creation failed
1913
1931
        if (errno != EEXIST)
1914
 
           DEBUG("Cannot create directory: %m");
 
1932
           DEBUG("Cannot create directory: %s!", configdir.c_str());
1915
1933
    }
1916
1934
 
1917
1935
    static const char * const PROGNAME = "sflphoned";
1952
1970
 */
1953
1971
void ManagerImpl::setAudioPlugin(const std::string& audioPlugin)
1954
1972
{
1955
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
1973
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
1956
1974
 
1957
1975
    audioPreference.setAlsaPlugin(audioPlugin);
1958
1976
 
1971
1989
 */
1972
1990
void ManagerImpl::setAudioDevice(int index, AudioLayer::PCMType type)
1973
1991
{
1974
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
1992
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
1975
1993
 
1976
1994
    if (!audiodriver_) {
1977
1995
        ERROR("Audio driver not initialized");
1994
2012
 */
1995
2013
std::vector<std::string> ManagerImpl::getAudioOutputDeviceList()
1996
2014
{
1997
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
2015
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
1998
2016
    return audiodriver_->getPlaybackDeviceList();
1999
2017
}
2000
2018
 
2004
2022
 */
2005
2023
std::vector<std::string> ManagerImpl::getAudioInputDeviceList()
2006
2024
{
2007
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
2025
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
2008
2026
    return audiodriver_->getCaptureDeviceList();
2009
2027
}
2010
2028
 
2013
2031
 */
2014
2032
std::vector<std::string> ManagerImpl::getCurrentAudioDevicesIndex()
2015
2033
{
2016
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
2034
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
2017
2035
 
2018
2036
    std::vector<std::string> v;
2019
2037
 
2062
2080
    return audioPreference.setIsAlwaysRecording(isAlwaysRec);
2063
2081
}
2064
2082
 
2065
 
void ManagerImpl::setRecordingCall(const std::string& id)
 
2083
bool ManagerImpl::toggleRecordingCall(const std::string& id)
2066
2084
{
2067
 
    Recordable* rec = NULL;
 
2085
    Recordable* rec = nullptr;
2068
2086
 
2069
2087
    ConferenceMap::const_iterator it(conferenceMap_.find(id));
2070
2088
    if (it == conferenceMap_.end()) {
2071
 
        DEBUG("Set recording for call %s", id.c_str());
 
2089
        DEBUG("toggle recording for call %s", id.c_str());
2072
2090
        rec = getCallFromCallID(id);
2073
2091
    } else {
2074
 
        DEBUG("Set recording for conference %s", id.c_str());
 
2092
        DEBUG("toggle recording for conference %s", id.c_str());
2075
2093
        Conference *conf = it->second;
2076
2094
 
2077
2095
        if (conf) {
2083
2101
        }
2084
2102
    }
2085
2103
 
2086
 
    if (rec == NULL) {
 
2104
    if (rec == nullptr) {
2087
2105
        ERROR("Could not find recordable instance %s", id.c_str());
2088
 
        return;
 
2106
        return false;
2089
2107
    }
2090
2108
 
2091
 
    rec->setRecording();
2092
 
    dbus_.getCallManager()->recordPlaybackFilepath(id, rec->getFilename());
 
2109
    const bool result = rec->toggleRecording();
 
2110
    client_.getCallManager()->recordPlaybackFilepath(id, rec->getFilename());
 
2111
    client_.getCallManager()->recordingStateChanged(id, result);
 
2112
    return result;
2093
2113
}
2094
2114
 
2095
2115
bool ManagerImpl::isRecording(const std::string& id)
2104
2124
 
2105
2125
    int sampleRate;
2106
2126
    {
2107
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
2127
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
2108
2128
 
2109
2129
        if (!audiodriver_) {
2110
2130
            ERROR("No audio layer in start recorded file playback");
2115
2135
    }
2116
2136
 
2117
2137
    {
2118
 
        sfl::ScopedLock m(toneMutex_);
 
2138
        std::lock_guard<std::mutex> m(toneMutex_);
2119
2139
 
2120
 
        if (audiofile_.get()) {
2121
 
            dbus_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath());
 
2140
        if (audiofile_) {
 
2141
            client_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath());
2122
2142
            audiofile_.reset();
2123
2143
        }
2124
2144
 
2125
2145
        try {
2126
 
            audiofile_.reset(new WaveFile(filepath, sampleRate));
2127
 
            audiofile_.get()->setIsRecording(true);
 
2146
            updateAudioFile(filepath, sampleRate);
 
2147
            if (not audiofile_)
 
2148
                return false;
2128
2149
        } catch (const AudioFileException &e) {
2129
 
            ERROR("Exception: %s", e.what());
 
2150
            WARN("Audio file error: %s", e.what());
 
2151
            return false;
2130
2152
        }
2131
2153
    } // release toneMutex
2132
2154
 
2133
 
    sfl::ScopedLock lock(audioLayerMutex_);
2134
 
    audiodriver_->startStream();
 
2155
    {
 
2156
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
 
2157
        audiodriver_->startStream();
 
2158
    }
2135
2159
 
2136
2160
    return true;
2137
2161
}
2138
2162
 
2139
2163
void ManagerImpl::recordingPlaybackSeek(const double value)
2140
2164
{
2141
 
    sfl::ScopedLock m(toneMutex_);
2142
 
    if (audiofile_.get())
 
2165
    std::lock_guard<std::mutex> m(toneMutex_);
 
2166
    if (audiofile_)
2143
2167
        audiofile_.get()->seek(value);
2144
2168
}
2145
2169
 
2148
2172
{
2149
2173
    DEBUG("Stop recorded file playback %s", filepath.c_str());
2150
2174
 
2151
 
    {
2152
 
        sfl::ScopedLock lock(audioLayerMutex_);
2153
 
        audiodriver_->stopStream();
2154
 
    }
 
2175
    checkAudio();
2155
2176
 
2156
2177
    {
2157
 
        sfl::ScopedLock m(toneMutex_);
 
2178
        std::lock_guard<std::mutex> m(toneMutex_);
2158
2179
        audiofile_.reset();
2159
2180
    }
 
2181
    client_.getCallManager()->recordPlaybackStopped(filepath);
2160
2182
}
2161
2183
 
2162
2184
void ManagerImpl::setHistoryLimit(int days)
2174
2196
void ManagerImpl::setAudioManager(const std::string &api)
2175
2197
{
2176
2198
    {
2177
 
        sfl::ScopedLock lock(audioLayerMutex_);
 
2199
        std::lock_guard<std::mutex> lock(audioLayerMutex_);
2178
2200
 
2179
2201
        if (!audiodriver_)
2180
2202
            return;
2200
2222
{
2201
2223
    int soundCardIndex = 0;
2202
2224
 
2203
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
2225
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
2204
2226
 
2205
 
    if (audiodriver_ == NULL) {
 
2227
    if (audiodriver_ == nullptr) {
2206
2228
        ERROR("Audio layer not initialized");
2207
2229
        return soundCardIndex;
2208
2230
    }
2216
2238
}
2217
2239
 
2218
2240
 
2219
 
std::string ManagerImpl::getNoiseSuppressState() const
2220
 
{
2221
 
    return audioPreference.getNoiseReduce() ? "enabled" : "disabled";
2222
 
}
2223
 
 
2224
 
void ManagerImpl::setNoiseSuppressState(const std::string &state)
2225
 
{
2226
 
    audioPreference.setNoiseReduce(state == "enabled");
2227
 
}
2228
 
 
2229
 
bool ManagerImpl::getEchoCancelState() const
2230
 
{
2231
 
    return audioPreference.getEchoCancel();
2232
 
}
2233
 
 
2234
 
void ManagerImpl::setEchoCancelState(const std::string &state)
2235
 
{
2236
 
    audioPreference.setEchoCancel(state == "enabled");
 
2241
bool ManagerImpl::getNoiseSuppressState() const
 
2242
{
 
2243
    return audioPreference.getNoiseReduce();
 
2244
}
 
2245
 
 
2246
void ManagerImpl::setNoiseSuppressState(bool state)
 
2247
{
 
2248
    audioPreference.setNoiseReduce(state);
 
2249
}
 
2250
 
 
2251
bool ManagerImpl::isAGCEnabled() const
 
2252
{
 
2253
    return audioPreference.isAGCEnabled();
 
2254
}
 
2255
 
 
2256
void ManagerImpl::setAGCState(bool state)
 
2257
{
 
2258
    audioPreference.setAGCState(state);
2237
2259
}
2238
2260
 
2239
2261
/**
2241
2263
 */
2242
2264
void ManagerImpl::initAudioDriver()
2243
2265
{
2244
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
2266
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
2245
2267
    audiodriver_ = audioPreference.createAudioLayer();
2246
2268
}
2247
2269
 
2248
2270
void ManagerImpl::switchAudioManager()
2249
2271
{
2250
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
2272
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
2251
2273
 
2252
2274
    bool wasStarted = audiodriver_->isStarted();
2253
2275
    delete audiodriver_;
2259
2281
 
2260
2282
void ManagerImpl::audioSamplingRateChanged(int samplerate)
2261
2283
{
2262
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
2284
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
2263
2285
 
2264
2286
    if (!audiodriver_) {
2265
2287
        DEBUG("No Audio driver initialized");
2266
2288
        return;
2267
2289
    }
2268
2290
 
2269
 
    // Only modify internal sampling rate if new sampling rate is higher
 
2291
    // Only modify internal sampling rate if new sampling rate is different
2270
2292
    int currentSamplerate = mainBuffer_.getInternalSamplingRate();
2271
2293
 
2272
 
    if (currentSamplerate >= samplerate) {
 
2294
    if (currentSamplerate == samplerate) {
2273
2295
        DEBUG("No need to update audio layer sampling rate");
2274
2296
        return;
2275
2297
    } else
2285
2307
    unsigned int sampleRate = audiodriver_->getSampleRate();
2286
2308
 
2287
2309
    {
2288
 
        sfl::ScopedLock toneLock(toneMutex_);
 
2310
        std::lock_guard<std::mutex> toneLock(toneMutex_);
2289
2311
        telephoneTone_.reset(new TelephoneTone(preferences.getZoneToneChoice(), sampleRate));
2290
2312
    }
2291
2313
    dtmfKey_.reset(new DTMF(sampleRate));
2347
2369
 
2348
2370
    // If no order has been set, load the default one ie according to the creation date.
2349
2371
    if (account_order.empty()) {
2350
 
        for (AccountMap::const_iterator iter = allAccounts.begin(); iter != allAccounts.end(); ++iter) {
2351
 
            if (iter->first == SIPAccount::IP2IP_PROFILE || iter->first.empty())
 
2372
        for (const auto &item : allAccounts) {
 
2373
            if (item.first == SIPAccount::IP2IP_PROFILE || item.first.empty())
2352
2374
                continue;
2353
2375
 
2354
 
            if (iter->second)
2355
 
                v.push_back(iter->second->getAccountID());
 
2376
            if (item.second)
 
2377
                v.push_back(item.second->getAccountID());
2356
2378
        }
2357
2379
    }
2358
2380
    else {
2359
 
        for (vector<string>::const_iterator iter = account_order.begin(); iter != account_order.end(); ++iter) {
2360
 
            if (*iter == SIPAccount::IP2IP_PROFILE or iter->empty())
 
2381
        for (const auto &item : account_order) {
 
2382
            if (item == SIPAccount::IP2IP_PROFILE or item.empty())
2361
2383
                continue;
2362
2384
 
2363
 
            AccountMap::const_iterator account_iter = allAccounts.find(*iter);
 
2385
            AccountMap::const_iterator account_iter = allAccounts.find(item);
2364
2386
 
2365
2387
            if (account_iter != allAccounts.end() and account_iter->second)
2366
2388
                v.push_back(account_iter->second->getAccountID());
2373
2395
std::map<std::string, std::string> ManagerImpl::getAccountDetails(
2374
2396
    const std::string& accountID) const
2375
2397
{
2376
 
    // Default account used to get default parameters if requested by client (to build new account)
2377
 
    static const SIPAccount DEFAULT_ACCOUNT("default");
2378
 
 
2379
 
    if (accountID.empty()) {
2380
 
        DEBUG("Returning default account settings");
2381
 
        return DEFAULT_ACCOUNT.getAccountDetails();
2382
 
    }
2383
 
 
2384
2398
    Account * account = getAccount(accountID);
2385
2399
 
2386
 
    if (account)
 
2400
    if (account) {
2387
2401
        return account->getAccountDetails();
2388
 
    else {
2389
 
        ERROR("Get account details on a non-existing accountID %s. Returning default", accountID.c_str());
2390
 
        return DEFAULT_ACCOUNT.getAccountDetails();
 
2402
    } else {
 
2403
        ERROR("Could not get account details on a non-existing accountID %s", accountID.c_str());
 
2404
        // return an empty map since we can't throw an exception to D-Bus
 
2405
        return std::map<std::string, std::string>();
2391
2406
    }
2392
2407
}
2393
2408
 
2401
2416
 
2402
2417
    Account* account = getAccount(accountID);
2403
2418
 
2404
 
    if (account == NULL) {
 
2419
    if (account == nullptr) {
2405
2420
        ERROR("Could not find account %s", accountID.c_str());
2406
2421
        return;
2407
2422
    }
2408
2423
 
 
2424
    // Ignore if nothing has changed
 
2425
    if (details == account->getAccountDetails())
 
2426
        return;
 
2427
 
 
2428
    // Unregister before modifying any account information
 
2429
    account->unregisterVoIPLink();
2409
2430
    account->setAccountDetails(details);
2410
2431
 
2411
2432
    // Serialize configuration to disk once it is done
2417
2438
        account->unregisterVoIPLink();
2418
2439
 
2419
2440
    // Update account details to the client side
2420
 
    dbus_.getConfigurationManager()->accountsChanged();
 
2441
    client_.getConfigurationManager()->accountsChanged();
2421
2442
}
2422
2443
 
2423
2444
std::string
2424
2445
ManagerImpl::addAccount(const std::map<std::string, std::string>& details)
2425
2446
{
2426
2447
    /** @todo Deal with both the accountMap_ and the Configuration */
2427
 
    std::stringstream accountID;
2428
 
 
2429
 
    accountID << "Account:" << time(NULL);
2430
 
    std::string newAccountID(accountID.str());
 
2448
 
 
2449
    std::string newAccountID;
 
2450
 
 
2451
    const std::vector<std::string> accountList(getAccountList());
 
2452
 
 
2453
    do {
 
2454
        std::stringstream accountID;
 
2455
        accountID << "Account:" << rand();
 
2456
        newAccountID = accountID.str();
 
2457
    } while (std::find(accountList.begin(), accountList.end(), newAccountID)
 
2458
             != accountList.end());
2431
2459
 
2432
2460
    // Get the type
2433
2461
 
2441
2469
 
2442
2470
    /** @todo Verify the uniqueness, in case a program adds accounts, two in a row. */
2443
2471
 
2444
 
    Account* newAccount = NULL;
 
2472
    Account* newAccount = nullptr;
2445
2473
 
2446
2474
    if (accountType == "SIP") {
2447
 
        newAccount = new SIPAccount(newAccountID);
 
2475
        newAccount = new SIPAccount(newAccountID, true);
2448
2476
        SIPVoIPLink::instance()->getAccounts()[newAccountID] = newAccount;
2449
2477
    }
2450
2478
#if HAVE_IAX
2461
2489
 
2462
2490
    newAccount->setAccountDetails(details);
2463
2491
 
2464
 
    // Add the newly created account in the account order list
2465
 
    std::string accountList(preferences.getAccountOrder());
2466
 
 
2467
 
    newAccountID += "/";
2468
 
    if (not accountList.empty()) {
2469
 
        // Prepend the new account
2470
 
        accountList.insert(0, newAccountID);
2471
 
        preferences.setAccountOrder(accountList);
2472
 
    } else {
2473
 
        accountList = newAccountID;
2474
 
        preferences.setAccountOrder(accountList);
2475
 
    }
2476
 
 
2477
 
    DEBUG("Getting accounts: %s", accountList.c_str());
 
2492
    preferences.addAccount(newAccountID);
2478
2493
 
2479
2494
    newAccount->registerVoIPLink();
2480
2495
 
2481
2496
    saveConfig();
2482
2497
 
2483
 
    dbus_.getConfigurationManager()->accountsChanged();
2484
 
 
2485
 
    return accountID.str();
 
2498
    client_.getConfigurationManager()->accountsChanged();
 
2499
 
 
2500
    return newAccountID;
 
2501
}
 
2502
 
 
2503
void ManagerImpl::removeAccounts()
 
2504
{
 
2505
    for (const auto &acc : getAccountList())
 
2506
        removeAccount(acc);
2486
2507
}
2487
2508
 
2488
2509
void ManagerImpl::removeAccount(const std::string& accountID)
2490
2511
    // Get it down and dying
2491
2512
    Account* remAccount = getAccount(accountID);
2492
2513
 
2493
 
    if (remAccount != NULL) {
 
2514
    if (remAccount != nullptr) {
2494
2515
        remAccount->unregisterVoIPLink();
2495
2516
        SIPVoIPLink::instance()->getAccounts().erase(accountID);
2496
2517
#if HAVE_IAX
2500
2521
        // delete remAccount;
2501
2522
    }
2502
2523
 
 
2524
    preferences.removeAccount(accountID);
2503
2525
    config_.removeSection(accountID);
2504
2526
 
2505
2527
    saveConfig();
2506
2528
 
2507
 
    dbus_.getConfigurationManager()->accountsChanged();
 
2529
    client_.getConfigurationManager()->accountsChanged();
2508
2530
}
2509
2531
 
2510
2532
std::string ManagerImpl::getAccountFromCall(const std::string& callID)
2558
2580
    }
2559
2581
 
2560
2582
#if HAVE_IAX
2561
 
    void loadAccount(const Conf::YamlNode *item, AccountMap &sipAccountMap, AccountMap &iaxAccountMap, int &errorCount)
 
2583
    void loadAccount(const Conf::YamlNode *item, AccountMap &sipAccountMap,
 
2584
                     AccountMap &iaxAccountMap, int &errorCount, const std::string &accountOrder)
2562
2585
#else
2563
 
    void loadAccount(const Conf::YamlNode *item, AccountMap &sipAccountMap, int &errorCount)
 
2586
    void loadAccount(const Conf::YamlNode *item, AccountMap &sipAccountMap, int &errorCount,
 
2587
                     const std::string &accountOrder)
2564
2588
#endif
2565
2589
    {
2566
2590
        if (!item) {
2577
2601
 
2578
2602
        std::string accountAlias;
2579
2603
        item->getValue("alias", &accountAlias);
 
2604
        const auto inAccountOrder = [&] (const std::string &id) {
 
2605
            return accountOrder.find(id + "/") != std::string::npos; };
2580
2606
 
2581
 
        if (!accountid.empty() and !accountAlias.empty() and accountid != SIPAccount::IP2IP_PROFILE) {
2582
 
            if (accountType == "SIP") {
2583
 
                Account *a = new SIPAccount(accountid);
 
2607
        if (!accountid.empty() and !accountAlias.empty() and
 
2608
            accountid != SIPAccount::IP2IP_PROFILE) {
 
2609
            if (not inAccountOrder(accountid)) {
 
2610
                WARN("Dropping account %s, which is not in account order", accountid.c_str());
 
2611
            } else if (accountType == "SIP") {
 
2612
                Account *a = new SIPAccount(accountid, true);
2584
2613
                sipAccountMap[accountid] = a;
2585
2614
                a->unserialize(*item);
2586
2615
            } else if (accountType == "IAX") {
2611
2640
 
2612
2641
    SIPAccount *createIP2IPAccount()
2613
2642
    {
2614
 
        SIPAccount *ip2ip = new SIPAccount(SIPAccount::IP2IP_PROFILE);
 
2643
        SIPAccount *ip2ip = new SIPAccount(SIPAccount::IP2IP_PROFILE, true);
2615
2644
        try {
2616
 
            SIPVoIPLink::instance()->sipTransport.createSipTransport(*ip2ip);
 
2645
            SIPVoIPLink::instance()->sipTransport->createSipTransport(*ip2ip);
2617
2646
        } catch (const std::runtime_error &e) {
2618
2647
            ERROR("%s", e.what());
2619
2648
        }
2643
2672
    Sequence *seq = parser.getAccountSequence()->getSequence();
2644
2673
 
2645
2674
    Sequence::const_iterator ip2ip = std::find_if(seq->begin(), seq->end(), isIP2IP);
2646
 
    if (ip2ip != seq->end()) {
 
2675
    if (ip2ip != seq->end())
2647
2676
        SIPVoIPLink::instance()->getAccounts()[SIPAccount::IP2IP_PROFILE]->unserialize(**ip2ip);
2648
 
    }
2649
2677
 
2650
2678
    // Force IP2IP settings to be loaded
2651
2679
    // No registration in the sense of the REGISTER method is performed.
2671
2699
    }
2672
2700
#endif
2673
2701
 
2674
 
    using std::tr1::placeholders::_1;
 
2702
    const std::string accountOrder = preferences.getAccountOrder();
 
2703
 
 
2704
    AccountMap &sipAccounts = SIPVoIPLink::instance()->getAccounts();
2675
2705
#if HAVE_IAX
2676
 
    std::for_each(seq->begin(), seq->end(),
2677
 
            std::tr1::bind(loadAccount, _1,
2678
 
                std::tr1::ref(SIPVoIPLink::instance()->getAccounts()),
2679
 
                std::tr1::ref(IAXVoIPLink::getAccounts()),
2680
 
                std::tr1::ref(errorCount)));
 
2706
    AccountMap &iaxAccounts = IAXVoIPLink::getAccounts();
 
2707
    for (auto &s : *seq)
 
2708
        loadAccount(s, sipAccounts, iaxAccounts, errorCount, accountOrder);
2681
2709
#else
2682
 
    std::for_each(seq->begin(), seq->end(),
2683
 
            std::tr1::bind(loadAccount, _1,
2684
 
                std::tr1::ref(SIPVoIPLink::instance()->getAccounts()),
2685
 
                std::tr1::ref(errorCount)));
 
2710
    for (auto &s : *seq)
 
2711
        loadAccount(s, sipAccounts, errorCount, accountOrder);
2686
2712
#endif
2687
2713
 
2688
2714
    return errorCount;
2690
2716
 
2691
2717
void ManagerImpl::registerAllAccounts()
2692
2718
{
2693
 
    std::for_each(SIPVoIPLink::instance()->getAccounts().begin(), SIPVoIPLink::instance()->getAccounts().end(), registerAccount);
 
2719
    for (auto &a : SIPVoIPLink::instance()->getAccounts())
 
2720
        registerAccount(a);
2694
2721
#if HAVE_IAX
2695
 
    std::for_each(IAXVoIPLink::getAccounts().begin(), IAXVoIPLink::getAccounts().end(), registerAccount);
 
2722
    for (auto &a : IAXVoIPLink::getAccounts())
 
2723
        registerAccount(a);
2696
2724
#endif
2697
2725
}
2698
2726
 
2699
2727
void ManagerImpl::unregisterAllAccounts()
2700
2728
{
2701
 
    std::for_each(SIPVoIPLink::instance()->getAccounts().begin(), SIPVoIPLink::instance()->getAccounts().end(), unregisterAccount);
 
2729
    for (auto &a : SIPVoIPLink::instance()->getAccounts())
 
2730
        unregisterAccount(a);
2702
2731
#if HAVE_IAX
2703
 
    std::for_each(IAXVoIPLink::getAccounts().begin(), IAXVoIPLink::getAccounts().end(), unregisterAccount);
 
2732
    for (auto &a : IAXVoIPLink::getAccounts())
 
2733
        unregisterAccount(a);
2704
2734
#endif
2705
2735
}
2706
2736
 
2710
2740
 
2711
2741
    ret = SIPVoIPLink::instance()->getAccounts().find(accountID) != SIPVoIPLink::instance()->getAccounts().end();
2712
2742
#if HAVE_IAX
2713
 
    if(ret)
 
2743
    if (ret)
2714
2744
        return ret;
2715
2745
 
2716
2746
    ret = IAXVoIPLink::getAccounts().find(accountID) != IAXVoIPLink::getAccounts().end();
2723
2753
ManagerImpl::getIP2IPAccount() const
2724
2754
{
2725
2755
    AccountMap::const_iterator iter = SIPVoIPLink::instance()->getAccounts().find(SIPAccount::IP2IP_PROFILE);
2726
 
    if(iter == SIPVoIPLink::instance()->getAccounts().end())
2727
 
        return NULL;
 
2756
    if (iter == SIPVoIPLink::instance()->getAccounts().end())
 
2757
        return nullptr;
2728
2758
 
2729
2759
    return static_cast<SIPAccount *>(iter->second);
2730
2760
}
2732
2762
Account*
2733
2763
ManagerImpl::getAccount(const std::string& accountID) const
2734
2764
{
2735
 
    Account *account = NULL;
 
2765
    Account *account = nullptr;
2736
2766
 
2737
2767
    account = getSipAccount(accountID);
2738
 
    if(account != NULL)
 
2768
    if (account != nullptr)
2739
2769
        return account;
2740
2770
 
2741
2771
#if HAVE_IAX
2742
2772
    account = getIaxAccount(accountID);
2743
 
    if(account != NULL)
 
2773
    if (account != nullptr)
2744
2774
        return account;
2745
2775
#endif
2746
2776
 
2747
 
    return NULL;
 
2777
    return nullptr;
2748
2778
}
2749
2779
 
2750
2780
SIPAccount *
2751
2781
ManagerImpl::getSipAccount(const std::string& accountID) const
2752
2782
{
2753
2783
    AccountMap::const_iterator iter = SIPVoIPLink::instance()->getAccounts().find(accountID);
2754
 
    if(iter != SIPVoIPLink::instance()->getAccounts().end())
 
2784
    if (iter != SIPVoIPLink::instance()->getAccounts().end())
2755
2785
        return static_cast<SIPAccount *>(iter->second);
2756
2786
 
2757
 
    return NULL;
 
2787
    return nullptr;
2758
2788
}
2759
2789
 
2760
2790
#if HAVE_IAX
2762
2792
ManagerImpl::getIaxAccount(const std::string& accountID) const
2763
2793
{
2764
2794
    AccountMap::const_iterator iter = IAXVoIPLink::getAccounts().find(accountID);
2765
 
    if(iter != IAXVoIPLink::getAccounts().end())
 
2795
    if (iter != IAXVoIPLink::getAccounts().end())
2766
2796
        return static_cast<IAXAccount *>(iter->second);
2767
2797
 
2768
 
    return NULL;
 
2798
    return nullptr;
2769
2799
}
2770
2800
#endif
2771
2801
 
2865
2895
std::string ManagerImpl::getConferenceId(const std::string& callID)
2866
2896
{
2867
2897
    Call *call = getCallFromCallID(callID);
2868
 
    if (call == NULL) {
 
2898
    if (call == nullptr) {
2869
2899
        ERROR("Call is NULL");
2870
2900
        return "";
2871
2901
    }
2878
2908
    if (!history_.save())
2879
2909
        ERROR("Could not save history!");
2880
2910
    else
2881
 
        dbus_.getConfigurationManager()->historyChanged();
 
2911
        client_.getConfigurationManager()->historyChanged();
2882
2912
}
2883
2913
 
2884
2914
void ManagerImpl::clearHistory()
2888
2918
 
2889
2919
void ManagerImpl::startAudioDriverStream()
2890
2920
{
2891
 
    sfl::ScopedLock lock(audioLayerMutex_);
 
2921
    std::lock_guard<std::mutex> lock(audioLayerMutex_);
2892
2922
    audiodriver_->startStream();
2893
2923
}
 
2924
 
 
2925
void
 
2926
ManagerImpl::registerAccounts()
 
2927
{
 
2928
    AccountMap allAccounts(getAllAccounts());
 
2929
 
 
2930
    for (auto &item : allAccounts) {
 
2931
        Account *a = item.second;
 
2932
 
 
2933
        if (!a)
 
2934
            continue;
 
2935
 
 
2936
        a->loadConfig();
 
2937
 
 
2938
        if (a->isEnabled())
 
2939
            a->registerVoIPLink();
 
2940
    }
 
2941
}
 
2942
 
 
2943
 
 
2944
VoIPLink* ManagerImpl::getAccountLink(const std::string& accountID)
 
2945
{
 
2946
    Account *account = getAccount(accountID);
 
2947
    if (account == nullptr) {
 
2948
        DEBUG("Could not find account for account %s, returning sip voip", accountID.c_str());
 
2949
        return SIPVoIPLink::instance();
 
2950
    }
 
2951
 
 
2952
    if (not accountID.empty())
 
2953
        return account->getVoIPLink();
 
2954
    else {
 
2955
        DEBUG("Account id is empty for voip link, returning sip voip");
 
2956
        return SIPVoIPLink::instance();
 
2957
    }
 
2958
}
 
2959
 
 
2960
 
 
2961
void
 
2962
ManagerImpl::sendRegister(const std::string& accountID, bool enable)
 
2963
{
 
2964
    Account* acc = getAccount(accountID);
 
2965
    if (!acc)
 
2966
        return;
 
2967
 
 
2968
    acc->setEnabled(enable);
 
2969
    acc->loadConfig();
 
2970
 
 
2971
    Manager::instance().saveConfig();
 
2972
 
 
2973
    if (acc->isEnabled())
 
2974
        acc->registerVoIPLink();
 
2975
    else
 
2976
        acc->unregisterVoIPLink();
 
2977
}
 
2978
 
 
2979
 
 
2980
AudioLayer*
 
2981
ManagerImpl::getAudioDriver()
 
2982
{
 
2983
    return audiodriver_;
 
2984
}
 
2985
 
 
2986
 
 
2987
MainBuffer &
 
2988
ManagerImpl::getMainBuffer()
 
2989
{
 
2990
    return mainBuffer_;
 
2991
}
 
2992
 
 
2993
Client*
 
2994
ManagerImpl::getClient()
 
2995
{
 
2996
    return &client_;
 
2997
}
 
2998
 
 
2999
#ifdef SFL_VIDEO
 
3000
VideoControls *
 
3001
ManagerImpl::getVideoControls()
 
3002
{
 
3003
    return client_.getVideoControls();
 
3004
}
 
3005
#endif