Commit 593926fb authored by atraczyk's avatar atraczyk Committed by Andreas Traczyk

ui/ux: add ringtones

- adds ringtone file to assets directory

- adds the ability to play and stop/restart a ringtone

- adds a toast pop notification on incoming call using
  background audio

- adds a background tasks to respond to call rejection

Change-Id: Ica7195fa0fa32dc10d9207399d98bed518373d15
Tuleap: #790
parent d1ba40d2
......@@ -38,6 +38,9 @@ App::App()
{
InitializeComponent(); // summon partial class, form generated files trough App.xaml
this->EnteredBackground += ref new EnteredBackgroundEventHandler(this, &App::App_EnteredBackground);
this->LeavingBackground += ref new LeavingBackgroundEventHandler(this, &App::App_LeavingBackground);
/* connect to delegate */
RingD::instance->summonWizard += ref new RingClientUWP::SummonWizard(this, &RingClientUWP::App::OnsummonWizard);
}
......@@ -77,4 +80,26 @@ void App::OnsummonWizard()
{
ApplicationView::GetForCurrentView()->TryResizeView(Size(400, 600));
rootFrame->Navigate(Windows::UI::Xaml::Interop::TypeName(Views::Wizard::typeid));
}
void App::App_EnteredBackground(Platform::Object^ sender, EnteredBackgroundEventArgs^ e)
{
MSG_("App_EnteredBackground");
RingD::instance->isInBackground = true;
}
void App::App_LeavingBackground(Platform::Object^ sender, LeavingBackgroundEventArgs^ e)
{
MSG_("App_LeavingBackground");
RingD::instance->isInBackground = false;
}
void App::OnActivated(IActivatedEventArgs^ e)
{
if (e->Kind == ActivationKind::ToastNotification) {
auto toastArgs = safe_cast<ToastNotificationActivatedEventArgs^>(e);
std::string args = Utils::toString(toastArgs->Argument);
if (!args.empty())
RingD::instance->acceptIncommingCall(Utils::toPlatformString(args));
}
}
\ No newline at end of file
......@@ -20,6 +20,8 @@
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Background;
namespace RingClientUWP
{
......@@ -28,6 +30,10 @@ ref class App sealed
{
protected:
virtual void OnLaunched(LaunchActivatedEventArgs^ e) override;
virtual void OnActivated(IActivatedEventArgs^ e) override;
void App_EnteredBackground(Platform::Object^ sender, EnteredBackgroundEventArgs^ e);
void App_LeavingBackground(Platform::Object^ sender, LeavingBackgroundEventArgs^ e);
internal:
App();
......@@ -36,4 +42,5 @@ private:
Frame^ rootFrame;
void OnsummonWizard();
};
}
\ No newline at end of file
......@@ -145,7 +145,23 @@ RingClientUWP::MainPage::showFrame(Windows::UI::Xaml::Controls::Frame^ frame)
void
RingClientUWP::MainPage::OnNavigatedTo(NavigationEventArgs ^ e)
{
auto iter = BackgroundTaskRegistration::AllTasks->First();
auto hascur = iter->HasCurrent;
while (hascur)
{
auto cur = iter->Current->Value;
cur->Unregister(true);
hascur = iter->MoveNext();
}
BackgroundExecutionManager::RequestAccessAsync();
BackgroundTaskBuilder^ builder = ref new BackgroundTaskBuilder();
builder->Name = "CallRefusalBackgroundTask";
//builder->TaskEntryPoint = "RingClientUWP.BackgroundActivity";
builder->SetTrigger(ref new ToastNotificationActionTrigger());
BackgroundTaskRegistration^ registration = builder->Register();
RingD::instance->init();
showLoadingOverlay(true, false);
}
......
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
IgnorableNamespaces="uap uap3 mp">
<Identity Name="Savoir-faireLinux.GNURing" Publisher="CN=8121A5F7-3CA1-4CAA-92B2-4F595B011941" Version="1.1.12.0" />
<mp:PhoneIdentity PhoneProductId="2385953f-9019-423d-aa82-d1bbacfa258b" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
......@@ -8,7 +12,7 @@
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
......@@ -27,6 +31,7 @@
<Capability Name="internetClientServer" />
<Capability Name="internetClient" />
<Capability Name="privateNetworkClientServer" />
<uap3:Capability Name="backgroundMediaPlayback"/>
<uap:Capability Name="userAccountInformation" />
<DeviceCapability Name="microphone" />
<DeviceCapability Name="webcam" />
......
......@@ -47,6 +47,7 @@ using namespace RingClientUWP;
using namespace RingClientUWP::Utils;
using namespace RingClientUWP::ViewModel;
using namespace Windows::System;
void
......@@ -365,6 +366,52 @@ void RingClientUWP::RingD::registerThisDevice(String ^ pin, String ^ archivePass
pin = "";
}
void
ShowCallToast(String^ callId, String^ from = nullptr)
{
String^ payload =
"<toast scenario='incomingCall'> "
"<visual> "
"<binding template='ToastGeneric'>"
"<text>GNU Ring - Incoming call"+ (from?(" from " + from):"") +"</text>"
"</binding>"
"</visual>"
/*"<actions>"
"<action arguments = '" + callId + "' content = 'Accept' />"
"</actions>"*/
"<audio src='ms-appx:///Assets/default.wav' loop='true'/>"
"</toast>";
auto doc = ref new XmlDocument();
doc->LoadXml(payload);
auto toast = ref new ToastNotification(doc);
ToastNotificationManager::CreateToastNotifier()->Show(toast);
}
void
ShowMsgToast(String^ from, String^ payload)
{
String^ xml =
"<toast scenario='incomingMessage'> "
"<visual> "
"<binding template='ToastGeneric'>"
"<text>" + from + " : " + payload + "</text>"
"</binding>"
"</visual>"
"<actions>"
"<action arguments = '" + from + "'/>"
"</actions>"
"<audio src='ms-appx:///Assets/message_notification_sound.wav' loop='false'/>"
"</toast>";
auto doc = ref new XmlDocument();
doc->LoadXml(xml);
auto toast = ref new ToastNotification(doc);
ToastNotificationManager::CreateToastNotifier()->Show(toast);
}
void
RingD::registerCallbacks()
{
......@@ -469,15 +516,30 @@ RingD::registerCallbacks()
if (state3 == CallStatus::OUTGOING_RINGING ||
state3 == CallStatus::INCOMING_RINGING) {
try {
//Configuration::UserPreferences::instance->sendVCard(callId);
Configuration::UserPreferences::instance->sendVCard(callId);
}
catch (Exception^ e) {
EXC_(e);
}
}
if (state3 == CallStatus::ENDED)
if (state3 == CallStatus::INCOMING_RINGING) {
if (isInBackground) {
ringtone_->Start();
ShowCallToast(callId2);
}
else
ringtone_->Start();
}
if (state3 == CallStatus::IN_PROGRESS) {
ringtone_->Stop();
}
if (state3 == CallStatus::ENDED) {
DRing::hangUp(callId); // solve a bug in the daemon API.
ringtone_->Stop();
}
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
......@@ -881,6 +943,7 @@ RingD::startDaemon()
RingD::RingD()
{
ringtone_ = ref new Ringtone("default.wav");
localFolder_ = Utils::toString(ApplicationData::Current->LocalFolder->Path);
callIdsList_ = ref new Vector<String^>();
currentCallId = nullptr;
......
......@@ -18,10 +18,16 @@
**************************************************************************/
#include <dring.h>
#include "Ringtone.h"
using namespace concurrency;
using namespace Windows::UI::Notifications;
using namespace Windows::Data::Xml::Dom;
namespace RingClientUWP
{
// its ok to keep this enum here and to use it with the wizard, because in pch.h headers are a-z sorted,
// but it would be much more consistent to move this enum in globals.h when merged
......@@ -83,6 +89,7 @@ public:
}
}
property bool isInBackground;
property StartingStatus _startingStatus;
void cancelOutGoingCall2(String^ callId); // marche
......@@ -252,6 +259,7 @@ private:
StartingStatus startingStatus_ = StartingStatus::NORMAL;
bool editModeOn_ = false;
bool debugModeOn_ = true;
Ringtone^ ringtone_;
std::map<std::string, SharedCallback> callHandlers;
std::map<std::string, SharedCallback> getAppPathHandler;
......
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux *
* Author: Jger 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"
using namespace Windows::UI::Core;
using namespace RingClientUWP;
Ringtone::Ringtone(String^ fileName)
{
fileName_ = fileName;
CreateGraph()
.then([this](task<void> t) {
t.get();
CreateDefaultDeviceOutputNode()
.then([this](task<void> t) {
t.get();
CreateFileInputNode()
.then([](task<void> t) {
t.get();
});
});
});
}
void
Ringtone::Start()
{
_graph->Start();
}
void
Ringtone::Stop()
{
_graph->Stop();
_graph->ResetAllNodes();
}
task<void>
Ringtone::CreateGraph()
{
AudioGraphSettings^ settings = ref new AudioGraphSettings(Windows::Media::Render::AudioRenderCategory::Media);
return create_task(AudioGraph::CreateAsync(settings))
.then([=](CreateAudioGraphResult^ result){
if (result->Status != AudioGraphCreationStatus::Success) {
MSG_("CreateGraph failed");
}
_graph = result->Graph;
});
}
task<void>
Ringtone::CreateDefaultDeviceOutputNode()
{
return create_task(_graph->CreateDeviceOutputNodeAsync())
.then([=](CreateAudioDeviceOutputNodeResult^ result){
if (result->Status != AudioDeviceNodeCreationStatus::Success) {
MSG_("CreateDefaultDeviceOutputNode failed");
}
_deviceOutputNode = result->DeviceOutputNode;
});
}
task<void>
Ringtone::CreateFileInputNode()
{
Windows::ApplicationModel::Package^ package = Windows::ApplicationModel::Package::Current;
Windows::Storage::StorageFolder^ installedLocation = package->InstalledLocation;
return create_task(installedLocation->GetFolderAsync("Assets"))
.then([=](StorageFolder^ assetsFolder){
create_task(assetsFolder->GetFileAsync(fileName_))
.then([=](StorageFile^ ringtoneFile){
// functions as a Background task but will force a SMTC panel into the thumbnail
//mp = ref new MediaPlayer();
//mp->Source = MediaSource::CreateFromStorageFile(ringtoneFile);
////mp->CommandManager->IsEnabled = false;
//mp->IsLoopingEnabled = true;
//mp->Play();
create_task(_graph->CreateFileInputNodeAsync(ringtoneFile))
.then([=](CreateAudioFileInputNodeResult^ result){
if (result->Status != AudioFileNodeCreationStatus::Success) {
MSG_("CreateFileInputNode failed");
}
_fileInputNode = result->FileInputNode;
_fileInputNode->LoopCount = nullptr;
_fileInputNode->AddOutgoingConnection(_deviceOutputNode);
});
});
});
}
\ No newline at end of file
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux *
* Author: Jger 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/>. *
**************************************************************************/
#pragma once
using namespace Platform;
using namespace Windows::Media::Audio;
using namespace Windows::Media::Core;
using namespace Windows::Media::Playback;
namespace RingClientUWP
{
public ref class Ringtone sealed
{
public:
Ringtone(String^ fileName);
void Start();
void Stop();
private:
AudioFileInputNode^ _fileInputNode;
AudioGraph^ _graph;
AudioDeviceOutputNode^ _deviceOutputNode;
MediaPlayer^ mp;
String^ fileName_;
task<void> CreateGraph();
task<void> CreateDefaultDeviceOutputNode();
task<void> CreateFileInputNode();
};
}
\ No newline at end of file
......@@ -80,7 +80,7 @@ UserPreferences::Stringify()
preferencesObject->SetNamedValue("PREF_ACCOUNT_INDEX", JsonValue::CreateNumberValue( PREF_ACCOUNT_INDEX ));
preferencesObject->SetNamedValue("PREF_PROFILE_HASPHOTO", JsonValue::CreateBooleanValue( PREF_PROFILE_HASPHOTO));
preferencesObject->SetNamedValue("PREF_PROFILE_UID", JsonValue::CreateNumberValue( PREF_PROFILE_UID ));
preferencesObject->SetNamedValue("PREF_PROFILE_UID", JsonValue::CreateNumberValue(static_cast<double>(PREF_PROFILE_UID)));
return preferencesObject->Stringify();
}
......
......@@ -50,8 +50,11 @@
#include "UserPreferences.h"
#include "VCardUtils.h"
/* video headers */
/* video */
#include "Video.h"
#include "VideoCaptureManager.h"
#include "VideoManager.h"
#include "VideoRendererManager.h"
/* audio */
#include "Ringtone.h"
\ No newline at end of file
......@@ -7,8 +7,8 @@
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.10240.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.14393.0</WindowsTargetPlatformMinVersion>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
......@@ -199,6 +199,9 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="RingDebug.h" />
<ClInclude Include="Ringtone.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="SmartPanel.xaml.h">
<DependentUpon>SmartPanel.xaml</DependentUpon>
</ClInclude>
......@@ -333,6 +336,9 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="RingDebug.cpp" />
<ClCompile Include="Ringtone.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="SmartPanel.xaml.cpp">
<DependentUpon>SmartPanel.xaml</DependentUpon>
</ClCompile>
......@@ -364,6 +370,10 @@
<ItemGroup>
<None Include="Package.StoreAssociation.xml" />
</ItemGroup>
<ItemGroup>
<Media Include="Assets\default.wav" />
<Media Include="Assets\message_notification_sound.wav" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
......
......@@ -77,6 +77,9 @@
<ClCompile Include="VCardUtils.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Ringtone.cpp">
<Filter>Media\Audio</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="LoadingPage.xaml.h" />
......@@ -150,6 +153,9 @@
<ClInclude Include="VCardUtils.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Ringtone.h">
<Filter>Media\Audio</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="Assets\AccountTypeRING.png">
......@@ -316,4 +322,12 @@
<UniqueIdentifier>{b81596e4-e16c-4537-9631-65655360cbf4}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Media Include="Assets\default.wav">
<Filter>Assets</Filter>
</Media>
<Media Include="Assets\message_notification_sound.wav">
<Filter>Assets</Filter>
</Media>
</ItemGroup>
</Project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment