58
58
#include "numbercleaner.h"
59
59
#include "config/yamlparser.h"
60
60
#include "config/yamlemitter.h"
61
63
#include "audio/alsa/alsalayer.h"
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"
68
#include "dbus/configurationmanager.h"
73
#include "client/configurationmanager.h"
74
#include "client/callmanager.h"
70
#include "dbus/video_controls.h"
77
#include "client/video_controls.h"
73
80
#include "conference.h"
74
#include "scoped_lock.h"
77
83
#include <algorithm>
80
86
#include <iostream>
81
#include <tr1/functional>
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_(),
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)
97
pthread_mutex_init(¤tCallMutex_, 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
103
srand(time(nullptr));
105
106
ManagerImpl::~ManagerImpl()
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(¤tCallMutex_);
115
// Creates a backup of the file at "path" with a .bak suffix appended
116
void make_backup(const std::string &path)
112
void copy_over(const std::string &srcPath, const std::string &destPath)
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();
120
// Creates a backup of the file at "path" with a .bak suffix appended
121
void make_backup(const std::string &path)
123
const std::string backup_path(path + ".bak");
124
copy_over(path, backup_path);
126
// Restore last backup of the configuration file
127
void restore_backup(const std::string &path)
129
const std::string backup_path(path + ".bak");
130
copy_over(backup_path, path);
128
void ManagerImpl::init(const std::string &config_file)
134
bool ManagerImpl::parseConfiguration()
130
path_ = config_file.empty() ? createConfigFile() : config_file;
131
DEBUG("Configuration file path: %s", path_.c_str());
133
bool no_errors = true;
138
FILE *file = fopen(path_.c_str(), "rb");
136
FILE *file = fopen(path_.c_str(), "rb");
139
142
Conf::YamlParser parser(file);
140
143
parser.serializeEvents();
145
148
if (error_count > 0) {
146
149
WARN("Errors while parsing %s", path_.c_str());
150
153
WARN("Config file not found: creating default account map");
151
154
loadDefaultAccountMap();
153
156
} catch (const Conf::YamlParserException &e) {
157
// we only want to close the local file here and then rethrow the exception
165
void ManagerImpl::init(const std::string &config_file)
167
path_ = config_file.empty() ? retrieveConfigPath() : config_file;
168
DEBUG("Configuration file path: %s", path_.c_str());
170
bool no_errors = true;
172
// manager can restart without being recreated (android)
176
no_errors = parseConfiguration();
177
} catch (const Conf::YamlParserException &e) {
154
178
ERROR("%s", e.what());
155
179
no_errors = false;
158
182
// always back up last error-free configuration
160
184
make_backup(path_);
186
// restore previous configuration
187
WARN("Restoring last working configuration");
189
// remove accounts from broken configuration
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();
162
200
initAudioDriver();
165
sfl::ScopedLock lock(audioLayerMutex_);
203
std::lock_guard<std::mutex> lock(audioLayerMutex_);
166
204
if (audiodriver_) {
168
sfl::ScopedLock toneLock(toneMutex_);
206
std::lock_guard<std::mutex> toneLock(toneMutex_);
169
207
telephoneTone_.reset(new TelephoneTone(preferences.getZoneToneChoice(), audiodriver_->getSampleRate()));
171
209
dtmfKey_.reset(new DTMF(getMainBuffer().getInternalSamplingRate()));
190
239
finished_ = true;
191
// Unset signal handlers
192
signal(SIGHUP, SIG_DFL);
193
signal(SIGINT, SIG_DFL);
194
signal(SIGTERM, SIG_DFL);
196
std::vector<std::string> callList(getCallList());
197
DEBUG("Hangup %zu remaining call(s)", callList.size());
199
for (std::vector<std::string>::iterator iter = callList.begin();
200
iter != callList.end(); ++iter)
205
unregisterAllAccounts();
207
SIPVoIPLink::destroy();
243
std::vector<std::string> callList(getCallList());
244
DEBUG("Hangup %zu remaining call(s)", callList.size());
246
for (const auto &item : callList)
251
unregisterAllAccounts();
253
SIPVoIPLink::destroy();
209
IAXVoIPLink::unloadAccountMap();
255
IAXVoIPLink::unloadAccountMap();
213
sfl::ScopedLock lock(audioLayerMutex_);
259
std::lock_guard<std::mutex> lock(audioLayerMutex_);
262
audiodriver_ = nullptr;
266
} catch (const VoipLinkException &err) {
267
ERROR("%s", err.what());
222
271
bool ManagerImpl::isCurrentCall(const std::string& callId) const
384
427
// Connect streams
385
428
addStream(call_id);
387
getMainBuffer().dumpInfo();
389
430
// Start recording if set in preference
390
431
if (audioPreference.getIsAlwaysRecording())
391
setRecordingCall(call_id);
393
// update call state on client side
394
dbus_.getCallManager()->callStateChanged(call_id, "CURRENT");
432
toggleRecordingCall(call_id);
434
client_.getCallManager()->callStateChanged(call_id, "CURRENT");
398
439
void ManagerImpl::checkAudio()
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();
415
// set playback mode to NONE
416
AudioLayer *al = getAudioDriver();
417
if(al) al->setPlaybackMode(AudioLayer::NONE);
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");
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());
560
593
detachParticipant(MainBuffer::DEFAULT_ID);
563
if (isIPToIP(callId))
564
SIPVoIPLink::instance()->offhold(callId);
566
/* Classic call, attached to an account */
567
Call * call = getCallFromCallID(callId);
597
if (isIPToIP(callId))
598
SIPVoIPLink::instance()->offhold(callId);
600
/* Classic call, attached to an account */
601
Call * call = getCallFromCallID(callId);
570
getAccountLink(call->getAccountId())->offhold(callId);
604
getAccountLink(call->getAccountId())->offhold(callId);
608
} catch (const VoipLinkException &e) {
609
ERROR("%s", e.what());
575
dbus_.getCallManager()->callStateChanged(callId, "UNHOLD");
613
client_.getCallManager()->callStateChanged(callId, "UNHOLD");
577
615
if (isConferenceParticipant(callId)) {
578
616
Call *call = getCallFromCallID(callId);
613
650
// remove waiting call in case we make transfer without even answer
614
651
removeWaitingCall(callId);
616
getMainBuffer().dumpInfo();
621
656
void ManagerImpl::transferFailed()
623
dbus_.getCallManager()->transferFailed();
658
client_.getCallManager()->transferFailed();
626
661
void ManagerImpl::transferSucceeded()
628
dbus_.getCallManager()->transferSucceeded();
663
client_.getCallManager()->transferSucceeded();
631
666
bool ManagerImpl::attendedTransfer(const std::string& transferID, const std::string& targetID)
800
834
ParticipantSet participants(conf->getParticipantList());
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);
805
839
// if one call is currently recording, the conference is in state recording
806
840
isRec |= call->isRecording();
813
847
conf->setState(isRec ? Conference::ACTIVE_ATTACHED_REC : Conference::ACTIVE_ATTACHED);
814
dbus_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
849
client_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
931
959
ParticipantSet participants(conf->getParticipantList());
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);
940
967
getMainBuffer().flush(MainBuffer::DEFAULT_ID);
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());
1120
sfl::ScopedLock lock(audioLayerMutex_);
1145
std::lock_guard<std::mutex> lock(audioLayerMutex_);
1122
1147
if (audiodriver_)
1123
1148
conf->setRecordingSmplRate(audiodriver_->getSampleRate());
1126
getMainBuffer().dumpInfo();
1319
1333
// bind to main
1320
1334
getMainBuffer().bindCallID(call_id, MainBuffer::DEFAULT_ID);
1322
sfl::ScopedLock lock(audioLayerMutex_);
1336
std::lock_guard<std::mutex> lock(audioLayerMutex_);
1323
1337
audiodriver_->flushUrgent();
1324
1338
audiodriver_->flushMain();
1327
getMainBuffer().dumpInfo();
1330
1342
void ManagerImpl::removeStream(const std::string& call_id)
1332
1344
DEBUG("Remove audio stream %s", call_id.c_str());
1333
1345
getMainBuffer().unBindAll(call_id);
1334
getMainBuffer().dumpInfo();
1338
1349
void ManagerImpl::saveConfig()
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());
1348
1360
Conf::YamlEmitter emitter(path_.c_str());
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);
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);
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);
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);
1427
1441
dtmfKey_->startTone(code);
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));
1451
// FIXME: do real synchronization
1453
while (not audiodriver_->isStarted() and tries--) {
1454
WARN("Audio layer not ready yet");
1457
audiodriver_->putUrgent(buf);
1439
1460
// TODO Cache the DTMF
1442
1463
// Multi-thread
1443
bool ManagerImpl::incomingCallWaiting() const
1464
bool ManagerImpl::incomingCallsWaiting()
1445
return nbIncomingWaitingCall_ > 0;
1466
std::lock_guard<std::mutex> m(waitingCallsMutex_);
1467
return not waitingCalls_.empty();
1448
1470
void ManagerImpl::addWaitingCall(const std::string& id)
1450
sfl::ScopedLock m(waitingCallMutex_);
1451
waitingCall_.insert(id);
1452
nbIncomingWaitingCall_++;
1472
std::lock_guard<std::mutex> m(waitingCallsMutex_);
1473
waitingCalls_.insert(id);
1455
1476
void ManagerImpl::removeWaitingCall(const std::string& id)
1457
sfl::ScopedLock m(waitingCallMutex_);
1459
if (waitingCall_.erase(id))
1460
nbIncomingWaitingCall_--;
1478
std::lock_guard<std::mutex> m(waitingCallsMutex_);
1479
waitingCalls_.erase(id);
1463
1482
///////////////////////////////////////////////////////////////////////////////
1509
1529
ParticipantSet participants(conf->getParticipantList());
1511
for (ParticipantSet::const_iterator iter_p = participants.begin();
1512
iter_p != participants.end(); ++iter_p) {
1531
for (const auto &item_p : participants) {
1514
if (*iter_p == callID)
1533
if (item_p == callID)
1517
std::string accountId(getAccountFromCall(*iter_p));
1536
std::string accountId(getAccountFromCall(item_p));
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());
1521
1540
Account *account = getAccount(accountId);
1613
1630
DEBUG("Peer answered call %s", id.c_str());
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))
1619
// set playback mode to VOICE
1620
AudioLayer *al = getAudioDriver();
1621
if(al) al->setPlaybackMode(AudioLayer::VOICE);
1624
1636
// Connect audio streams
1628
sfl::ScopedLock lock(audioLayerMutex_);
1640
std::lock_guard<std::mutex> lock(audioLayerMutex_);
1629
1641
audiodriver_->flushMain();
1630
1642
audiodriver_->flushUrgent();
1633
1645
if (audioPreference.getIsAlwaysRecording())
1634
setRecordingCall(id);
1646
toggleRecordingCall(id);
1636
dbus_.getCallManager()->callStateChanged(id, "CURRENT");
1648
client_.getCallManager()->callStateChanged(id, "CURRENT");
1639
1651
//THREAD=VoIP Call=Outgoing
1684
/* Broadcast a signal over DBus */
1685
dbus_.getCallManager()->callStateChanged(call_id, "HUNGUP");
1692
client_.getCallManager()->callStateChanged(call_id, "HUNGUP");
1687
1694
removeWaitingCall(call_id);
1695
if (not incomingCallsWaiting())
1689
1698
removeStream(call_id);
1693
1702
void ManagerImpl::callBusy(const std::string& id)
1695
DEBUG("Call %s busy", id.c_str());
1696
dbus_.getCallManager()->callStateChanged(id, "BUSY");
1704
client_.getCallManager()->callStateChanged(id, "BUSY");
1698
1706
if (isCurrentCall(id)) {
1699
1707
playATone(Tone::TONE_BUSY);
1847
1863
audioLayerSmplr = audiodriver_->getSampleRate();
1866
bool doFallback = false;
1851
sfl::ScopedLock m(toneMutex_);
1869
std::lock_guard<std::mutex> m(toneMutex_);
1853
if (audiofile_.get()) {
1854
dbus_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath());
1872
client_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath());
1855
1873
audiofile_.reset();
1859
if (ringchoice.find(".wav") != std::string::npos)
1860
audiofile_.reset(new WaveFile(ringchoice, audioLayerSmplr));
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);
1866
throw AudioFileException("Couldn't guess an appropriate decoder");
1868
audiofile_.reset(new RawFile(ringchoice, static_cast<sfl::AudioCodec *>(codec), audioLayerSmplr));
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
1873
1882
} // leave mutex
1875
sfl::ScopedLock lock(audioLayerMutex_);
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();
1880
1894
AudioLoop* ManagerImpl::getTelephoneTone()
1882
sfl::ScopedLock m(toneMutex_);
1883
if (telephoneTone_.get())
1896
std::lock_guard<std::mutex> m(toneMutex_);
1884
1898
return telephoneTone_->getCurrentTone();
1890
1904
ManagerImpl::getTelephoneFile()
1892
sfl::ScopedLock m(toneMutex_);
1906
std::lock_guard<std::mutex> m(toneMutex_);
1893
1907
return audiofile_.get();
2062
2080
return audioPreference.setIsAlwaysRecording(isAlwaysRec);
2065
void ManagerImpl::setRecordingCall(const std::string& id)
2083
bool ManagerImpl::toggleRecordingCall(const std::string& id)
2067
Recordable* rec = NULL;
2085
Recordable* rec = nullptr;
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);
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;
2118
sfl::ScopedLock m(toneMutex_);
2138
std::lock_guard<std::mutex> m(toneMutex_);
2120
if (audiofile_.get()) {
2121
dbus_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath());
2141
client_.getCallManager()->recordPlaybackStopped(audiofile_->getFilePath());
2122
2142
audiofile_.reset();
2126
audiofile_.reset(new WaveFile(filepath, sampleRate));
2127
audiofile_.get()->setIsRecording(true);
2146
updateAudioFile(filepath, sampleRate);
2128
2149
} catch (const AudioFileException &e) {
2129
ERROR("Exception: %s", e.what());
2150
WARN("Audio file error: %s", e.what());
2131
2153
} // release toneMutex
2133
sfl::ScopedLock lock(audioLayerMutex_);
2134
audiodriver_->startStream();
2156
std::lock_guard<std::mutex> lock(audioLayerMutex_);
2157
audiodriver_->startStream();
2139
2163
void ManagerImpl::recordingPlaybackSeek(const double value)
2141
sfl::ScopedLock m(toneMutex_);
2142
if (audiofile_.get())
2165
std::lock_guard<std::mutex> m(toneMutex_);
2143
2167
audiofile_.get()->seek(value);
2219
std::string ManagerImpl::getNoiseSuppressState() const
2221
return audioPreference.getNoiseReduce() ? "enabled" : "disabled";
2224
void ManagerImpl::setNoiseSuppressState(const std::string &state)
2226
audioPreference.setNoiseReduce(state == "enabled");
2229
bool ManagerImpl::getEchoCancelState() const
2231
return audioPreference.getEchoCancel();
2234
void ManagerImpl::setEchoCancelState(const std::string &state)
2236
audioPreference.setEchoCancel(state == "enabled");
2241
bool ManagerImpl::getNoiseSuppressState() const
2243
return audioPreference.getNoiseReduce();
2246
void ManagerImpl::setNoiseSuppressState(bool state)
2248
audioPreference.setNoiseReduce(state);
2251
bool ManagerImpl::isAGCEnabled() const
2253
return audioPreference.isAGCEnabled();
2256
void ManagerImpl::setAGCState(bool state)
2258
audioPreference.setAGCState(state);
2260
2282
void ManagerImpl::audioSamplingRateChanged(int samplerate)
2262
sfl::ScopedLock lock(audioLayerMutex_);
2284
std::lock_guard<std::mutex> lock(audioLayerMutex_);
2264
2286
if (!audiodriver_) {
2265
2287
DEBUG("No Audio driver initialized");
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();
2272
if (currentSamplerate >= samplerate) {
2294
if (currentSamplerate == samplerate) {
2273
2295
DEBUG("No need to update audio layer sampling rate");
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())
2355
v.push_back(iter->second->getAccountID());
2377
v.push_back(item.second->getAccountID());
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())
2363
AccountMap::const_iterator account_iter = allAccounts.find(*iter);
2385
AccountMap::const_iterator account_iter = allAccounts.find(item);
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
2376
// Default account used to get default parameters if requested by client (to build new account)
2377
static const SIPAccount DEFAULT_ACCOUNT("default");
2379
if (accountID.empty()) {
2380
DEBUG("Returning default account settings");
2381
return DEFAULT_ACCOUNT.getAccountDetails();
2384
2398
Account * account = getAccount(accountID);
2387
2401
return account->getAccountDetails();
2389
ERROR("Get account details on a non-existing accountID %s. Returning default", accountID.c_str());
2390
return DEFAULT_ACCOUNT.getAccountDetails();
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>();
2402
2417
Account* account = getAccount(accountID);
2404
if (account == NULL) {
2419
if (account == nullptr) {
2405
2420
ERROR("Could not find account %s", accountID.c_str());
2424
// Ignore if nothing has changed
2425
if (details == account->getAccountDetails())
2428
// Unregister before modifying any account information
2429
account->unregisterVoIPLink();
2409
2430
account->setAccountDetails(details);
2411
2432
// Serialize configuration to disk once it is done
2417
2438
account->unregisterVoIPLink();
2419
2440
// Update account details to the client side
2420
dbus_.getConfigurationManager()->accountsChanged();
2441
client_.getConfigurationManager()->accountsChanged();
2424
2445
ManagerImpl::addAccount(const std::map<std::string, std::string>& details)
2426
2447
/** @todo Deal with both the accountMap_ and the Configuration */
2427
std::stringstream accountID;
2429
accountID << "Account:" << time(NULL);
2430
std::string newAccountID(accountID.str());
2449
std::string newAccountID;
2451
const std::vector<std::string> accountList(getAccountList());
2454
std::stringstream accountID;
2455
accountID << "Account:" << rand();
2456
newAccountID = accountID.str();
2457
} while (std::find(accountList.begin(), accountList.end(), newAccountID)
2458
!= accountList.end());
2432
2460
// Get the type
2462
2490
newAccount->setAccountDetails(details);
2464
// Add the newly created account in the account order list
2465
std::string accountList(preferences.getAccountOrder());
2467
newAccountID += "/";
2468
if (not accountList.empty()) {
2469
// Prepend the new account
2470
accountList.insert(0, newAccountID);
2471
preferences.setAccountOrder(accountList);
2473
accountList = newAccountID;
2474
preferences.setAccountOrder(accountList);
2477
DEBUG("Getting accounts: %s", accountList.c_str());
2492
preferences.addAccount(newAccountID);
2479
2494
newAccount->registerVoIPLink();
2483
dbus_.getConfigurationManager()->accountsChanged();
2485
return accountID.str();
2498
client_.getConfigurationManager()->accountsChanged();
2500
return newAccountID;
2503
void ManagerImpl::removeAccounts()
2505
for (const auto &acc : getAccountList())
2488
2509
void ManagerImpl::removeAccount(const std::string& accountID)
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)
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)
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; };
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") {
2674
using std::tr1::placeholders::_1;
2702
const std::string accountOrder = preferences.getAccountOrder();
2704
AccountMap &sipAccounts = SIPVoIPLink::instance()->getAccounts();
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);
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);
2688
2714
return errorCount;
2691
2717
void ManagerImpl::registerAllAccounts()
2693
std::for_each(SIPVoIPLink::instance()->getAccounts().begin(), SIPVoIPLink::instance()->getAccounts().end(), registerAccount);
2719
for (auto &a : SIPVoIPLink::instance()->getAccounts())
2695
std::for_each(IAXVoIPLink::getAccounts().begin(), IAXVoIPLink::getAccounts().end(), registerAccount);
2722
for (auto &a : IAXVoIPLink::getAccounts())
2699
2727
void ManagerImpl::unregisterAllAccounts()
2701
std::for_each(SIPVoIPLink::instance()->getAccounts().begin(), SIPVoIPLink::instance()->getAccounts().end(), unregisterAccount);
2729
for (auto &a : SIPVoIPLink::instance()->getAccounts())
2730
unregisterAccount(a);
2703
std::for_each(IAXVoIPLink::getAccounts().begin(), IAXVoIPLink::getAccounts().end(), unregisterAccount);
2732
for (auto &a : IAXVoIPLink::getAccounts())
2733
unregisterAccount(a);
2733
2763
ManagerImpl::getAccount(const std::string& accountID) const
2735
Account *account = NULL;
2765
Account *account = nullptr;
2737
2767
account = getSipAccount(accountID);
2768
if (account != nullptr)
2739
2769
return account;
2742
2772
account = getIaxAccount(accountID);
2773
if (account != nullptr)
2744
2774
return account;
2751
2781
ManagerImpl::getSipAccount(const std::string& accountID) const
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);
2889
2919
void ManagerImpl::startAudioDriverStream()
2891
sfl::ScopedLock lock(audioLayerMutex_);
2921
std::lock_guard<std::mutex> lock(audioLayerMutex_);
2892
2922
audiodriver_->startStream();
2926
ManagerImpl::registerAccounts()
2928
AccountMap allAccounts(getAllAccounts());
2930
for (auto &item : allAccounts) {
2931
Account *a = item.second;
2939
a->registerVoIPLink();
2944
VoIPLink* ManagerImpl::getAccountLink(const std::string& accountID)
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();
2952
if (not accountID.empty())
2953
return account->getVoIPLink();
2955
DEBUG("Account id is empty for voip link, returning sip voip");
2956
return SIPVoIPLink::instance();
2962
ManagerImpl::sendRegister(const std::string& accountID, bool enable)
2964
Account* acc = getAccount(accountID);
2968
acc->setEnabled(enable);
2971
Manager::instance().saveConfig();
2973
if (acc->isEnabled())
2974
acc->registerVoIPLink();
2976
acc->unregisterVoIPLink();
2981
ManagerImpl::getAudioDriver()
2983
return audiodriver_;
2988
ManagerImpl::getMainBuffer()
2994
ManagerImpl::getClient()
3001
ManagerImpl::getVideoControls()
3003
return client_.getVideoControls();