blob: 3abac156d8b86ac7509384373be02ce7c30b9529 [file] [log] [blame]
Nicolas Jager6e30ad82016-08-26 13:00:27 -04001/**************************************************************************
atraczykb724d332016-08-30 15:25:59 -04002* Copyright (C) 2016 by Savoir-faire Linux *
3* Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
4* Author: Traczyk Andreas <traczyk.andreas@savoirfairelinux.com> *
5* *
6* This program is free software; you can redistribute it and/or modify *
7* it under the terms of the GNU General Public License as published by *
8* the Free Software Foundation; either version 3 of the License, or *
9* (at your option) any later version. *
10* *
11* This program is distributed in the hope that it will be useful, *
12* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14* GNU General Public License for more details. *
15* *
16* You should have received a copy of the GNU General Public License *
17* along with this program. If not, see <http://www.gnu.org/licenses/>. *
18**************************************************************************/
19#include "pch.h"
20
21/* daemon */
22#include <dring.h>
23#include "callmanager_interface.h"
24#include "configurationmanager_interface.h"
25#include "presencemanager_interface.h"
26#include "fileutils.h"
atraczykb724d332016-08-30 15:25:59 -040027#include "account_schema.h"
atraczyk196936e2016-09-02 15:31:53 -040028#include "account_const.h"
atraczykb724d332016-08-30 15:25:59 -040029
30#include "SmartPanel.xaml.h"
31
32using namespace Windows::ApplicationModel::Core;
33using namespace Windows::Storage;
34using namespace Windows::UI::Core;
35
36using namespace RingClientUWP;
37using namespace RingClientUWP::Utils;
Nicolas Jager655df542016-08-31 10:24:47 -040038using namespace RingClientUWP::ViewModel;
atraczykb724d332016-08-30 15:25:59 -040039
40void
41debugOutputWrapper(const std::string& str)
42{
43 MSG_(str);
44}
45
46void
47RingClientUWP::RingD::reloadAccountList()
48{
49 RingClientUWP::ViewModel::AccountsViewModel::instance->clearAccountList();
50 std::vector<std::string> accountList = DRing::getAccountList();
51 std::vector<std::string>::reverse_iterator rit = accountList.rbegin();
52 for (; rit != accountList.rend(); ++rit) {
53 std::map<std::string,std::string> accountDetails = DRing::getAccountDetails(*rit);
54 std::string ringID(accountDetails.find(ring::Conf::CONFIG_ACCOUNT_USERNAME)->second);
55 if(!ringID.empty())
56 ringID = ringID.substr(5);
57 RingClientUWP::ViewModel::AccountsViewModel::instance->add(
58 accountDetails.find(ring::Conf::CONFIG_ACCOUNT_ALIAS)->second, //name
59 ringID, //ringid
atraczyk797fa1a2016-08-31 09:55:53 -040060 accountDetails.find(ring::Conf::CONFIG_ACCOUNT_TYPE)->second, //type
61 *rit);
atraczykb724d332016-08-30 15:25:59 -040062 }
63 // load user preferences
64 Configuration::UserPreferences::instance->load();
65}
66
Nicolas Jager655df542016-08-31 10:24:47 -040067/* nb: send message during conversation not chat video message */
68void RingClientUWP::RingD::sendAccountTextMessage(String^ message)
69{
70 /* account id */
71 auto accountId = AccountsViewModel::instance->selectedAccount->accountID_;
72 std::wstring accountId2(accountId->Begin());
73 std::string accountId3(accountId2.begin(), accountId2.end());
74
75 /* recipient */
76 auto contact = ContactsViewModel::instance->selectedContact;
77 auto toRingId = contact->ringID_;
78 std::wstring toRingId2(toRingId->Begin());
79 std::string toRingId3(toRingId2.begin(), toRingId2.end());
80
81 /* payload(s) */
82 std::wstring message2(message->Begin());
83 std::string message3(message2.begin(), message2.end());
84 std::map<std::string, std::string> payloads;
85 payloads["text/plain"] = message3;
86
87 /* daemon */
88 auto sent = DRing::sendAccountTextMessage(accountId3, toRingId3, payloads);
89
90 /* conversation */
91 if (sent) {
92 contact->_conversation->addMessage(""/* date not yet used*/, MSG_FROM_ME, message);
atraczykf5be5462016-08-31 14:23:06 -040093
94 /* save contacts conversation to disk */
95 contact->saveConversationToFile();
96
Nicolas Jager655df542016-08-31 10:24:47 -040097 } else {
98 WNG_("message not sent, see daemon outputs");
99 }
100}
101
atraczykb724d332016-08-30 15:25:59 -0400102void
atraczyk196936e2016-09-02 15:31:53 -0400103RingD::createRINGAccount(String^ alias)
104{
Nicolas Jagerf6a10322016-09-06 08:17:49 -0400105 // refactoring : create a dedicated class constructor task and removes accountName from RingD
atraczyk196936e2016-09-02 15:31:53 -0400106 accountName = Utils::toString(alias);
107 tasksList_.push(ref new RingD::Task(Request::AddRingAccount));
108}
109
110void
111RingD::createSIPAccount(String^ alias)
112{
Nicolas Jagerf6a10322016-09-06 08:17:49 -0400113 // refactoring : create a dedicated class constructor task and removes accountName from RingD
atraczyk196936e2016-09-02 15:31:53 -0400114 accountName = Utils::toString(alias);
115 tasksList_.push(ref new RingD::Task(Request::AddSIPAccount));
116}
117
Nicolas Jagerf6a10322016-09-06 08:17:49 -0400118void RingClientUWP::RingD::refuseIncommingCall(Call^ call)
119{
120 tasksList_.push(ref new RingD::Task(Request::RefuseIncommingCall, call));
121}
122
123void RingClientUWP::RingD::acceptIncommingCall(Call^ call)
124{
125 tasksList_.push(ref new RingD::Task(Request::AcceptIncommingCall, call));
126}
127
atraczyk196936e2016-09-02 15:31:53 -0400128void
atraczykb724d332016-08-30 15:25:59 -0400129RingClientUWP::RingD::startDaemon()
130{
Nicolas Jagerd76940f2016-08-31 14:44:04 -0400131 // TODO (during refactoring) : use namespace
132 /* clear the calls list and instantiate the singleton (required) */
133 RingClientUWP::ViewModel::CallsViewModel::instance->clearCallsList();
134
atraczykb724d332016-08-30 15:25:59 -0400135 create_task([&]()
136 {
137 using SharedCallback = std::shared_ptr<DRing::CallbackWrapperBase>;
138 using namespace std::placeholders;
139
140 std::map<std::string, SharedCallback> callHandlers = {
141 // use IncomingCall only to register the call client sided, use StateChange to determine the impact on the UI
142 DRing::exportable_callback<DRing::CallSignal::IncomingCall>([this](
143 const std::string& accountId,
144 const std::string& callId,
145 const std::string& from)
146 {
147 MSG_("<IncomingCall>");
148 MSG_("accountId = " + accountId);
149 MSG_("callId = " + callId);
150 MSG_("from = " + from);
151
152 auto accountId2 = toPlatformString(accountId);
153 auto callId2 = toPlatformString(callId);
154 auto from2 = toPlatformString(from);
155
Nicolas Jagerd76940f2016-08-31 14:44:04 -0400156 CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
157 CoreDispatcherPriority::Normal, ref new DispatchedHandler([=]()
158 {
159 incomingCall(accountId2, callId2, from2);
160 stateChange(callId2, "incoming call", 0);
161 }));
atraczykb724d332016-08-30 15:25:59 -0400162 }),
163 DRing::exportable_callback<DRing::CallSignal::StateChange>([this](
Nicolas Jagerd76940f2016-08-31 14:44:04 -0400164 const std::string& callId,
165 const std::string& state,
166 int code)
atraczykb724d332016-08-30 15:25:59 -0400167 {
168 MSG_("<StateChange>");
169 MSG_("callId = " + callId);
170 MSG_("state = " + state);
171 MSG_("code = " + std::to_string(code));
172
173 auto callId2 = toPlatformString(callId);
174 auto state2 = toPlatformString(state);
175
atraczykb724d332016-08-30 15:25:59 -0400176
Nicolas Jagerd76940f2016-08-31 14:44:04 -0400177 CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
178 CoreDispatcherPriority::Low, ref new DispatchedHandler([=]()
179 {
180 stateChange(callId2, state2, code);
181 }));
atraczykb724d332016-08-30 15:25:59 -0400182 }),
Nicolas Jager6e30ad82016-08-26 13:00:27 -0400183 DRing::exportable_callback<DRing::ConfigurationSignal::IncomingAccountMessage>([&](
Nicolas Jagerd76940f2016-08-31 14:44:04 -0400184 const std::string& accountId,
185 const std::string& from,
186 const std::map<std::string, std::string>& payloads)
atraczykb724d332016-08-30 15:25:59 -0400187 {
188 MSG_("<IncomingAccountMessage>");
189 MSG_("accountId = " + accountId);
190 MSG_("from = " + from);
191
Nicolas Jager6e30ad82016-08-26 13:00:27 -0400192 auto accountId2 = toPlatformString(accountId);
193 auto from2 = toPlatformString(from);
194
atraczykb724d332016-08-30 15:25:59 -0400195 for (auto i : payloads) {
196 MSG_("payload = " + i.second);
197 auto payload = Utils::toPlatformString(i.second);
Nicolas Jager6e30ad82016-08-26 13:00:27 -0400198 CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
199 CoreDispatcherPriority::Low, ref new DispatchedHandler([=]()
200 {
201 incomingAccountMessage(accountId2, from2, payload);
202 }));
atraczykb724d332016-08-30 15:25:59 -0400203 }
204 }),
atraczyk196936e2016-09-02 15:31:53 -0400205 DRing::exportable_callback<DRing::ConfigurationSignal::RegistrationStateChanged>([this](
Nicolas Jagerf6a10322016-09-06 08:17:49 -0400206 const std::string& account_id, const std::string& state,
207 int detailsCode, const std::string& detailsStr)
atraczyk196936e2016-09-02 15:31:53 -0400208 {
209 MSG_("<RegistrationStateChanged>: ID = " + account_id + "state = " + state);
210 if (state == DRing::Account::States::UNREGISTERED) {
211 CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,
Nicolas Jagerf6a10322016-09-06 08:17:49 -0400212 ref new DispatchedHandler([=]() {
atraczyk196936e2016-09-02 15:31:53 -0400213 reloadAccountList();
214 }));
215 }
216 }),
atraczykb724d332016-08-30 15:25:59 -0400217 DRing::exportable_callback<DRing::ConfigurationSignal::AccountsChanged>([this]()
218 {
219 CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,
Nicolas Jager655df542016-08-31 10:24:47 -0400220 ref new DispatchedHandler([=]() {
atraczykb724d332016-08-30 15:25:59 -0400221 reloadAccountList();
222 }));
223 })
224 };
225
226 registerCallHandlers(callHandlers);
227
228 std::map<std::string, SharedCallback> dringDebugOutHandler;
229 dringDebugOutHandler.insert(DRing::exportable_callback<DRing::Debug::MessageSend>
230 (std::bind(&debugOutputWrapper, _1)));
231 registerCallHandlers(dringDebugOutHandler);
232
233 std::map<std::string, SharedCallback> getAppPathHandler =
234 {
235 DRing::exportable_callback<DRing::ConfigurationSignal::GetAppDataPath>
236 ([this](std::vector<std::string>* paths) {
237 paths->emplace_back(localFolder_);
238 })
239 };
240 registerCallHandlers(getAppPathHandler);
241
Nicolas Jageraef65722016-09-06 08:30:14 -0400242 DRing::init(static_cast<DRing::InitFlag>(DRing::DRING_FLAG_CONSOLE_LOG |
Nicolas Jagerf6a10322016-09-06 08:17:49 -0400243 DRing::DRING_FLAG_DEBUG));
atraczykb724d332016-08-30 15:25:59 -0400244
245 if (!DRing::start()) {
246 ERR_("\ndaemon didn't start.\n");
247 return;
248 }
249 else {
250 if (!hasConfig)
251 {
atraczyk4464ace2016-09-01 09:37:37 -0400252 tasksList_.push(ref new RingD::Task(Request::AddRingAccount));
253 tasksList_.push(ref new RingD::Task(Request::AddSIPAccount));
atraczykb724d332016-08-30 15:25:59 -0400254 }
255 else {
256 CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,
Nicolas Jager655df542016-08-31 10:24:47 -0400257 ref new DispatchedHandler([=]() {
atraczykb724d332016-08-30 15:25:59 -0400258 reloadAccountList();
259 }));
260 }
261 while (true) {
262 DRing::pollEvents();
263 Sleep(1000);
264 dequeueTasks();
265 }
266 DRing::fini();
267 }
268 });
269}
270
271RingD::RingD()
272{
273 localFolder_ = Utils::toString(ApplicationData::Current->LocalFolder->Path);
274}
275
276void
277RingD::dequeueTasks()
278{
279 for (int i = 0; i < tasksList_.size(); i++) {
280 auto task = tasksList_.front();
Nicolas Jagerf6a10322016-09-06 08:17:49 -0400281 auto request = dynamic_cast<Task^>(task)->request;
282 switch (request) {
atraczykb724d332016-08-30 15:25:59 -0400283 case Request::None:
atraczyk4464ace2016-09-01 09:37:37 -0400284 break;
285 case Request::AddRingAccount:
Nicolas Jagerd76940f2016-08-31 14:44:04 -0400286 {
287 std::map<std::string, std::string> ringAccountDetails;
288 ringAccountDetails.insert(std::make_pair(ring::Conf::CONFIG_ACCOUNT_ALIAS, accountName));
289 ringAccountDetails.insert(std::make_pair(ring::Conf::CONFIG_ACCOUNT_TYPE,"RING"));
290 DRing::addAccount(ringAccountDetails);
291 }
292 break;
atraczyk4464ace2016-09-01 09:37:37 -0400293 case Request::AddSIPAccount:
Nicolas Jagerd76940f2016-08-31 14:44:04 -0400294 {
295 std::map<std::string, std::string> sipAccountDetails;
296 sipAccountDetails.insert(std::make_pair(ring::Conf::CONFIG_ACCOUNT_ALIAS, accountName + " (SIP)"));
297 sipAccountDetails.insert(std::make_pair(ring::Conf::CONFIG_ACCOUNT_TYPE,"SIP"));
298 DRing::addAccount(sipAccountDetails);
299 }
300 break;
Nicolas Jagerf6a10322016-09-06 08:17:49 -0400301 case Request::RefuseIncommingCall:
302 {
303 auto callId = task->_call->callId;
304 auto callId2 = Utils::toString(callId);
305 DRing::refuse(callId2);
306 }
307 break;
308 case Request::AcceptIncommingCall:
309 {
310 auto callId = task->_call->callId;
311 auto callId2 = Utils::toString(callId);
312 DRing::accept(callId2);
313 }
314 break;
atraczykb724d332016-08-30 15:25:59 -0400315 default:
316 break;
317 }
318 tasksList_.pop();
319 }
320}