diff --git a/AccountsViewModel.cpp b/AccountsViewModel.cpp index d6ba55362ef1d43887d1591df85d621cfe4fb7ff..11b8c86a60cffbba3607bca4f3b57b22921f200c 100644 --- a/AccountsViewModel.cpp +++ b/AccountsViewModel.cpp @@ -32,10 +32,10 @@ void AccountsViewModel::add(std::string& name, std::string& ringID, std::string& accountType) { accountsList_->Append(ref new Account( - Utils::toPlatformString(name), - Utils::toPlatformString(ringID), - Utils::toPlatformString(accountType) - )); + Utils::toPlatformString(name), + Utils::toPlatformString(ringID), + Utils::toPlatformString(accountType) + )); } void diff --git a/Contact.h b/Contact.h index 87f46f981ef5f670b57316d00722fd9a43371aa3..eb1ff211ce89633af3d49366c81ce8c0ce1516b7 100644 --- a/Contact.h +++ b/Contact.h @@ -1,60 +1,60 @@ -#pragma once -/************************************************************************** -* 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/>. * -**************************************************************************/ -using namespace Platform; -using namespace Windows::Data::Json; -using namespace Windows::UI::Xaml::Data; - -/* strings required by Windows::Data::Json. Defined here on puprose */ -String^ nameKey = "name"; -String^ ringIDKey = "ringid"; -String^ contactKey = "contact"; -String^ contactListKey = "contactlist"; - -namespace RingClientUWP -{ -ref class Conversation; -public ref class Contact sealed : public INotifyPropertyChanged -{ -public: - Contact(String^ name, String^ ringID); - JsonObject^ ToJsonObject(); - - - virtual event PropertyChangedEventHandler^ PropertyChanged; - - property String^ name_; - property String^ ringID_; - property Conversation^ _conversation - { - Conversation^ get() - { - return conversation_; - } - } - -protected: - void NotifyPropertyChanged(String^ propertyName); - -private: - Conversation^ conversation_; - -}; -} - +#pragma once +/************************************************************************** +* 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/>. * +**************************************************************************/ +using namespace Platform; +using namespace Windows::Data::Json; +using namespace Windows::UI::Xaml::Data; + +/* strings required by Windows::Data::Json. Defined here on puprose */ +String^ nameKey = "name"; +String^ ringIDKey = "ringid"; +String^ contactKey = "contact"; +String^ contactListKey = "contactlist"; + +namespace RingClientUWP +{ +ref class Conversation; +public ref class Contact sealed : public INotifyPropertyChanged +{ +public: + Contact(String^ name, String^ ringID); + JsonObject^ ToJsonObject(); + + + virtual event PropertyChangedEventHandler^ PropertyChanged; + + property String^ name_; + property String^ ringID_; + property Conversation^ _conversation + { + Conversation^ get() + { + return conversation_; + } + } + +protected: + void NotifyPropertyChanged(String^ propertyName); + +private: + Conversation^ conversation_; + +}; +} + diff --git a/ContactsViewModel.cpp b/ContactsViewModel.cpp index 28b5b8cbfbd7621ddbc7346b9ea47bc4b2d92dc2..58205790a96c81ad87c681399542c186d7185ad6 100644 --- a/ContactsViewModel.cpp +++ b/ContactsViewModel.cpp @@ -1,142 +1,142 @@ -/*************************************************************************** -* Copyright (C) 2016 by Savoir-faire Linux * -* Author: Jäger Nicolas <nicolas.jager@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" -#include "ContactsViewModel.h" - -using namespace Windows::Data::Json; -using namespace Windows::Storage; - -using namespace RingClientUWP; -using namespace ViewModel; - -ContactsViewModel::ContactsViewModel() -{ - contactsList_ = ref new Vector<Contact^>(); - openContactsFromFile(); -} - -Contact^ -RingClientUWP::ViewModel::ContactsViewModel::findContactByName(String ^ name) -{ - for each (Contact^ contact in contactsList_) - if (contact->name_ == name) - return contact; - - return nullptr; -} - -Contact^ -RingClientUWP::ViewModel::ContactsViewModel::addNewContact(String^ name, String^ ringId) -{ - if (contactsList_ && !findContactByName(name)) { - Contact^ contact = ref new Contact(name, ringId); - contactsList_->Append(contact); - saveContactsToFile(); - return contact; - } - - return nullptr; -} - -void -ContactsViewModel::saveContactsToFile() -{ - StorageFolder^ localfolder = ApplicationData::Current->LocalFolder; - String^ contactsFile = ".profile\\contacts.json"; - - try { - create_task(localfolder->CreateFileAsync(contactsFile - , Windows::Storage::CreationCollisionOption::ReplaceExisting)) - .then([&](StorageFile^ newFile) { - try { - FileIO::WriteTextAsync(newFile, Stringify()); - } - catch (Exception^ e) { - RingDebug::instance->print("Exception while writing to contacts file"); - } - }); - } - catch (Exception^ e) { - RingDebug::instance->print("Exception while opening contacts file"); - } -} - -void -ContactsViewModel::openContactsFromFile() -{ - String^ contactsFile = ".profile\\contacts.json"; - - Utils::fileExists(ApplicationData::Current->LocalFolder, - contactsFile) - .then([this, contactsFile](bool contacts_file_exists) - { - if (contacts_file_exists) { - try { - create_task(ApplicationData::Current->LocalFolder->GetFileAsync(contactsFile)) - .then([this](StorageFile^ file) - { - create_task(FileIO::ReadTextAsync(file)) - .then([this](String^ fileContents) { - if (fileContents != nullptr) - Destringify(fileContents); - }); - }); - } - catch (Exception^ e) { - RingDebug::instance->print("Exception while opening contacts file"); - } - } - }); -} - -String^ -ContactsViewModel::Stringify() -{ - JsonArray^ jsonArray = ref new JsonArray(); - - for (unsigned int i = 0; i < contactsList_->Size; i++) { - jsonArray->Append(contactsList_->GetAt(i)->ToJsonObject()); - } - - JsonObject^ jsonObject = ref new JsonObject(); - jsonObject->SetNamedValue(contactListKey, jsonArray); - - return jsonObject->Stringify(); -} - -void -ContactsViewModel::Destringify(String^ data) -{ - JsonObject^ jsonObject = JsonObject::Parse(data); - String^ name; - String^ ringid; - - JsonArray^ contactlist = jsonObject->GetNamedArray(contactListKey, ref new JsonArray()); - for (unsigned int i = 0; i < contactlist->Size; i++) { - IJsonValue^ contact = contactlist->GetAt(i); - if (contact->ValueType == JsonValueType::Object) { - JsonObject^ jsonContactObject = contact->GetObject(); - JsonObject^ contactObject = jsonContactObject->GetNamedObject(contactKey, nullptr); - if (contactObject != nullptr) { - name = contactObject->GetNamedString(nameKey, ""); - ringid = contactObject->GetNamedString(ringIDKey, ""); - } - contactsList_->Append(ref new Contact(name, ringid)); - } - } +/*************************************************************************** +* Copyright (C) 2016 by Savoir-faire Linux * +* Author: Jäger Nicolas <nicolas.jager@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" +#include "ContactsViewModel.h" + +using namespace Windows::Data::Json; +using namespace Windows::Storage; + +using namespace RingClientUWP; +using namespace ViewModel; + +ContactsViewModel::ContactsViewModel() +{ + contactsList_ = ref new Vector<Contact^>(); + openContactsFromFile(); +} + +Contact^ +RingClientUWP::ViewModel::ContactsViewModel::findContactByName(String ^ name) +{ + for each (Contact^ contact in contactsList_) + if (contact->name_ == name) + return contact; + + return nullptr; +} + +Contact^ +RingClientUWP::ViewModel::ContactsViewModel::addNewContact(String^ name, String^ ringId) +{ + if (contactsList_ && !findContactByName(name)) { + Contact^ contact = ref new Contact(name, ringId); + contactsList_->Append(contact); + saveContactsToFile(); + return contact; + } + + return nullptr; +} + +void +ContactsViewModel::saveContactsToFile() +{ + StorageFolder^ localfolder = ApplicationData::Current->LocalFolder; + String^ contactsFile = ".profile\\contacts.json"; + + try { + create_task(localfolder->CreateFileAsync(contactsFile + , Windows::Storage::CreationCollisionOption::ReplaceExisting)) + .then([&](StorageFile^ newFile) { + try { + FileIO::WriteTextAsync(newFile, Stringify()); + } + catch (Exception^ e) { + RingDebug::instance->print("Exception while writing to contacts file"); + } + }); + } + catch (Exception^ e) { + RingDebug::instance->print("Exception while opening contacts file"); + } +} + +void +ContactsViewModel::openContactsFromFile() +{ + String^ contactsFile = ".profile\\contacts.json"; + + Utils::fileExists(ApplicationData::Current->LocalFolder, + contactsFile) + .then([this, contactsFile](bool contacts_file_exists) + { + if (contacts_file_exists) { + try { + create_task(ApplicationData::Current->LocalFolder->GetFileAsync(contactsFile)) + .then([this](StorageFile^ file) + { + create_task(FileIO::ReadTextAsync(file)) + .then([this](String^ fileContents) { + if (fileContents != nullptr) + Destringify(fileContents); + }); + }); + } + catch (Exception^ e) { + RingDebug::instance->print("Exception while opening contacts file"); + } + } + }); +} + +String^ +ContactsViewModel::Stringify() +{ + JsonArray^ jsonArray = ref new JsonArray(); + + for (unsigned int i = 0; i < contactsList_->Size; i++) { + jsonArray->Append(contactsList_->GetAt(i)->ToJsonObject()); + } + + JsonObject^ jsonObject = ref new JsonObject(); + jsonObject->SetNamedValue(contactListKey, jsonArray); + + return jsonObject->Stringify(); +} + +void +ContactsViewModel::Destringify(String^ data) +{ + JsonObject^ jsonObject = JsonObject::Parse(data); + String^ name; + String^ ringid; + + JsonArray^ contactlist = jsonObject->GetNamedArray(contactListKey, ref new JsonArray()); + for (unsigned int i = 0; i < contactlist->Size; i++) { + IJsonValue^ contact = contactlist->GetAt(i); + if (contact->ValueType == JsonValueType::Object) { + JsonObject^ jsonContactObject = contact->GetObject(); + JsonObject^ contactObject = jsonContactObject->GetNamedObject(contactKey, nullptr); + if (contactObject != nullptr) { + name = contactObject->GetNamedString(nameKey, ""); + ringid = contactObject->GetNamedString(ringIDKey, ""); + } + contactsList_->Append(ref new Contact(name, ringid)); + } + } } \ No newline at end of file diff --git a/ContactsViewModel.h b/ContactsViewModel.h index 9ab75ffbbad82751b5a21b0ee015fd9695d72017..31bf79e79b921a8bab6cd9bcb13ec69739f657d4 100644 --- a/ContactsViewModel.h +++ b/ContactsViewModel.h @@ -1,88 +1,88 @@ -#pragma once -/************************************************************************** -* Copyright (C) 2016 by Savoir-faire Linux * -* Author: Jäger Nicolas <nicolas.jager@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/>. * -**************************************************************************/ -using namespace Concurrency; -using namespace Platform::Collections; - -namespace RingClientUWP -{ - -delegate void NewContactSelected(); -delegate void NoContactSelected(); - -namespace ViewModel { -public ref class ContactsViewModel sealed -{ -internal: - /* singleton */ - static property ContactsViewModel^ instance - { - ContactsViewModel^ get() - { - static ContactsViewModel^ instance_ = ref new ContactsViewModel(); - return instance_; - } - } - - /* functions */ - Contact^ findContactByName(String^ name); - Contact^ addNewContact(String^ name, String^ ringId); - void saveContactsToFile(); - void openContactsFromFile(); - String^ Stringify(); - void Destringify(String^ data); - - /* properties */ - property Contact^ selectedContact - { - Contact^ get() - { - return currentItem_; - } - void set(Contact^ value) - { - oldItem_ = currentItem_; - currentItem_ = value; - if (value) - newContactSelected(); - else - noContactSelected(); - } - } - - property Vector<Contact^>^ contactsList - { - Vector<Contact^>^ get() - { - return contactsList_; - } - } - - /* events */ - event NewContactSelected^ newContactSelected; - event NoContactSelected^ noContactSelected; - -private: - ContactsViewModel(); // singleton - Vector<Contact^>^ contactsList_; - Contact^ currentItem_; - Contact^ oldItem_; - -}; -} -} +#pragma once +/************************************************************************** +* Copyright (C) 2016 by Savoir-faire Linux * +* Author: Jäger Nicolas <nicolas.jager@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/>. * +**************************************************************************/ +using namespace Concurrency; +using namespace Platform::Collections; + +namespace RingClientUWP +{ + +delegate void NewContactSelected(); +delegate void NoContactSelected(); + +namespace ViewModel { +public ref class ContactsViewModel sealed +{ +internal: + /* singleton */ + static property ContactsViewModel^ instance + { + ContactsViewModel^ get() + { + static ContactsViewModel^ instance_ = ref new ContactsViewModel(); + return instance_; + } + } + + /* functions */ + Contact^ findContactByName(String^ name); + Contact^ addNewContact(String^ name, String^ ringId); + void saveContactsToFile(); + void openContactsFromFile(); + String^ Stringify(); + void Destringify(String^ data); + + /* properties */ + property Contact^ selectedContact + { + Contact^ get() + { + return currentItem_; + } + void set(Contact^ value) + { + oldItem_ = currentItem_; + currentItem_ = value; + if (value) + newContactSelected(); + else + noContactSelected(); + } + } + + property Vector<Contact^>^ contactsList + { + Vector<Contact^>^ get() + { + return contactsList_; + } + } + + /* events */ + event NewContactSelected^ newContactSelected; + event NoContactSelected^ noContactSelected; + +private: + ContactsViewModel(); // singleton + Vector<Contact^>^ contactsList_; + Contact^ currentItem_; + Contact^ oldItem_; + +}; +} +} diff --git a/LoadingPage.xaml.cpp b/LoadingPage.xaml.cpp index b0263ee70e9b35f42a603b1faf0e766a74b77267..a8d24bc2dd374cd932b209deaef649d2a73e5a74 100644 --- a/LoadingPage.xaml.cpp +++ b/LoadingPage.xaml.cpp @@ -49,7 +49,7 @@ LoadingPage::LoadingPage() InitializeComponent(); Utils::fileExists(ApplicationData::Current->LocalFolder, ".config\\dring.yml") - .then([this](bool config_exists) + .then([this](bool config_exists) { if (config_exists) { RingD::instance->hasConfig = true; diff --git a/RingD.cpp b/RingD.cpp index 922b6d14dbb4f215b7e44fe6d5ef4806d38d343a..cacaad8bf22116dae83ae541537927414bd4634d 100644 --- a/RingD.cpp +++ b/RingD.cpp @@ -1,189 +1,189 @@ -/*************************************************************************** -* 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" -#include "fileutils.h" - -#include "account_schema.h" - -#include "SmartPanel.xaml.h" - -using namespace Windows::ApplicationModel::Core; -using namespace Windows::Storage; -using namespace Windows::UI::Core; - -using namespace RingClientUWP; -using namespace RingClientUWP::Utils; - -void -debugOutputWrapper(const std::string& str) -{ - MSG_(str); -} - -void -reloadAccountList() -{ - RingClientUWP::ViewModel::AccountsViewModel::instance->clearAccountList(); - std::vector<std::string> accountList = DRing::getAccountList(); - std::vector<std::string>::reverse_iterator rit = accountList.rbegin(); - for (; rit != accountList.rend(); ++rit) { - std::map<std::string,std::string> accountDetails = DRing::getAccountDetails(*rit); - std::string ringID(accountDetails.find(ring::Conf::CONFIG_ACCOUNT_USERNAME)->second); - if(!ringID.empty()) - ringID = ringID.substr(5); - RingClientUWP::ViewModel::AccountsViewModel::instance->add( - accountDetails.find(ring::Conf::CONFIG_ACCOUNT_ALIAS)->second, //name - ringID, //ringid - accountDetails.find(ring::Conf::CONFIG_ACCOUNT_TYPE)->second); //type - } -} - -void -RingClientUWP::RingD::startDaemon() -{ - create_task([&]() - { - using SharedCallback = std::shared_ptr<DRing::CallbackWrapperBase>; - using namespace std::placeholders; - - 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); - - incomingCall(accountId2, callId2, from2); - - }), - DRing::exportable_callback<DRing::CallSignal::StateChange>([this]( - const std::string& callId, - const std::string& state, - int code) - { - MSG_("<StateChange>"); - MSG_("callId = " + callId); - MSG_("state = " + state); - MSG_("code = " + std::to_string(code)); - - auto callId2 = toPlatformString(callId); - auto state2 = toPlatformString(state); - - stateChange(callId2, state2, code); - - }), - DRing::exportable_callback<DRing::ConfigurationSignal::IncomingAccountMessage>([this]( - const std::string& accountId, - const std::string& from, - const std::map<std::string, std::string>& payloads) - { - MSG_("<IncomingAccountMessage>"); - MSG_("accountId = " + accountId); - MSG_("from = " + from); - - for (auto i : payloads) { - MSG_("payload = " + i.second); - auto payload = Utils::toPlatformString(i.second); - } - }), - DRing::exportable_callback<DRing::ConfigurationSignal::AccountsChanged>([this]() - { - reloadAccountList(); - }) - }; - - registerCallHandlers(callHandlers); - - std::map<std::string, SharedCallback> dringDebugOutHandler; - dringDebugOutHandler.insert(DRing::exportable_callback<DRing::Debug::MessageSend> - (std::bind(&debugOutputWrapper, _1))); - registerCallHandlers(dringDebugOutHandler); - - std::map<std::string, SharedCallback> getAppPathHandler = - { - DRing::exportable_callback<DRing::ConfigurationSignal::GetAppDataPath> - ([this](std::vector<std::string>* paths) { - paths->emplace_back(localFolder_); - }) - }; - registerCallHandlers(getAppPathHandler); - - DRing::init(static_cast<DRing::InitFlag>(DRing::DRING_FLAG_CONSOLE_LOG | - DRing::DRING_FLAG_DEBUG | - DRing::DRING_FLAG_AUTOANSWER)); - - if (!DRing::start()) { - ERR_("\ndaemon didn't start.\n"); - return; - } - else { - if (!hasConfig) - { - std::map<std::string, std::string> ringAccountDetails; - ringAccountDetails.insert(std::make_pair(ring::Conf::CONFIG_ACCOUNT_ALIAS, accountName)); - ringAccountDetails.insert(std::make_pair(ring::Conf::CONFIG_ACCOUNT_TYPE,"RING")); - DRing::addAccount(ringAccountDetails); - } - CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, - ref new DispatchedHandler([=]() { - reloadAccountList(); - })); - while (true) { - DRing::pollEvents(); - Sleep(1000); - dequeueTasks(); - } - DRing::fini(); - } - }); -} - -RingD::RingD() -{ - localFolder_ = Utils::toString(ApplicationData::Current->LocalFolder->Path); -} - -void -RingD::dequeueTasks() -{ - for (int i = 0; i < tasksList_.size(); i++) { - auto task = tasksList_.front(); - switch (task->request) { - case Request::None: - default: - break; - } - tasksList_.pop(); - } -} +/*************************************************************************** +* 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" +#include "fileutils.h" + +#include "account_schema.h" + +#include "SmartPanel.xaml.h" + +using namespace Windows::ApplicationModel::Core; +using namespace Windows::Storage; +using namespace Windows::UI::Core; + +using namespace RingClientUWP; +using namespace RingClientUWP::Utils; + +void +debugOutputWrapper(const std::string& str) +{ + MSG_(str); +} + +void +reloadAccountList() +{ + RingClientUWP::ViewModel::AccountsViewModel::instance->clearAccountList(); + std::vector<std::string> accountList = DRing::getAccountList(); + std::vector<std::string>::reverse_iterator rit = accountList.rbegin(); + for (; rit != accountList.rend(); ++rit) { + std::map<std::string,std::string> accountDetails = DRing::getAccountDetails(*rit); + std::string ringID(accountDetails.find(ring::Conf::CONFIG_ACCOUNT_USERNAME)->second); + if(!ringID.empty()) + ringID = ringID.substr(5); + RingClientUWP::ViewModel::AccountsViewModel::instance->add( + accountDetails.find(ring::Conf::CONFIG_ACCOUNT_ALIAS)->second, //name + ringID, //ringid + accountDetails.find(ring::Conf::CONFIG_ACCOUNT_TYPE)->second); //type + } +} + +void +RingClientUWP::RingD::startDaemon() +{ + create_task([&]() + { + using SharedCallback = std::shared_ptr<DRing::CallbackWrapperBase>; + using namespace std::placeholders; + + 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); + + incomingCall(accountId2, callId2, from2); + + }), + DRing::exportable_callback<DRing::CallSignal::StateChange>([this]( + const std::string& callId, + const std::string& state, + int code) + { + MSG_("<StateChange>"); + MSG_("callId = " + callId); + MSG_("state = " + state); + MSG_("code = " + std::to_string(code)); + + auto callId2 = toPlatformString(callId); + auto state2 = toPlatformString(state); + + stateChange(callId2, state2, code); + + }), + DRing::exportable_callback<DRing::ConfigurationSignal::IncomingAccountMessage>([this]( + const std::string& accountId, + const std::string& from, + const std::map<std::string, std::string>& payloads) + { + MSG_("<IncomingAccountMessage>"); + MSG_("accountId = " + accountId); + MSG_("from = " + from); + + for (auto i : payloads) { + MSG_("payload = " + i.second); + auto payload = Utils::toPlatformString(i.second); + } + }), + DRing::exportable_callback<DRing::ConfigurationSignal::AccountsChanged>([this]() + { + reloadAccountList(); + }) + }; + + registerCallHandlers(callHandlers); + + std::map<std::string, SharedCallback> dringDebugOutHandler; + dringDebugOutHandler.insert(DRing::exportable_callback<DRing::Debug::MessageSend> + (std::bind(&debugOutputWrapper, _1))); + registerCallHandlers(dringDebugOutHandler); + + std::map<std::string, SharedCallback> getAppPathHandler = + { + DRing::exportable_callback<DRing::ConfigurationSignal::GetAppDataPath> + ([this](std::vector<std::string>* paths) { + paths->emplace_back(localFolder_); + }) + }; + registerCallHandlers(getAppPathHandler); + + DRing::init(static_cast<DRing::InitFlag>(DRing::DRING_FLAG_CONSOLE_LOG | + DRing::DRING_FLAG_DEBUG | + DRing::DRING_FLAG_AUTOANSWER)); + + if (!DRing::start()) { + ERR_("\ndaemon didn't start.\n"); + return; + } + else { + if (!hasConfig) + { + std::map<std::string, std::string> ringAccountDetails; + ringAccountDetails.insert(std::make_pair(ring::Conf::CONFIG_ACCOUNT_ALIAS, accountName)); + ringAccountDetails.insert(std::make_pair(ring::Conf::CONFIG_ACCOUNT_TYPE,"RING")); + DRing::addAccount(ringAccountDetails); + } + CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, + ref new DispatchedHandler([=]() { + reloadAccountList(); + })); + while (true) { + DRing::pollEvents(); + Sleep(1000); + dequeueTasks(); + } + DRing::fini(); + } + }); +} + +RingD::RingD() +{ + localFolder_ = Utils::toString(ApplicationData::Current->LocalFolder->Path); +} + +void +RingD::dequeueTasks() +{ + for (int i = 0; i < tasksList_.size(); i++) { + auto task = tasksList_.front(); + switch (task->request) { + case Request::None: + default: + break; + } + tasksList_.pop(); + } +} diff --git a/SmartPanel.xaml.cpp b/SmartPanel.xaml.cpp index b77347730ed82e770f3de3444677559207383713..c68b9ac44faaa2e845e8d3c7139687b6e30b01ec 100644 --- a/SmartPanel.xaml.cpp +++ b/SmartPanel.xaml.cpp @@ -1,180 +1,180 @@ -/*************************************************************************** - * Copyright (C) 2016 by Savoir-faire Linux * - * Author: Jäger Nicolas <nicolas.jager@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" - -#include "SmartPanel.xaml.h" - -using namespace Platform; - -using namespace RingClientUWP; -using namespace RingClientUWP::Views; -using namespace RingClientUWP::ViewModel; -using namespace Windows::Media::Capture; -using namespace Windows::UI::Xaml; -using namespace Windows::Storage; -using namespace Windows::UI::Xaml::Media::Imaging; -using namespace Windows::UI::Xaml::Shapes; -using namespace Windows::UI::Xaml::Media; -using namespace Concurrency; -using namespace Windows::Foundation; - -SmartPanel::SmartPanel() -{ - InitializeComponent(); - - _accountsList_->ItemsSource = AccountsViewModel::instance->accountsList; - _smartList_->ItemsSource = ContactsViewModel::instance->contactsList; -} - -void -RingClientUWP::Views::SmartPanel::updatePageContent() -{ - auto account = AccountsViewModel::instance->selectedAccount; - if (!account) - return; - - _selectedAccountName_->Text = account->name_; -} - -void RingClientUWP::Views::SmartPanel::_accountsMenuButton__Checked(Object^ sender, RoutedEventArgs^ e) -{ - _shareMenuButton_->IsChecked = false; - _accountsMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Visible; - _accountCreationMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; -} - -void RingClientUWP::Views::SmartPanel::_accountsMenuButton__Unchecked(Object^ sender, RoutedEventArgs^ e) -{ - _accountsMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; - _accountCreationMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; -} - -void RingClientUWP::Views::SmartPanel::_settings__Checked(Object^ sender, RoutedEventArgs^ e) -{ - _smartGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; - _settings_->Visibility = Windows::UI::Xaml::Visibility::Visible; -} - -void RingClientUWP::Views::SmartPanel::_settings__Unchecked(Object^ sender, RoutedEventArgs^ e) -{ - _settings_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; - _smartGrid_->Visibility = Windows::UI::Xaml::Visibility::Visible; -} - -void RingClientUWP::Views::SmartPanel::setMode(RingClientUWP::Views::SmartPanel::Mode mode) -{ - if (mode == RingClientUWP::Views::SmartPanel::Mode::Normal) { - _rowRingTxtBx_->Height = 40; - _selectedAccountAvatar_->Height = 80; - _selectedAccountAvatarColumn_->Width = 90; - _selectedAccountRow_->Height = 90; - } - else { - _rowRingTxtBx_->Height = 0; - _selectedAccountAvatar_->Height = 50; - _selectedAccountAvatarColumn_->Width = 60; - _selectedAccountRow_->Height = 60; - } - - _selectedAccountAvatar_->Width = _selectedAccountAvatar_->Height; - _settingsTBtn_->IsChecked = false; - _accountsMenuButton_->IsChecked = false; - _shareMenuButton_->IsChecked = false; -} - -void RingClientUWP::Views::SmartPanel::_shareMenuButton__Checked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) -{ - _shareMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Visible; - _accountsMenuButton_->IsChecked = false; -} - -void RingClientUWP::Views::SmartPanel::_shareMenuButton__Unchecked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) -{ - _shareMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; -} - -void RingClientUWP::Views::SmartPanel::_addAccountBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) -{ - _accountsMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; - _accountCreationMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Visible; -} - -void RingClientUWP::Views::SmartPanel::_createAccountYes__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) -{ - -} - -void RingClientUWP::Views::SmartPanel::_createAccountNo__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) -{ - -} - -void RingClientUWP::Views::SmartPanel::_avatarWebcamCaptureBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) -{ - CameraCaptureUI^ cameraCaptureUI = ref new CameraCaptureUI(); - cameraCaptureUI->PhotoSettings->Format = CameraCaptureUIPhotoFormat::Png; - cameraCaptureUI->PhotoSettings->CroppedSizeInPixels = Size(100, 100); - - - create_task(cameraCaptureUI->CaptureFileAsync(CameraCaptureUIMode::Photo)).then([this](StorageFile^ photo) - { - if (photo != nullptr) { - // maybe it would be possible to move some logics to the style sheet - auto brush = ref new ImageBrush(); - - auto circle = ref new Ellipse(); - circle->Height = 80; // TODO : use some global constant when ready - circle->Width = 80; - auto path = photo->Path; - auto uri = ref new Windows::Foundation::Uri(path); - auto bitmapImage = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(); - bitmapImage->UriSource = uri; - - brush->ImageSource = bitmapImage; - circle->Fill = brush; - _avatarWebcamCaptureBtn_->Content = circle; - } - }); - -} - -void -SmartPanel::_smartList__SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e) -{ - auto listbox = safe_cast<ListBox^>(sender); - auto contact = safe_cast<Contact^>(listbox->SelectedItem); - ContactsViewModel::instance->selectedContact = contact; -} - -void -SmartPanel::_accountList__SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e) -{ - auto listbox = safe_cast<ListBox^>(sender); - auto account = safe_cast<Account^>(listbox->SelectedItem); - AccountsViewModel::instance->selectedAccount = account; - updatePageContent(); -} - -void RingClientUWP::Views::SmartPanel::_ringTxtBx__KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) -{ - /* add contact, test purpose but will be reused later in some way */ - if (e->Key == Windows::System::VirtualKey::Enter && _ringTxtBx_->Text != "") { - ContactsViewModel::instance->addNewContact(_ringTxtBx_->Text, _ringTxtBx_->Text); - _ringTxtBx_->Text = ""; - } +/*************************************************************************** + * Copyright (C) 2016 by Savoir-faire Linux * + * Author: Jäger Nicolas <nicolas.jager@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" + +#include "SmartPanel.xaml.h" + +using namespace Platform; + +using namespace RingClientUWP; +using namespace RingClientUWP::Views; +using namespace RingClientUWP::ViewModel; +using namespace Windows::Media::Capture; +using namespace Windows::UI::Xaml; +using namespace Windows::Storage; +using namespace Windows::UI::Xaml::Media::Imaging; +using namespace Windows::UI::Xaml::Shapes; +using namespace Windows::UI::Xaml::Media; +using namespace Concurrency; +using namespace Windows::Foundation; + +SmartPanel::SmartPanel() +{ + InitializeComponent(); + + _accountsList_->ItemsSource = AccountsViewModel::instance->accountsList; + _smartList_->ItemsSource = ContactsViewModel::instance->contactsList; +} + +void +RingClientUWP::Views::SmartPanel::updatePageContent() +{ + auto account = AccountsViewModel::instance->selectedAccount; + if (!account) + return; + + _selectedAccountName_->Text = account->name_; +} + +void RingClientUWP::Views::SmartPanel::_accountsMenuButton__Checked(Object^ sender, RoutedEventArgs^ e) +{ + _shareMenuButton_->IsChecked = false; + _accountsMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Visible; + _accountCreationMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; +} + +void RingClientUWP::Views::SmartPanel::_accountsMenuButton__Unchecked(Object^ sender, RoutedEventArgs^ e) +{ + _accountsMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + _accountCreationMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; +} + +void RingClientUWP::Views::SmartPanel::_settings__Checked(Object^ sender, RoutedEventArgs^ e) +{ + _smartGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + _settings_->Visibility = Windows::UI::Xaml::Visibility::Visible; +} + +void RingClientUWP::Views::SmartPanel::_settings__Unchecked(Object^ sender, RoutedEventArgs^ e) +{ + _settings_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + _smartGrid_->Visibility = Windows::UI::Xaml::Visibility::Visible; +} + +void RingClientUWP::Views::SmartPanel::setMode(RingClientUWP::Views::SmartPanel::Mode mode) +{ + if (mode == RingClientUWP::Views::SmartPanel::Mode::Normal) { + _rowRingTxtBx_->Height = 40; + _selectedAccountAvatar_->Height = 80; + _selectedAccountAvatarColumn_->Width = 90; + _selectedAccountRow_->Height = 90; + } + else { + _rowRingTxtBx_->Height = 0; + _selectedAccountAvatar_->Height = 50; + _selectedAccountAvatarColumn_->Width = 60; + _selectedAccountRow_->Height = 60; + } + + _selectedAccountAvatar_->Width = _selectedAccountAvatar_->Height; + _settingsTBtn_->IsChecked = false; + _accountsMenuButton_->IsChecked = false; + _shareMenuButton_->IsChecked = false; +} + +void RingClientUWP::Views::SmartPanel::_shareMenuButton__Checked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + _shareMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Visible; + _accountsMenuButton_->IsChecked = false; +} + +void RingClientUWP::Views::SmartPanel::_shareMenuButton__Unchecked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + _shareMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; +} + +void RingClientUWP::Views::SmartPanel::_addAccountBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + _accountsMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + _accountCreationMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Visible; +} + +void RingClientUWP::Views::SmartPanel::_createAccountYes__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + +} + +void RingClientUWP::Views::SmartPanel::_createAccountNo__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + +} + +void RingClientUWP::Views::SmartPanel::_avatarWebcamCaptureBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + CameraCaptureUI^ cameraCaptureUI = ref new CameraCaptureUI(); + cameraCaptureUI->PhotoSettings->Format = CameraCaptureUIPhotoFormat::Png; + cameraCaptureUI->PhotoSettings->CroppedSizeInPixels = Size(100, 100); + + + create_task(cameraCaptureUI->CaptureFileAsync(CameraCaptureUIMode::Photo)).then([this](StorageFile^ photo) + { + if (photo != nullptr) { + // maybe it would be possible to move some logics to the style sheet + auto brush = ref new ImageBrush(); + + auto circle = ref new Ellipse(); + circle->Height = 80; // TODO : use some global constant when ready + circle->Width = 80; + auto path = photo->Path; + auto uri = ref new Windows::Foundation::Uri(path); + auto bitmapImage = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(); + bitmapImage->UriSource = uri; + + brush->ImageSource = bitmapImage; + circle->Fill = brush; + _avatarWebcamCaptureBtn_->Content = circle; + } + }); + +} + +void +SmartPanel::_smartList__SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e) +{ + auto listbox = safe_cast<ListBox^>(sender); + auto contact = safe_cast<Contact^>(listbox->SelectedItem); + ContactsViewModel::instance->selectedContact = contact; +} + +void +SmartPanel::_accountList__SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e) +{ + auto listbox = safe_cast<ListBox^>(sender); + auto account = safe_cast<Account^>(listbox->SelectedItem); + AccountsViewModel::instance->selectedAccount = account; + updatePageContent(); +} + +void RingClientUWP::Views::SmartPanel::_ringTxtBx__KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) +{ + /* add contact, test purpose but will be reused later in some way */ + if (e->Key == Windows::System::VirtualKey::Enter && _ringTxtBx_->Text != "") { + ContactsViewModel::instance->addNewContact(_ringTxtBx_->Text, _ringTxtBx_->Text); + _ringTxtBx_->Text = ""; + } } diff --git a/Utils.h b/Utils.h index f75f30fa383dcf130b283fdf19e74c5db9c5b246..05d54270b6132b02c7aecc2af3d95c7cbc611bd9 100644 --- a/Utils.h +++ b/Utils.h @@ -1,78 +1,78 @@ -#pragma once -#include <pch.h> - -using namespace Platform; -using namespace Windows::Storage; - -namespace RingClientUWP -{ -namespace Utils -{ - -task<bool> -fileExists(StorageFolder^ folder, String^ fileName) -{ - return create_task(folder->GetFileAsync(fileName)) - .then([](task<StorageFile^> taskResult) - { - bool exists; - try { - taskResult.get(); - exists = true; - } - catch (COMException ^e) { - if (e->HResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { - exists = false; - } - else { - throw; - } - } - return exists; - }); -} - -std::string makeString(const std::wstring& wstr) -{ - auto wideData = wstr.c_str(); - int bufferSize = WideCharToMultiByte(CP_UTF8, 0, wideData, -1, nullptr, 0, NULL, NULL); - - std::unique_ptr<char[]> utf8; - utf8.reset(new char[bufferSize]); - - if (WideCharToMultiByte(CP_UTF8, 0, wideData, -1, utf8.get(), bufferSize, NULL, NULL) == 0) { - return std::string(); - } - - return std::string(utf8.get()); -} - -std::wstring makeWString(const std::string& str) -{ - auto utf8Data = str.c_str(); - int bufferSize = MultiByteToWideChar(CP_UTF8, 0, utf8Data, -1, nullptr, 0); - - std::unique_ptr<wchar_t[]> wide; - wide.reset(new wchar_t[bufferSize]); - - if (MultiByteToWideChar(CP_UTF8, 0, utf8Data, -1, wide.get(), bufferSize) == 0) { - return std::wstring(); - } - - return std::wstring(wide.get());; -} - -std::string toString(Platform::String ^str) -{ - std::wstring wsstr(str->Data()); - return makeString(wsstr); -} - -Platform::String^ toPlatformString(const std::string& str) -{ - std::wstring wsstr = makeWString(str); - return ref new Platform::String(wsstr.c_str(), wsstr.length()); -} - -} +#pragma once +#include <pch.h> + +using namespace Platform; +using namespace Windows::Storage; + +namespace RingClientUWP +{ +namespace Utils +{ + +task<bool> +fileExists(StorageFolder^ folder, String^ fileName) +{ + return create_task(folder->GetFileAsync(fileName)) + .then([](task<StorageFile^> taskResult) + { + bool exists; + try { + taskResult.get(); + exists = true; + } + catch (COMException ^e) { + if (e->HResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { + exists = false; + } + else { + throw; + } + } + return exists; + }); +} + +std::string makeString(const std::wstring& wstr) +{ + auto wideData = wstr.c_str(); + int bufferSize = WideCharToMultiByte(CP_UTF8, 0, wideData, -1, nullptr, 0, NULL, NULL); + + std::unique_ptr<char[]> utf8; + utf8.reset(new char[bufferSize]); + + if (WideCharToMultiByte(CP_UTF8, 0, wideData, -1, utf8.get(), bufferSize, NULL, NULL) == 0) { + return std::string(); + } + + return std::string(utf8.get()); +} + +std::wstring makeWString(const std::string& str) +{ + auto utf8Data = str.c_str(); + int bufferSize = MultiByteToWideChar(CP_UTF8, 0, utf8Data, -1, nullptr, 0); + + std::unique_ptr<wchar_t[]> wide; + wide.reset(new wchar_t[bufferSize]); + + if (MultiByteToWideChar(CP_UTF8, 0, utf8Data, -1, wide.get(), bufferSize) == 0) { + return std::wstring(); + } + + return std::wstring(wide.get());; +} + +std::string toString(Platform::String ^str) +{ + std::wstring wsstr(str->Data()); + return makeString(wsstr); +} + +Platform::String^ toPlatformString(const std::string& str) +{ + std::wstring wsstr = makeWString(str); + return ref new Platform::String(wsstr.c_str(), wsstr.length()); +} + +} } \ No newline at end of file