RingD.cpp 28 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"
atraczyk's avatar
atraczyk committed
30 31 32 33 34 35

#include "SmartPanel.xaml.h"

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

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

void
RingClientUWP::RingD::reloadAccountList()
{
    RingClientUWP::ViewModel::AccountsViewModel::instance->clearAccountList();
Nicolas Jager's avatar
Nicolas Jager committed
48

atraczyk's avatar
atraczyk committed
49 50
    std::vector<std::string> accountList = DRing::getAccountList();
    std::vector<std::string>::reverse_iterator rit = accountList.rbegin();
Nicolas Jager's avatar
Nicolas Jager committed
51

atraczyk's avatar
atraczyk committed
52
    for (; rit != accountList.rend(); ++rit) {
Nicolas Jager's avatar
Nicolas Jager committed
53

atraczyk's avatar
atraczyk committed
54
        std::map<std::string,std::string> accountDetails = DRing::getAccountDetails(*rit);
atraczyk's avatar
atraczyk committed
55
        std::string ringID(accountDetails.find(DRing::Account::ConfProperties::USERNAME)->second);
Nicolas Jager's avatar
Nicolas Jager committed
56

atraczyk's avatar
atraczyk committed
57 58
        if(!ringID.empty())
            ringID = ringID.substr(5);
Nicolas Jager's avatar
Nicolas Jager committed
59

60 61 62 63 64 65
        auto alias = accountDetails.find(DRing::Account::ConfProperties::ALIAS)->second;
        auto type = accountDetails.find(DRing::Account::ConfProperties::TYPE)->second;
        auto deviceId = (type == "SIP")? std::string() : accountDetails.find(DRing::Account::ConfProperties::RING_DEVICE_ID)->second;

        RingClientUWP::ViewModel::AccountsViewModel::instance->add(alias, ringID, type, *rit /*account id*/, deviceId);

atraczyk's avatar
atraczyk committed
66
    }
Nicolas Jager's avatar
Nicolas Jager committed
67

atraczyk's avatar
atraczyk committed
68 69 70 71
    // load user preferences
    Configuration::UserPreferences::instance->load();
}

Nicolas Jager's avatar
Nicolas Jager committed
72 73 74 75 76 77 78 79 80
/* nb: send message during conversation not chat video message */
void RingClientUWP::RingD::sendAccountTextMessage(String^ message)
{
    /* account id */
    auto accountId = AccountsViewModel::instance->selectedAccount->accountID_;
    std::wstring accountId2(accountId->Begin());
    std::string accountId3(accountId2.begin(), accountId2.end());

    /* recipient */
Nicolas Jager's avatar
Nicolas Jager committed
81 82
    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
    auto contact = item->_contact;
Nicolas Jager's avatar
Nicolas Jager committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    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);
99 100 101 102

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

Nicolas Jager's avatar
Nicolas Jager committed
103 104 105 106 107
    } else {
        WNG_("message not sent, see daemon outputs");
    }
}

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
// send message during video call
void RingClientUWP::RingD::sendSIPTextMessage(String^ message)
{
    /* account id */
    auto accountId = AccountsViewModel::instance->selectedAccount->accountID_;
    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
137 138 139
void
RingD::createRINGAccount(String^ alias)
{
140
    // refactoring : create a dedicated class constructor task and removes accountName from RingD
atraczyk's avatar
atraczyk committed
141 142 143 144 145 146 147
    accountName = Utils::toString(alias);
    tasksList_.push(ref new RingD::Task(Request::AddRingAccount));
}

void
RingD::createSIPAccount(String^ alias)
{
148
    // refactoring : create a dedicated class constructor task and removes accountName from RingD
atraczyk's avatar
atraczyk committed
149 150 151 152
    accountName = Utils::toString(alias);
    tasksList_.push(ref new RingD::Task(Request::AddSIPAccount));
}

153
void RingClientUWP::RingD::refuseIncommingCall(String^ callId)
154
{
155
    tasksList_.push(ref new RingD::Task(Request::RefuseIncommingCall, callId));
156 157
}

158
void RingClientUWP::RingD::acceptIncommingCall(String^ callId)
159
{
160
    tasksList_.push(ref new RingD::Task(Request::AcceptIncommingCall, callId));
161 162
}

Nicolas Jager's avatar
Nicolas Jager committed
163 164
void RingClientUWP::RingD::placeCall(Contact^ contact)
{
165
    MSG_("!--->> placeCall");
Nicolas Jager's avatar
Nicolas Jager committed
166 167 168 169 170 171 172 173
    auto to = contact->ringID_;
    auto accountId = AccountsViewModel::instance->selectedAccount->accountID_;

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

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

174 175


176
    if (callId2.empty()) {
Nicolas Jager's avatar
Nicolas Jager committed
177 178 179 180 181 182
        WNG_("call not created, the daemon didn't return a call Id");
        return;
    }

    auto callId = Utils::toPlatformString(callId2);

183
    _callIdsList->Append(callId);
184 185 186 187 188 189

    //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));

190
    callPlaced(callId);
191 192 193 194 195 196

}

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

200

201 202 203
void RingClientUWP::RingD::hangUpCall2(String ^ callId)
{
    MSG_("$1 hangUpCall2 : "+Utils::toString(callId));
204
    tasksList_.push(ref new RingD::Task(Request::HangUpCall, callId));
205 206
}

207 208 209 210 211 212 213 214 215 216 217 218
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
219 220 221 222 223 224 225 226
void RingClientUWP::RingD::askToRefreshKnownDevices(String^ accountId)
{
    auto task = ref new RingD::Task(Request::GetKnownDevices);
    task->_accountId = accountId;

    tasksList_.push(task);
}

227 228 229 230 231 232 233 234 235
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);
}

236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
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.");
        }
    });
}

atraczyk's avatar
atraczyk committed
253 254 255
void
RingClientUWP::RingD::startDaemon()
{
256 257
    eraseCacheFolder();

atraczyk's avatar
atraczyk committed
258 259 260 261 262
    create_task([&]()
    {
        using SharedCallback = std::shared_ptr<DRing::CallbackWrapperBase>;
        using namespace std::placeholders;

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

atraczyk's avatar
atraczyk committed
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
        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);

281 282 283
                /* fix some issue in the daemon --> <...@...> */
                from2 = Utils::TrimRingId(from2);

284
                CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
285
                    CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
286 287
                {
                    incomingCall(accountId2, callId2, from2);
Nicolas Jager's avatar
Nicolas Jager committed
288
                    stateChange(callId2, CallStatus::INCOMING_RINGING, 0);
289 290 291 292

                    auto contact = ContactsViewModel::instance->findContactByName(from2);
                    auto item = SmartPanelItemsViewModel::instance->findItem(contact);
                    item->_callId = callId2;
293
                }));
atraczyk's avatar
atraczyk committed
294 295
            }),
            DRing::exportable_callback<DRing::CallSignal::StateChange>([this](
296 297 298
                        const std::string& callId,
                        const std::string& state,
                        int code)
atraczyk's avatar
atraczyk committed
299 300 301 302 303 304 305 306 307
            {
                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
308
                auto state3 = translateCallStatus(state2);
Nicolas Jager's avatar
Nicolas Jager committed
309

310 311 312
                if (state3 == CallStatus::ENDED)
                    DRing::hangUp(callId); // solve a bug in the daemon API.

atraczyk's avatar
atraczyk committed
313

314
                CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
315
                    CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
316
                {
Nicolas Jager's avatar
Nicolas Jager committed
317
                    stateChange(callId2, state3, code);
318
                }));
atraczyk's avatar
atraczyk committed
319
            }),
320
            DRing::exportable_callback<DRing::ConfigurationSignal::IncomingAccountMessage>([&](
321 322 323
                        const std::string& accountId,
                        const std::string& from,
                        const std::map<std::string, std::string>& payloads)
atraczyk's avatar
atraczyk committed
324 325 326 327 328
            {
                MSG_("<IncomingAccountMessage>");
                MSG_("accountId = " + accountId);
                MSG_("from = " + from);

329 330 331
                auto accountId2 = toPlatformString(accountId);
                auto from2 = toPlatformString(from);

atraczyk's avatar
atraczyk committed
332 333 334
                for (auto i : payloads) {
                    MSG_("payload = " + i.second);
                    auto payload = Utils::toPlatformString(i.second);
335
                    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
336
                        CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
337 338 339
                    {
                        incomingAccountMessage(accountId2, from2, payload);
                    }));
atraczyk's avatar
atraczyk committed
340 341
                }
            }),
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
            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(
367
                        CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
368
                    {
Nicolas Jager's avatar
Nicolas Jager committed
369
                        incomingMessage(callId2, payload);
370
                        MSG_("message recu :" + i.second);
371 372 373
                    }));
                }
            }),
atraczyk's avatar
atraczyk committed
374
            DRing::exportable_callback<DRing::ConfigurationSignal::RegistrationStateChanged>([this](
375 376
                        const std::string& account_id, const std::string& state,
                        int detailsCode, const std::string& detailsStr)
atraczyk's avatar
atraczyk committed
377 378
            {
                MSG_("<RegistrationStateChanged>: ID = " + account_id + "state = " + state);
379
                if (state == DRing::Account::States::REGISTERED) {
380
                    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High,
381
                    ref new DispatchedHandler([=]() {
atraczyk's avatar
atraczyk committed
382
                        reloadAccountList();
383 384 385 386 387 388
                        std::vector<std::string> accountList = DRing::getAccountList();
                        auto last_id = accountList.back();
                        if (!account_id.compare(last_id)) {
                            auto frame = dynamic_cast<Frame^>(Window::Current->Content);
                            dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(false, false);
                        }
atraczyk's avatar
atraczyk committed
389 390 391
                    }));
                }
            }),
atraczyk's avatar
atraczyk committed
392 393
            DRing::exportable_callback<DRing::ConfigurationSignal::AccountsChanged>([this]()
            {
394
                CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High,
Nicolas Jager's avatar
Nicolas Jager committed
395
                ref new DispatchedHandler([=]() {
atraczyk's avatar
atraczyk committed
396 397
                    reloadAccountList();
                }));
Nicolas Jager's avatar
Nicolas Jager committed
398
            }),
Nicolas Jager's avatar
Nicolas Jager committed
399 400
            DRing::exportable_callback<DRing::Debug::MessageSend>([&](const std::string& toto)
            {
401
                dispatcher->RunAsync(CoreDispatcherPriority::High,
Nicolas Jager's avatar
Nicolas Jager committed
402 403 404
                ref new DispatchedHandler([=]() {
                    RingDebug::instance->print(toto);
                }));
Nicolas Jager's avatar
Nicolas Jager committed
405 406 407 408 409 410 411
            }),


            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([=]() {
412 413 414 415 416 417
                    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
418
                auto pin2 = (pin.empty()) ? "Error bad password" : "Your generated pin : " + Utils::toPlatformString(pin);
419 420 421
                dispatcher->RunAsync(CoreDispatcherPriority::High,
                ref new DispatchedHandler([=]() {
                    exportOnRingEnded(accountId2, pin2);
Nicolas Jager's avatar
Nicolas Jager committed
422
                }));
Nicolas Jager's avatar
Nicolas Jager committed
423
            })
Nicolas Jager's avatar
Nicolas Jager committed
424 425


atraczyk's avatar
atraczyk committed
426 427 428 429 430 431 432 433 434 435 436 437
        };
        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
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 464 465
        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,
466 467 468
            std::vector<std::string> *formats,
            std::vector<unsigned> *sizes,
            std::vector<unsigned> *rates) {
atraczyk's avatar
atraczyk committed
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
                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,
491
            const int rate) {
atraczyk's avatar
atraczyk committed
492 493 494 495 496 497 498
                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");
499
                dispatcher->RunAsync(CoreDispatcherPriority::High,
atraczyk's avatar
atraczyk committed
500 501 502 503 504 505 506 507
                ref new DispatchedHandler([=]() {
                    VideoManager::instance->captureManager()->InitializeCameraAsync();
                    VideoManager::instance->captureManager()->videoFrameCopyInvoker->Start();
                }));
            }),
            DRing::exportable_callback<DRing::VideoSignal::StopCapture>
            ([&]() {
                MSG_("\n<StopCapture>\n");
508
                dispatcher->RunAsync(CoreDispatcherPriority::High,
atraczyk's avatar
atraczyk committed
509 510 511 512 513 514 515 516 517 518
                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
519
        DRing::init(static_cast<DRing::InitFlag>(DRing::DRING_FLAG_CONSOLE_LOG |
520
                    DRing::DRING_FLAG_DEBUG));
atraczyk's avatar
atraczyk committed
521 522 523 524 525 526

        if (!DRing::start()) {
            ERR_("\ndaemon didn't start.\n");
            return;
        }
        else {
527 528 529
            switch (_startingStatus) {
            case StartingStatus::REGISTERING_ON_THIS_PC:
            {
530 531
                tasksList_.push(ref new RingD::Task(Request::AddRingAccount));
                tasksList_.push(ref new RingD::Task(Request::AddSIPAccount));
532
                break;
atraczyk's avatar
atraczyk committed
533
            }
534 535 536 537 538 539 540 541 542
            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
543
                ref new DispatchedHandler([=]() {
atraczyk's avatar
atraczyk committed
544 545
                    reloadAccountList();
                }));
546
                break;
atraczyk's avatar
atraczyk committed
547
            }
548 549
            }

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564

            /* 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
565 566 567
            while (true) {
                DRing::pollEvents();
                dequeueTasks();
568
                Sleep(1000);
atraczyk's avatar
atraczyk committed
569 570 571 572 573 574 575 576 577
            }
            DRing::fini();
        }
    });
}

RingD::RingD()
{
    localFolder_ = Utils::toString(ApplicationData::Current->LocalFolder->Path);
578
    callIdsList_ = ref new Vector<String^>();
579
    currentCallId = nullptr;
atraczyk's avatar
atraczyk committed
580 581 582 583 584 585 586
}

void
RingD::dequeueTasks()
{
    for (int i = 0; i < tasksList_.size(); i++) {
        auto task = tasksList_.front();
587 588
        auto request = dynamic_cast<Task^>(task)->request;
        switch (request) {
atraczyk's avatar
atraczyk committed
589
        case Request::None:
590 591
            break;
        case Request::AddRingAccount:
592 593
        {
            std::map<std::string, std::string> ringAccountDetails;
atraczyk's avatar
atraczyk committed
594 595 596
            ringAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::ALIAS, accountName));
            ringAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::ARCHIVE_PASSWORD, accountName));
            ringAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::TYPE,"RING"));
597 598 599
            DRing::addAccount(ringAccountDetails);
        }
        break;
600
        case Request::AddSIPAccount:
601 602
        {
            std::map<std::string, std::string> sipAccountDetails;
atraczyk's avatar
atraczyk committed
603 604
            sipAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::ALIAS, accountName + " (SIP)"));
            sipAccountDetails.insert(std::make_pair(DRing::Account::ConfProperties::TYPE,"SIP"));
605 606 607
            DRing::addAccount(sipAccountDetails);
        }
        break;
608 609
        case Request::RefuseIncommingCall:
        {
610
            auto callId = task->_callId;
611 612 613 614 615 616
            auto callId2 = Utils::toString(callId);
            DRing::refuse(callId2);
        }
        break;
        case Request::AcceptIncommingCall:
        {
617
            auto callId = task->_callId;
618 619 620 621
            auto callId2 = Utils::toString(callId);
            DRing::accept(callId2);
        }
        break;
Nicolas Jager's avatar
Nicolas Jager committed
622
        case Request::CancelOutGoingCall:
623
        case Request::HangUpCall:
Nicolas Jager's avatar
Nicolas Jager committed
624
        {
625 626
            auto callId = task->_callId;
            DRing::hangUp(Utils::toString(callId));
Nicolas Jager's avatar
Nicolas Jager committed
627 628
        }
        break;
629 630 631 632 633 634 635 636 637 638
        case Request::PauseCall:
        {
            DRing::hold(Utils::toString(task->_callId));
        }
        break;
        case Request::UnPauseCall:
        {
            DRing::unhold(Utils::toString(task->_callId));
        }
        break;
639 640 641 642 643 644 645 646 647 648 649 650 651
        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
652 653 654 655 656 657
        case Request::GetKnownDevices:
        {
            auto accountId = task->_accountId;
            auto accountId2 = Utils::toString(accountId);

            auto devicesList = DRing::getKnownRingDevices(accountId2);
658 659 660
            if (devicesList.empty())
                break;

Nicolas Jager's avatar
Nicolas Jager committed
661 662
            auto devicesList2 = translateKnownRingDevices(devicesList);

663 664 665 666
            CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,
            ref new DispatchedHandler([=]() {
                devicesListRefreshed(devicesList2);
            }));
Nicolas Jager's avatar
Nicolas Jager committed
667
            break;
668 669 670 671 672 673 674 675 676 677
        }
        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);
Nicolas Jager's avatar
Nicolas Jager committed
678
        }
atraczyk's avatar
atraczyk committed
679 680 681 682 683 684
        default:
            break;
        }
        tasksList_.pop();
    }
}
Nicolas Jager's avatar
Nicolas Jager committed
685

Nicolas Jager's avatar
Nicolas Jager committed
686
RingClientUWP::CallStatus RingClientUWP::RingD::translateCallStatus(String^ state)
Nicolas Jager's avatar
Nicolas Jager committed
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
{
    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
705 706 707 708 709 710 711 712

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);
713 714
        auto deviceName = Utils::toPlatformString(i.second);
        devicesList->Append(deviceName);
Nicolas Jager's avatar
Nicolas Jager committed
715 716 717
    }


718

Nicolas Jager's avatar
Nicolas Jager committed
719 720
    return devicesList;
}