RingD.cpp 34.2 KB
Newer Older
1
/**************************************************************************
atraczyk's avatar
atraczyk committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
* Copyright (C) 2016 by Savoir-faire Linux                                *
* Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com>              *
* Author: Traczyk Andreas <traczyk.andreas@savoirfairelinux.com>          *
*                                                                         *
* This program is free software; you can redistribute it and/or modify    *
* it under the terms of the GNU General Public License as published by    *
* the Free Software Foundation; either version 3 of the License, or       *
* (at your option) any later version.                                     *
*                                                                         *
* This program is distributed in the hope that it will be useful,         *
* but WITHOUT ANY WARRANTY; without even the implied warranty of          *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
* GNU General Public License for more details.                            *
*                                                                         *
* You should have received a copy of the GNU General Public License       *
* along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
**************************************************************************/
#include "pch.h"

/* daemon */
#include <dring.h>
#include "callmanager_interface.h"
#include "configurationmanager_interface.h"
#include "presencemanager_interface.h"
atraczyk's avatar
atraczyk committed
26
#include "videomanager_interface.h"
atraczyk's avatar
atraczyk committed
27 28
#include "fileutils.h"
#include "account_schema.h"
atraczyk's avatar
atraczyk committed
29
#include "account_const.h"
30 31
#include "string_utils.h" // used to get some const expr like TRUE_STR

atraczyk's avatar
atraczyk committed
32 33 34 35 36 37

#include "SmartPanel.xaml.h"

using namespace Windows::ApplicationModel::Core;
using namespace Windows::Storage;
using namespace Windows::UI::Core;
atraczyk's avatar
atraczyk committed
38 39 40
using namespace Windows::Media;
using namespace Windows::Media::MediaProperties;
using namespace Windows::Media::Capture;
atraczyk's avatar
atraczyk committed
41 42 43

using namespace RingClientUWP;
using namespace RingClientUWP::Utils;
Nicolas Jager's avatar
Nicolas Jager committed
44
using namespace RingClientUWP::ViewModel;
atraczyk's avatar
atraczyk committed
45

atraczyk's avatar
atraczyk committed
46 47
using namespace Windows::System;

atraczyk's avatar
atraczyk committed
48 49 50
void
RingClientUWP::RingD::reloadAccountList()
{
51
    //RingClientUWP::ViewModel::AccountsViewModel::instance->clearAccountList();
Nicolas Jager's avatar
Nicolas Jager committed
52

atraczyk's avatar
atraczyk committed
53
    std::vector<std::string> accountList = DRing::getAccountList();
54 55 56 57 58 59 60

    /* if for any reason there is no account at all, screen the wizard */
    if (accountList.size() == 0) {
        summonWizard();
        return;
    }

atraczyk's avatar
atraczyk committed
61
    std::vector<std::string>::reverse_iterator rit = accountList.rbegin();
Nicolas Jager's avatar
Nicolas Jager committed
62

atraczyk's avatar
atraczyk committed
63 64
    for (; rit != accountList.rend(); ++rit) {
        std::map<std::string,std::string> accountDetails = DRing::getAccountDetails(*rit);
65

66
        auto type = accountDetails.find(DRing::Account::ConfProperties::TYPE)->second;
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
        if (type == "RING") {
            auto  ringID = accountDetails.find(DRing::Account::ConfProperties::USERNAME)->second;
            if (!ringID.empty())
                ringID = ringID.substr(5);

            bool upnpState = (accountDetails.find(DRing::Account::ConfProperties::UPNP_ENABLED)->second == ring::TRUE_STR)
                             ? true
                             : false;
            auto alias = accountDetails.find(DRing::Account::ConfProperties::ALIAS)->second;
            auto deviceId = accountDetails.find(DRing::Account::ConfProperties::RING_DEVICE_ID)->second;
            auto accountId = *rit;

            auto account = AccountsViewModel::instance->findItem(Utils::toPlatformString(accountId));

            if (account) {
                account->name_ = Utils::toPlatformString(alias);
                account->_upnpState = upnpState;
                account->accountType_ = Utils::toPlatformString(type);
                account->ringID_ = Utils::toPlatformString(ringID);
                accountUpdated(account);
            }
            else {
                RingClientUWP::ViewModel::AccountsViewModel::instance->addRingAccount(alias, ringID, accountId, deviceId, upnpState);
            }
91
        }
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
        else { /* SIP */
            auto alias = accountDetails.find(DRing::Account::ConfProperties::ALIAS)->second;
            auto accountId = *rit;
            auto sipHostname = accountDetails.find(DRing::Account::ConfProperties::HOSTNAME)->second;
            auto sipUsername = accountDetails.find(DRing::Account::ConfProperties::USERNAME)->second;
            auto sipPassword = accountDetails.find(DRing::Account::ConfProperties::PASSWORD)->second;

            auto account = AccountsViewModel::instance->findItem(Utils::toPlatformString(accountId));

            if (account) {
                account->name_ = Utils::toPlatformString(alias);
                account->accountType_ = Utils::toPlatformString(type);
                account->_sipHostname = Utils::toPlatformString(sipHostname);
                account->_sipUsername = Utils::toPlatformString(sipUsername);
                account->_sipPassword = Utils::toPlatformString(sipPassword);
                accountUpdated(account);
            }
            else {
                RingClientUWP::ViewModel::AccountsViewModel::instance->addSipAccount(alias, accountId, sipHostname, sipUsername, sipPassword);
            }
112

113 114 115
            sipPassword = ""; // avoid to keep password in memory

        }
atraczyk's avatar
atraczyk committed
116
    }
Nicolas Jager's avatar
Nicolas Jager committed
117

atraczyk's avatar
atraczyk committed
118 119 120 121
    // load user preferences
    Configuration::UserPreferences::instance->load();
}

Nicolas Jager's avatar
Nicolas Jager committed
122 123 124 125
/* nb: send message during conversation not chat video message */
void RingClientUWP::RingD::sendAccountTextMessage(String^ message)
{
    /* account id */
Nicolas Jager's avatar
Nicolas Jager committed
126
    auto accountId = AccountListItemsViewModel::instance->_selectedItem->_account->accountID_;
Nicolas Jager's avatar
Nicolas Jager committed
127 128 129 130
    std::wstring accountId2(accountId->Begin());
    std::string accountId3(accountId2.begin(), accountId2.end());

    /* recipient */
Nicolas Jager's avatar
Nicolas Jager committed
131 132
    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
    auto contact = item->_contact;
Nicolas Jager's avatar
Nicolas Jager committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    auto toRingId = contact->ringID_;
    std::wstring toRingId2(toRingId->Begin());
    std::string toRingId3(toRingId2.begin(), toRingId2.end());

    /* payload(s) */
    std::wstring message2(message->Begin());
    std::string message3(message2.begin(), message2.end());
    std::map<std::string, std::string> payloads;
    payloads["text/plain"] = message3;

    /* daemon */
    auto sent = DRing::sendAccountTextMessage(accountId3, toRingId3, payloads);

    /* conversation */
    if (sent) {
        contact->_conversation->addMessage(""/* date not yet used*/, MSG_FROM_ME, message);
149 150 151 152

        /* save contacts conversation to disk */
        contact->saveConversationToFile();

Nicolas Jager's avatar
Nicolas Jager committed
153 154 155 156 157
    } else {
        WNG_("message not sent, see daemon outputs");
    }
}

158 159 160 161
// send message during video call
void RingClientUWP::RingD::sendSIPTextMessage(String^ message)
{
    /* account id */
Nicolas Jager's avatar
Nicolas Jager committed
162
    auto accountId = AccountListItemsViewModel::instance->_selectedItem->_account->accountID_;
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    std::wstring accountId2(accountId->Begin());
    std::string accountId3(accountId2.begin(), accountId2.end());

    /* call */
    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
    auto callId = item->_callId;
    std::wstring callId2(callId->Begin());
    std::string callId3(callId2.begin(), callId2.end());

    /* recipient */
    auto contact = item->_contact;

    /* payload(s) */
    std::wstring message2(message->Begin());
    std::string message3(message2.begin(), message2.end());
    std::map<std::string, std::string> payloads;
    payloads["text/plain"] = message3;

    /* daemon */
    DRing::sendTextMessage(callId3, payloads, accountId3, true /*not used*/);
    contact->_conversation->addMessage(""/* date not yet used*/, MSG_FROM_ME, message);
    contact->saveConversationToFile();
}

atraczyk's avatar
atraczyk committed
187
void
188
RingD::createRINGAccount(String^ alias, String^ archivePassword, bool upnp)
atraczyk's avatar
atraczyk committed
189
{
190 191 192 193 194
    editModeOn_ = true;

    auto frame = dynamic_cast<Frame^>(Window::Current->Content);
    dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(true, true);

195 196 197 198 199 200 201
    auto task = ref new RingD::Task(Request::AddRingAccount);

    task->_alias = alias;
    task->_password = archivePassword;
    task->_upnp = upnp;

    tasksList_.push(task);
atraczyk's avatar
atraczyk committed
202 203 204
}

void
205
RingD::createSIPAccount(String^ alias, String^ sipPassword, String^ sipHostname, String^ sipusername)
atraczyk's avatar
atraczyk committed
206
{
207 208 209 210 211
    editModeOn_ = true;

    auto frame = dynamic_cast<Frame^>(Window::Current->Content);
    dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(true, true);

212 213 214 215 216 217 218 219
    auto task = ref new RingD::Task(Request::AddSIPAccount);

    task->_alias = alias;
    task->_sipPassword = sipPassword;
    task->_sipHostname = sipHostname;
    task->_sipUsername = sipusername;

    tasksList_.push(task);
atraczyk's avatar
atraczyk committed
220 221
}

222
void RingClientUWP::RingD::refuseIncommingCall(String^ callId)
223
{
224
    tasksList_.push(ref new RingD::Task(Request::RefuseIncommingCall, callId));
225 226
}

227
void RingClientUWP::RingD::acceptIncommingCall(String^ callId)
228
{
229
    tasksList_.push(ref new RingD::Task(Request::AcceptIncommingCall, callId));
230 231
}

Nicolas Jager's avatar
Nicolas Jager committed
232 233
void RingClientUWP::RingD::placeCall(Contact^ contact)
{
234
    MSG_("!--->> placeCall");
Nicolas Jager's avatar
Nicolas Jager committed
235
    auto to = contact->ringID_;
Nicolas Jager's avatar
Nicolas Jager committed
236
    auto accountId = AccountListItemsViewModel::instance->_selectedItem->_account->accountID_;
Nicolas Jager's avatar
Nicolas Jager committed
237 238 239 240 241 242

    auto to2 = Utils::toString(to);
    auto accountId2 = Utils::toString(accountId);

    auto callId2 = DRing::placeCall(accountId2, to2);

243 244


245
    if (callId2.empty()) {
Nicolas Jager's avatar
Nicolas Jager committed
246 247 248 249 250 251
        WNG_("call not created, the daemon didn't return a call Id");
        return;
    }

    auto callId = Utils::toPlatformString(callId2);

252
    _callIdsList->Append(callId);
253 254 255 256 257 258

    //auto con = ContactsViewModel::instance->findContactByName(to);
    auto item = SmartPanelItemsViewModel::instance->findItem(contact);
    item->_callId = callId;
    MSG_("$1 place call with id : " + Utils::toString(item->_callId));

259
    callPlaced(callId);
260 261 262 263 264 265

}

void RingClientUWP::RingD::cancelOutGoingCall2(String ^ callId)
{
    MSG_("$1 cancelOutGoingCall2 : " + Utils::toString(callId));
266
    tasksList_.push(ref new RingD::Task(Request::HangUpCall, callId));
Nicolas Jager's avatar
Nicolas Jager committed
267 268
}

269

270 271 272
void RingClientUWP::RingD::hangUpCall2(String ^ callId)
{
    MSG_("$1 hangUpCall2 : "+Utils::toString(callId));
273
    tasksList_.push(ref new RingD::Task(Request::HangUpCall, callId));
274 275
}

276 277 278 279 280 281 282 283 284 285 286 287
void RingClientUWP::RingD::pauseCall(String ^ callId)
{
    MSG_("$1 pauseCall : " + Utils::toString(callId));
    tasksList_.push(ref new RingD::Task(Request::PauseCall, callId));
}

void RingClientUWP::RingD::unPauseCall(String ^ callId)
{
    MSG_("$1 unPauseCall : " + Utils::toString(callId));
    tasksList_.push(ref new RingD::Task(Request::UnPauseCall, callId));
}

Nicolas Jager's avatar
Nicolas Jager committed
288 289 290 291 292 293 294 295
void RingClientUWP::RingD::askToRefreshKnownDevices(String^ accountId)
{
    auto task = ref new RingD::Task(Request::GetKnownDevices);
    task->_accountId = accountId;

    tasksList_.push(task);
}

296 297 298 299 300 301 302 303 304
void RingClientUWP::RingD::askToExportOnRing(String ^ accountId, String ^ password)
{
    auto task = ref new RingD::Task(Request::ExportOnRing);
    task->_accountId = accountId;
    task->_password = password;

    tasksList_.push(task);
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
void RingClientUWP::RingD::eraseCacheFolder()
{
    StorageFolder^ localFolder = ApplicationData::Current->LocalFolder;
    String^ folderName = ".cache";

    task<IStorageItem^>(localFolder->TryGetItemAsync(folderName)).then([this](IStorageItem^ folder)
    {
        if (folder) {
            MSG_("erasing cache folder.");
            folder->DeleteAsync();
        }
        else {
            WNG_("cache folder not found.");
        }
    });
}

322 323 324 325 326 327 328 329 330 331 332 333 334
void RingClientUWP::RingD::updateAccount(String^ accountId)
{
    editModeOn_ = true;

    auto frame = dynamic_cast<Frame^>(Window::Current->Content);
    dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(true, true);

    auto task = ref new RingD::Task(Request::UpdateAccount);
    task->_accountId = accountId;

    tasksList_.push(task);
}

335 336 337 338 339 340 341 342 343 344 345 346 347
void RingClientUWP::RingD::deleteAccount(String ^ accountId)
{
    editModeOn_ = true;

    auto frame = dynamic_cast<Frame^>(Window::Current->Content);
    dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(true, true);

    auto task = ref new RingD::Task(Request::DeleteAccount);
    task->_accountId = accountId;

    tasksList_.push(task);
}

atraczyk's avatar
atraczyk committed
348 349 350
void
RingClientUWP::RingD::startDaemon()
{
351
    //eraseCacheFolder();
352 353
    editModeOn_ = true;

354

atraczyk's avatar
atraczyk committed
355 356 357 358 359
    create_task([&]()
    {
        using SharedCallback = std::shared_ptr<DRing::CallbackWrapperBase>;
        using namespace std::placeholders;

Nicolas Jager's avatar
Nicolas Jager committed
360 361
        auto dispatcher = CoreApplication::MainView->CoreWindow->Dispatcher;

atraczyk's avatar
atraczyk committed
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
        std::map<std::string, SharedCallback> callHandlers = {
            // use IncomingCall only to register the call client sided, use StateChange to determine the impact on the UI
            DRing::exportable_callback<DRing::CallSignal::IncomingCall>([this](
                const std::string& accountId,
                const std::string& callId,
                const std::string& from)
            {
                MSG_("<IncomingCall>");
                MSG_("accountId = " + accountId);
                MSG_("callId = " + callId);
                MSG_("from = " + from);

                auto accountId2 = toPlatformString(accountId);
                auto callId2 = toPlatformString(callId);
                auto from2 = toPlatformString(from);

378 379 380
                /* fix some issue in the daemon --> <...@...> */
                from2 = Utils::TrimRingId(from2);

381
                CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
382
                    CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
383 384
                {
                    incomingCall(accountId2, callId2, from2);
Nicolas Jager's avatar
Nicolas Jager committed
385
                    stateChange(callId2, CallStatus::INCOMING_RINGING, 0);
386 387 388 389

                    auto contact = ContactsViewModel::instance->findContactByName(from2);
                    auto item = SmartPanelItemsViewModel::instance->findItem(contact);
                    item->_callId = callId2;
390
                }));
atraczyk's avatar
atraczyk committed
391 392
            }),
            DRing::exportable_callback<DRing::CallSignal::StateChange>([this](
393 394 395
                        const std::string& callId,
                        const std::string& state,
                        int code)
atraczyk's avatar
atraczyk committed
396 397 398 399 400 401 402 403 404
            {
                MSG_("<StateChange>");
                MSG_("callId = " + callId);
                MSG_("state = " + state);
                MSG_("code = " + std::to_string(code));

                auto callId2 = toPlatformString(callId);
                auto state2 = toPlatformString(state);

Nicolas Jager's avatar
Nicolas Jager committed
405
                auto state3 = translateCallStatus(state2);
Nicolas Jager's avatar
Nicolas Jager committed
406

407 408 409
                if (state3 == CallStatus::ENDED)
                    DRing::hangUp(callId); // solve a bug in the daemon API.

atraczyk's avatar
atraczyk committed
410

411
                CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
412
                    CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
413
                {
Nicolas Jager's avatar
Nicolas Jager committed
414
                    stateChange(callId2, state3, code);
415
                }));
atraczyk's avatar
atraczyk committed
416
            }),
417
            DRing::exportable_callback<DRing::ConfigurationSignal::IncomingAccountMessage>([&](
418 419 420
                        const std::string& accountId,
                        const std::string& from,
                        const std::map<std::string, std::string>& payloads)
atraczyk's avatar
atraczyk committed
421 422 423 424 425
            {
                MSG_("<IncomingAccountMessage>");
                MSG_("accountId = " + accountId);
                MSG_("from = " + from);

426 427 428
                auto accountId2 = toPlatformString(accountId);
                auto from2 = toPlatformString(from);

atraczyk's avatar
atraczyk committed
429 430 431
                for (auto i : payloads) {
                    MSG_("payload = " + i.second);
                    auto payload = Utils::toPlatformString(i.second);
432
                    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
433
                        CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
434 435 436
                    {
                        incomingAccountMessage(accountId2, from2, payload);
                    }));
atraczyk's avatar
atraczyk committed
437 438
                }
            }),
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
            DRing::exportable_callback<DRing::CallSignal::IncomingMessage>([&](
                        const std::string& callId,
                        const std::string& from,
                        const std::map<std::string, std::string>& payloads)
            {
                MSG_("<IncomingMessage>");
                MSG_("callId = " + callId);
                MSG_("from = " + from);

                auto callId2 = toPlatformString(callId);
                auto from2 = toPlatformString(from);

                const std::string PROFILE_VCF = "x-ring/ring.profile.vcard";
                static const unsigned int profileSize = PROFILE_VCF.size();

                for (auto i : payloads) {
                    if (i.first.compare(0, profileSize, PROFILE_VCF) == 0) {
                        MSG_("VCARD");
                        return;
                    }
                    MSG_("payload.first = " + i.first);
                    MSG_("payload.second = " + i.second);

                    auto payload = Utils::toPlatformString(i.second);
                    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
464
                        CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
465
                    {
Nicolas Jager's avatar
Nicolas Jager committed
466
                        incomingMessage(callId2, payload);
467
                        MSG_("message recu :" + i.second);
468 469 470
                    }));
                }
            }),
atraczyk's avatar
atraczyk committed
471
            DRing::exportable_callback<DRing::ConfigurationSignal::RegistrationStateChanged>([this](
472 473
                        const std::string& account_id, const std::string& state,
                        int detailsCode, const std::string& detailsStr)
atraczyk's avatar
atraczyk committed
474
            {
475
                MSG_("<RegistrationStateChanged>: ID = " + account_id + " state = " + state);
476
                if (state == DRing::Account::States::REGISTERED) {
477
                    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High,
478
                    ref new DispatchedHandler([=]() {
atraczyk's avatar
atraczyk committed
479
                        reloadAccountList();
480
                        if (editModeOn_) {
481 482
                            auto frame = dynamic_cast<Frame^>(Window::Current->Content);
                            dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(false, false);
483
                            editModeOn_ = false;
484
                        }
atraczyk's avatar
atraczyk committed
485 486 487
                    }));
                }
            }),
atraczyk's avatar
atraczyk committed
488 489
            DRing::exportable_callback<DRing::ConfigurationSignal::AccountsChanged>([this]()
            {
490
                MSG_("<AccountsChanged>");
491
                CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High,
Nicolas Jager's avatar
Nicolas Jager committed
492
                ref new DispatchedHandler([=]() {
atraczyk's avatar
atraczyk committed
493
                    reloadAccountList();
494 495 496 497 498
                    if (editModeOn_) {
                        auto frame = dynamic_cast<Frame^>(Window::Current->Content);
                        dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(false, false);
                        editModeOn_ = false;
                    }
atraczyk's avatar
atraczyk committed
499
                }));
Nicolas Jager's avatar
Nicolas Jager committed
500
            }),
Nicolas Jager's avatar
Nicolas Jager committed
501 502
            DRing::exportable_callback<DRing::Debug::MessageSend>([&](const std::string& toto)
            {
503
                dispatcher->RunAsync(CoreDispatcherPriority::High,
Nicolas Jager's avatar
Nicolas Jager committed
504 505 506
                ref new DispatchedHandler([=]() {
                    RingDebug::instance->print(toto);
                }));
Nicolas Jager's avatar
Nicolas Jager committed
507 508 509 510 511 512 513
            }),


            DRing::exportable_callback<DRing::ConfigurationSignal::KnownDevicesChanged>([&](const std::string& accountId, const std::map<std::string, std::string>& devices)
            {
                dispatcher->RunAsync(CoreDispatcherPriority::High,
                ref new DispatchedHandler([=]() {
514 515 516 517 518 519
                    RingDebug::instance->print("KnownDevicesChanged ---> C PAS FINI");
                }));
            }),
            DRing::exportable_callback<DRing::ConfigurationSignal::ExportOnRingEnded>([&](const std::string& accountId, int status, const std::string& pin)
            {
                auto accountId2 = Utils::toPlatformString(accountId);
Nicolas Jager's avatar
Nicolas Jager committed
520
                auto pin2 = (pin.empty()) ? "Error bad password" : "Your generated pin : " + Utils::toPlatformString(pin);
521 522 523
                dispatcher->RunAsync(CoreDispatcherPriority::High,
                ref new DispatchedHandler([=]() {
                    exportOnRingEnded(accountId2, pin2);
Nicolas Jager's avatar
Nicolas Jager committed
524
                }));
Nicolas Jager's avatar
Nicolas Jager committed
525
            })
Nicolas Jager's avatar
Nicolas Jager committed
526 527


atraczyk's avatar
atraczyk committed
528 529 530 531 532 533 534 535 536 537 538 539
        };
        registerCallHandlers(callHandlers);

        std::map<std::string, SharedCallback> getAppPathHandler =
        {
            DRing::exportable_callback<DRing::ConfigurationSignal::GetAppDataPath>
            ([this](std::vector<std::string>* paths) {
                paths->emplace_back(localFolder_);
            })
        };
        registerCallHandlers(getAppPathHandler);

atraczyk's avatar
atraczyk committed
540 541 542 543 544 545 546 547 548 549 550 551
        std::map<std::string, SharedCallback> getAppUserNameHandler =
        {
            DRing::exportable_callback<DRing::ConfigurationSignal::GetAppUserName>
            ([this](std::vector<std::string>* unames) {
                unames->emplace_back(Utils::toString(
                    UserModel::instance->firstName +
                    "." +
                    UserModel::instance->lastName));
            })
        };
        registerCallHandlers(getAppUserNameHandler);

atraczyk's avatar
atraczyk committed
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
        std::map<std::string, SharedCallback> incomingVideoHandlers =
        {
            DRing::exportable_callback<DRing::VideoSignal::DeviceEvent>
            ([this]() {
                MSG_("<DeviceEvent>");
            }),
            DRing::exportable_callback<DRing::VideoSignal::DecodingStarted>
            ([this](const std::string &id, const std::string &shmPath, int width, int height, bool isMixer) {
                MSG_("<DecodingStarted>");
                Video::VideoManager::instance->rendererManager()->startedDecoding(
                    Utils::toPlatformString(id),
                    width,
                    height);
            }),
            DRing::exportable_callback<DRing::VideoSignal::DecodingStopped>
            ([this](const std::string &id, const std::string &shmPath, bool isMixer) {
                MSG_("<DecodingStopped>");
                MSG_("Removing renderer id:" + id);
                Video::VideoManager::instance->rendererManager()->removeRenderer(Utils::toPlatformString(id));
            })
        };
        registerVideoHandlers(incomingVideoHandlers);

        using namespace Video;
        std::map<std::string, SharedCallback> outgoingVideoHandlers =
        {
            DRing::exportable_callback<DRing::VideoSignal::GetCameraInfo>
            ([this](const std::string& device,
580 581 582
            std::vector<std::string> *formats,
            std::vector<unsigned> *sizes,
            std::vector<unsigned> *rates) {
atraczyk's avatar
atraczyk committed
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
                MSG_("\n<GetCameraInfo>\n");
                auto device_list = VideoManager::instance->captureManager()->deviceList;

                for (unsigned int i = 0; i < device_list->Size; i++) {
                    auto dev = device_list->GetAt(i);
                    if (device == Utils::toString(dev->name())) {
                        auto channel = dev->channel();
                        Vector<Video::Resolution^>^ resolutions = channel->resolutionList();
                        for (auto res : resolutions) {
                            formats->emplace_back(Utils::toString(res->format()));
                            sizes->emplace_back(res->size()->width());
                            sizes->emplace_back(res->size()->height());
                            rates->emplace_back(res->activeRate()->value());
                        }
                    }
                }
            }),
            DRing::exportable_callback<DRing::VideoSignal::SetParameters>
            ([this](const std::string& device,
                    std::string format,
                    const int width,
                    const int height,
605
            const int rate) {
atraczyk's avatar
atraczyk committed
606 607 608 609 610 611 612
                MSG_("\n<SetParameters>\n");
                VideoManager::instance->captureManager()->activeDevice->SetDeviceProperties(
                    Utils::toPlatformString(format),width,height,rate);
            }),
            DRing::exportable_callback<DRing::VideoSignal::StartCapture>
            ([&](const std::string& device) {
                MSG_("\n<StartCapture>\n");
613
                dispatcher->RunAsync(CoreDispatcherPriority::High,
atraczyk's avatar
atraczyk committed
614 615 616 617 618 619 620 621
                ref new DispatchedHandler([=]() {
                    VideoManager::instance->captureManager()->InitializeCameraAsync();
                    VideoManager::instance->captureManager()->videoFrameCopyInvoker->Start();
                }));
            }),
            DRing::exportable_callback<DRing::VideoSignal::StopCapture>
            ([&]() {
                MSG_("\n<StopCapture>\n");
622
                dispatcher->RunAsync(CoreDispatcherPriority::High,
atraczyk's avatar
atraczyk committed
623 624 625 626 627 628 629 630 631 632
                ref new DispatchedHandler([=]() {
                    VideoManager::instance->captureManager()->StopPreviewAsync();
                    if (VideoManager::instance->captureManager()->captureTaskTokenSource)
                        VideoManager::instance->captureManager()->captureTaskTokenSource->cancel();
                    VideoManager::instance->captureManager()->videoFrameCopyInvoker->Stop();
                }));
            })
        };
        registerVideoHandlers(outgoingVideoHandlers);

Nicolas Jager's avatar
Nicolas Jager committed
633
        DRing::init(static_cast<DRing::InitFlag>(DRing::DRING_FLAG_CONSOLE_LOG |
634
                    DRing::DRING_FLAG_DEBUG));
atraczyk's avatar
atraczyk committed
635 636 637 638 639 640

        if (!DRing::start()) {
            ERR_("\ndaemon didn't start.\n");
            return;
        }
        else {
641 642 643
            switch (_startingStatus) {
            case StartingStatus::REGISTERING_ON_THIS_PC:
            {
644
                tasksList_.push(ref new RingD::Task(Request::AddRingAccount));
645
                break;
atraczyk's avatar
atraczyk committed
646
            }
647 648 649 650 651 652 653 654 655
            case StartingStatus::REGISTERING_THIS_DEVICE:
            {
                tasksList_.push(ref new RingD::Task(Request::RegisterDevice, _pin, _password));
                break;
            }
            case StartingStatus::NORMAL:
            default:
            {
                CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,
Nicolas Jager's avatar
Nicolas Jager committed
656
                ref new DispatchedHandler([=]() {
atraczyk's avatar
atraczyk committed
657 658
                    reloadAccountList();
                }));
659
                break;
atraczyk's avatar
atraczyk committed
660
            }
661 662
            }

663 664 665 666 667 668 669 670 671 672 673 674 675 676 677

            /* at this point the config.yml is safe. */
            Utils::fileExists(ApplicationData::Current->LocalFolder, "creation.token")
            .then([this](bool token_exists)
            {
                if (token_exists) {
                    StorageFolder^ storageFolder = ApplicationData::Current->LocalFolder;
                    task<StorageFile^>(storageFolder->GetFileAsync("creation.token")).then([this](StorageFile^ file)
                    {
                        file->DeleteAsync();
                    });
                }
            });


atraczyk's avatar
atraczyk committed
678 679 680
            while (true) {
                DRing::pollEvents();
                dequeueTasks();
681
                Sleep(5);
atraczyk's avatar
atraczyk committed
682 683 684 685 686 687 688 689 690
            }
            DRing::fini();
        }
    });
}

RingD::RingD()
{
    localFolder_ = Utils::toString(ApplicationData::Current->LocalFolder->Path);
691
    callIdsList_ = ref new Vector<String^>();
692
    currentCallId = nullptr;
atraczyk's avatar
atraczyk committed
693 694 695 696 697 698 699
}

void
RingD::dequeueTasks()
{
    for (int i = 0; i < tasksList_.size(); i++) {
        auto task = tasksList_.front();
700 701
        auto request = dynamic_cast<Task^>(task)->request;
        switch (request) {
atraczyk's avatar
atraczyk committed
702
        case Request::None:
703 704
            break;
        case Request::AddRingAccount:
705 706
        {
            std::map<std::string, std::string> ringAccountDetails;
707 708 709 710
            ringAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::ALIAS
                                      , Utils::toString(task->_alias)));
            ringAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::ARCHIVE_PASSWORD,
                                      Utils::toString(task->_password)));
atraczyk's avatar
atraczyk committed
711
            ringAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::TYPE,"RING"));
712 713
            ringAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::UPNP_ENABLED
                                      , (task->_upnp)? ring::TRUE_STR : ring::FALSE_STR));
714 715 716
            DRing::addAccount(ringAccountDetails);
        }
        break;
717
        case Request::AddSIPAccount:
718 719
        {
            std::map<std::string, std::string> sipAccountDetails;
720 721
            sipAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::ALIAS
                                                    , Utils::toString(task->_alias)));
atraczyk's avatar
atraczyk committed
722
            sipAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::TYPE,"SIP"));
723 724 725 726 727 728
            sipAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::PASSWORD
                                                    , Utils::toString(task->_sipPassword)));
            sipAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::HOSTNAME
                                                    , Utils::toString(task->_sipHostname)));
            sipAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::USERNAME
                                                    , Utils::toString(task->_sipUsername)));
729 730 731
            DRing::addAccount(sipAccountDetails);
        }
        break;
732 733
        case Request::RefuseIncommingCall:
        {
734
            auto callId = task->_callId;
735 736 737 738 739 740
            auto callId2 = Utils::toString(callId);
            DRing::refuse(callId2);
        }
        break;
        case Request::AcceptIncommingCall:
        {
741
            auto callId = task->_callId;
742 743 744 745
            auto callId2 = Utils::toString(callId);
            DRing::accept(callId2);
        }
        break;
Nicolas Jager's avatar
Nicolas Jager committed
746
        case Request::CancelOutGoingCall:
747
        case Request::HangUpCall:
Nicolas Jager's avatar
Nicolas Jager committed
748
        {
749 750
            auto callId = task->_callId;
            DRing::hangUp(Utils::toString(callId));
Nicolas Jager's avatar
Nicolas Jager committed
751 752
        }
        break;
753 754 755 756 757 758 759 760 761 762
        case Request::PauseCall:
        {
            DRing::hold(Utils::toString(task->_callId));
        }
        break;
        case Request::UnPauseCall:
        {
            DRing::unhold(Utils::toString(task->_callId));
        }
        break;
763 764 765 766 767 768 769 770 771 772 773 774 775
        case Request::RegisterDevice:
        {
            auto pin = Utils::toString(_pin);
            auto password = Utils::toString(_password);

            std::map<std::string, std::string> deviceDetails;
            deviceDetails.insert(std::make_pair(DRing::Account::ConfProperties::TYPE, "RING"));
            //deviceDetails.insert(std::make_pair(DRing::Account::ConfProperties::UPNP_ENABLED, "true"));
            //deviceDetails.insert(std::make_pair(DRing::Account::ConfProperties::ALIAS, "MonSuperUsername"));
            deviceDetails.insert(std::make_pair(DRing::Account::ConfProperties::ARCHIVE_PIN, pin));
            deviceDetails.insert(std::make_pair(DRing::Account::ConfProperties::ARCHIVE_PASSWORD, password));
            DRing::addAccount(deviceDetails);
        }
Nicolas Jager's avatar
Nicolas Jager committed
776 777 778 779 780 781
        case Request::GetKnownDevices:
        {
            auto accountId = task->_accountId;
            auto accountId2 = Utils::toString(accountId);

            auto devicesList = DRing::getKnownRingDevices(accountId2);
782 783 784
            if (devicesList.empty())
                break;

Nicolas Jager's avatar
Nicolas Jager committed
785 786
            auto devicesList2 = translateKnownRingDevices(devicesList);

787 788 789 790
            CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,
            ref new DispatchedHandler([=]() {
                devicesListRefreshed(devicesList2);
            }));
Nicolas Jager's avatar
Nicolas Jager committed
791
            break;
792 793 794 795 796 797 798 799 800 801
        }
        case Request::ExportOnRing:
        {
            auto accountId = task->_accountId;
            auto password = task->_password;

            auto accountId2 = Utils::toString(accountId);
            auto password2 = Utils::toString(password);

            DRing::exportOnRing(accountId2, password2);
802 803 804 805 806 807 808 809 810 811 812 813 814
            break;
        }
        case Request::UpdateAccount:
        {
            auto accountId = task->_accountId;
            auto accountId2 = Utils::toString(accountId);
            auto account = AccountListItemsViewModel::instance->findItem(accountId)->_account;
            std::map<std::string, std::string> accountDetails = DRing::getAccountDetails(accountId2);
            accountDetails[DRing::Account::ConfProperties::UPNP_ENABLED] = (account->_upnpState) ? ring::TRUE_STR : ring::FALSE_STR;
            accountDetails[DRing::Account::ConfProperties::ALIAS] = Utils::toString(account->name_);

            DRing::setAccountDetails(Utils::toString(account->accountID_), accountDetails);
            break;
815 816 817 818 819 820 821 822
        }
        case Request::DeleteAccount:
        {
            auto accountId = task->_accountId;
            auto accountId2 = Utils::toString(accountId);

            DRing::removeAccount(accountId2);
            break;
Nicolas Jager's avatar
Nicolas Jager committed
823
        }
atraczyk's avatar
atraczyk committed
824 825 826 827 828 829
        default:
            break;
        }
        tasksList_.pop();
    }
}
Nicolas Jager's avatar
Nicolas Jager committed
830

Nicolas Jager's avatar
Nicolas Jager committed
831
RingClientUWP::CallStatus RingClientUWP::RingD::translateCallStatus(String^ state)
Nicolas Jager's avatar
Nicolas Jager committed
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
{
    if (state == "INCOMING")
        return CallStatus::INCOMING_RINGING;

    if (state == "CURRENT")
        return CallStatus::IN_PROGRESS;

    if (state == "OVER")
        return CallStatus::ENDED;

    if (state == "RINGING")
        return CallStatus::OUTGOING_RINGING;

    if (state == "CONNECTING")
        return CallStatus::SEARCHING;

    return CallStatus::NONE;
}
Nicolas Jager's avatar
Nicolas Jager committed
850

atraczyk's avatar
atraczyk committed
851 852 853 854 855 856 857
String^
RingD::getUserName()
{
    auto users = User::FindAllAsync();
    return nullptr;
}

Nicolas Jager's avatar
Nicolas Jager committed
858 859 860 861 862 863 864
Vector<String^>^ RingClientUWP::RingD::translateKnownRingDevices(const std::map<std::string, std::string> devices)
{
    auto devicesList = ref new Vector<String^>();

    for (auto i : devices) {
        MSG_("devices.first = " + i.first);
        MSG_("devices.second = " + i.second);
865 866
        auto deviceName = Utils::toPlatformString(i.second);
        devicesList->Append(deviceName);
Nicolas Jager's avatar
Nicolas Jager committed
867 868 869
    }


870

Nicolas Jager's avatar
Nicolas Jager committed
871 872
    return devicesList;
}