Commit d3a3b1c4 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

Incoming call with PN + ringing interface working

parent 387d57b8
using Microsoft.Phone.Networking.Voip;
using System.Diagnostics;
using Linphone.BackEnd;
using System.Threading;
using Linphone.BackEnd.OutOfProcess;
namespace Linphone.Agents
{
public class LinphoneForegroundLifeTimeAgent : VoipForegroundLifetimeAgent
{
public LinphoneForegroundLifeTimeAgent() : base()
{
}
protected override void OnLaunched()
{
Debug.WriteLine("[LinphoneForegroundLifeTimeAgent] The UI has entered the foreground.");
Globals.Instance.StartServer(RegistrationHelper.OutOfProcServerClassNames);
}
protected override void OnCancel()
{
Debug.WriteLine("[LinphoneForegroundLifeTimeAgent] The UI is leaving the foreground");
uint currentProcessId = Globals.GetCurrentProcessId();
string backgroundProcessReadyEventName = Globals.GetBackgroundProcessReadyEventName(currentProcessId);
using (EventWaitHandle backgroundProcessReadyEvent = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset, name: backgroundProcessReadyEventName))
{
backgroundProcessReadyEvent.WaitOne();
Debug.WriteLine("[LinphoneForegroundLifeTimeAgent] Background process {0} is ready", currentProcessId);
}
base.NotifyComplete();
}
}
using Microsoft.Phone.Networking.Voip;
using System.Diagnostics;
using Linphone.BackEnd;
using System.Threading;
using Linphone.BackEnd.OutOfProcess;
namespace Linphone.Agents
{
public class LinphoneForegroundLifeTimeAgent : VoipForegroundLifetimeAgent
{
public LinphoneForegroundLifeTimeAgent() : base()
{
}
protected override void OnLaunched()
{
Debug.WriteLine("[LinphoneForegroundLifeTimeAgent] The UI has entered the foreground.");
Globals.Instance.StartServer(RegistrationHelper.OutOfProcServerClassNames);
}
protected override void OnCancel()
{
Debug.WriteLine("[LinphoneForegroundLifeTimeAgent] The UI is leaving the foreground");
uint currentProcessId = Globals.GetCurrentProcessId();
string backgroundProcessReadyEventName = Globals.GetBackgroundProcessReadyEventName(currentProcessId);
using (EventWaitHandle backgroundProcessReadyEvent = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset, name: backgroundProcessReadyEventName))
{
backgroundProcessReadyEvent.WaitOne();
Debug.WriteLine("[LinphoneForegroundLifeTimeAgent] Background process {0} is ready", currentProcessId);
}
Debug.WriteLine("[LinphoneForegroundLifeTimeAgent] NotifyComplete");
base.NotifyComplete();
}
}
}
\ No newline at end of file
......@@ -2,43 +2,65 @@
using Microsoft.Phone.Scheduler;
using Linphone.BackEnd;
using Linphone.BackEnd.OutOfProcess;
using System.Diagnostics;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;
using System;
namespace Linphone
namespace Linphone.Agents
{
class LinphoneScheduledAgent : ScheduledTaskAgent
public class LinphoneScheduledAgent : ScheduledTaskAgent
{
// Indicates if this agent instance is handling an incoming call or not
private bool isIncomingCallAgent;
// Strings used in tracing
private const string keepAliveAgentId = "KeepAliveAgent";
private const string incomingCallAgentId = "IncomingCallAgent";
public LinphoneScheduledAgent()
{
}
protected override void OnInvoke(ScheduledTask task)
{
Debug.WriteLine("[LinphoneScheduledAgent] ScheduledAgentImpl has been invoked with argument of type {0}.", task.GetType());
Globals.Instance.StartServer(RegistrationHelper.OutOfProcServerClassNames);
VoipHttpIncomingCallTask incomingCallTask = task as VoipHttpIncomingCallTask;
if (incomingCallTask != null)
{
isIncomingCallAgent = true;
}
else
{
VoipKeepAliveTask keepAliveTask = task as VoipKeepAliveTask;
if (keepAliveTask != null)
{
isIncomingCallAgent = false;
}
}
}
protected override void OnInvoke(ScheduledTask task)
{
Debug.WriteLine("[LinphoneScheduledAgent] ScheduledAgentImpl has been invoked with argument of type {0}.", task.GetType());
Globals.Instance.StartServer(RegistrationHelper.OutOfProcServerClassNames);
VoipHttpIncomingCallTask incomingCallTask = task as VoipHttpIncomingCallTask;
if (incomingCallTask != null)
{
this.isIncomingCallAgent = true;
String message = System.Text.Encoding.UTF8.GetString(incomingCallTask.MessageBody, 0, incomingCallTask.MessageBody.Length);
Debug.WriteLine("[LinphoneScheduledAgent] Received VoIP Incoming Call task with body {0}", message);
//TODO Parse the the incoming push notification message
String callerName = "", callerNumber = "";
Debug.WriteLine("[{0}] Incoming call from caller {1}, number {2}", "KeepAliveAgent", callerName, callerNumber);
// Initiate incoming call processing
// If you want to pass in additional information such as pushNotification.Number, you can
bool incomingCallProcessingStarted = BackEnd.Globals.Instance.CallController.OnIncomingCallReceived(callerName, callerNumber, this.OnIncomingCallDialogDismissed);
if (!incomingCallProcessingStarted)
{
// For some reasons, the incoming call processing was not started.
base.NotifyComplete();
return;
}
}
else
{
VoipKeepAliveTask keepAliveTask = task as VoipKeepAliveTask;
if (keepAliveTask != null)
{
this.isIncomingCallAgent = false;
base.NotifyComplete();
}
else
{
throw new InvalidOperationException(string.Format("Unknown scheduled task type {0}", task.GetType()));
}
}
}
private void OnIncomingCallDialogDismissed()
......@@ -49,8 +71,8 @@ namespace Linphone
}
protected override void OnCancel()
{
Debug.WriteLine("[{0}] Cancel requested.", this.isIncomingCallAgent ? LinphoneScheduledAgent.incomingCallAgentId : LinphoneScheduledAgent.keepAliveAgentId);
{
Debug.WriteLine("[{0}] Cancel requested.", this.isIncomingCallAgent ? "IncomingCallAgent" : "KeepAliveAgent");
base.NotifyComplete();
}
......
......@@ -7,8 +7,70 @@ using namespace Windows::Foundation;
using namespace Windows::Phone::Media::Devices;
using namespace Windows::Phone::Networking::Voip;
CallController::CallController()
bool CallController::OnIncomingCallReceived(Platform::String^ contactName, Platform::String^ contactNumber, IncomingCallDialogDismissedCallback^ incomingCallDialogDismissedCallback)
{
std::lock_guard<std::recursive_mutex> lock(g_apiLock);
VoipPhoneCall^ incomingCall = nullptr;
try
{
TimeSpan ringingTimeout;
ringingTimeout.Duration = 90 * 10 * 1000 * 1000; // in 100ns units
::OutputDebugString(L"[CallController::OnIncomingCallReceived] => Will time out in 90 seconds\n");
// Ask the Phone Service to start a new incoming call
this->callCoordinator->RequestNewIncomingCall(
this->callInProgressPageUri,
contactName,
contactNumber,
this->defaultContactImageUri,
this->voipServiceName,
this->linphoneImageUri,
"",
this->ringtoneUri,
VoipCallMedia::Audio,
ringingTimeout,
&incomingCall);
}
catch(...)
{
return false;
}
// Register for events about this incoming call.
incomingCall->AnswerRequested += this->acceptCallRequestedHandler;
incomingCall->RejectRequested += this->rejectCallRequestedHandler;
return true;
}
void CallController::OnAcceptCallRequested(VoipPhoneCall^ sender, CallAnswerEventArgs^ args)
{
}
void CallController::OnRejectCallRequested(VoipPhoneCall^ sender, CallRejectEventArgs^ args)
{
}
CallController::CallController() :
callInProgressPageUri(L"/Views/InCall.xaml"),
voipServiceName(nullptr),
defaultContactImageUri(nullptr),
linphoneImageUri(nullptr),
ringtoneUri(nullptr)
{
this->callCoordinator = VoipCallCoordinator::GetDefault();
// URIs required for interactions with the VoipCallCoordinator
String^ installFolder = String::Concat(Windows::ApplicationModel::Package::Current->InstalledLocation->Path, "\\");
this->defaultContactImageUri = ref new Uri(installFolder, "Assets\\unknown.png");
this->voipServiceName = ref new String(L"Linphone");
this->linphoneImageUri = ref new Uri(installFolder, "Assets\\AppIcon.png");
this->ringtoneUri = ref new Uri(installFolder, "Assets\\Sounds\\Ringtone.wma");
this->acceptCallRequestedHandler = ref new TypedEventHandler<VoipPhoneCall^, CallAnswerEventArgs^>(this, &CallController::OnAcceptCallRequested);
this->rejectCallRequestedHandler = ref new TypedEventHandler<VoipPhoneCall^, CallRejectEventArgs^>(this, &CallController::OnRejectCallRequested);
}
CallController::~CallController()
......
......@@ -7,18 +7,52 @@ namespace Linphone
namespace BackEnd
{
// Forward declaration
ref class Globals;
ref class Globals;
// A method that is called back when the incoming call dialog has been dismissed.
// This callback is used to complete the incoming call agent.
public delegate void IncomingCallDialogDismissedCallback();
// A class that provides methods and properties related to VoIP calls.
// It wraps Windows.Phone.Networking.Voip.VoipCallCoordinator, and provides app-specific call functionality.
public ref class CallController sealed
{
public:
// Start processing an incoming call. Called by managed code in this process (the VoIP agent host process).
// Returns true if the incoming call processing was started, false otherwise.
bool OnIncomingCallReceived(Platform::String^ contactName, Platform::String^ contactNumber, IncomingCallDialogDismissedCallback^ incomingCallDialogDismissedCallback);
private:
// Only the server can create an instance of this object
friend ref class Linphone::BackEnd::Globals;
friend ref class Linphone::BackEnd::Globals;
Platform::String^ voipServiceName;
// The relative URI to the call-in-progress page
Platform::String ^callInProgressPageUri;
// The URI to the contact image, jpg or png, 1mb max !
Windows::Foundation::Uri^ defaultContactImageUri;
// The URI to the linphone icon, 128kb max !
Windows::Foundation::Uri^ linphoneImageUri;
// The URI to the ringtone file, mp3 or wma, 1mb max !
Windows::Foundation::Uri^ ringtoneUri;
// The VoIP call coordinator
Windows::Phone::Networking::Voip::VoipCallCoordinator^ callCoordinator;
// Called by the VoipCallCoordinator when the user accepts an incoming call.
void OnAcceptCallRequested(Windows::Phone::Networking::Voip::VoipPhoneCall^ sender, Windows::Phone::Networking::Voip::CallAnswerEventArgs^ args);
// Called by the VoipCallCoordinator when the user rejects an incoming call.
void OnRejectCallRequested(Windows::Phone::Networking::Voip::VoipPhoneCall^ sender, Windows::Phone::Networking::Voip::CallRejectEventArgs^ args);
// Phone call related event handlers
Windows::Foundation::TypedEventHandler<Windows::Phone::Networking::Voip::VoipPhoneCall^, Windows::Phone::Networking::Voip::CallAnswerEventArgs^>^ acceptCallRequestedHandler;
Windows::Foundation::TypedEventHandler<Windows::Phone::Networking::Voip::VoipPhoneCall^, Windows::Phone::Networking::Voip::CallRejectEventArgs^>^ rejectCallRequestedHandler;
// Constructor and destructor
CallController();
~CallController();
......
No preview for this file type
This diff is collapsed.
Linphone/Assets/AppIcon.png

16.6 KB | W: | H:

Linphone/Assets/AppIcon.png

16.6 KB | W: | H:

Linphone/Assets/AppIcon.png
Linphone/Assets/AppIcon.png
Linphone/Assets/AppIcon.png
Linphone/Assets/AppIcon.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -321,6 +321,8 @@
<Content Include="Assets\Numpad\numpad_two_over.png" />
<Content Include="Assets\Numpad\numpad_zero_default.png" />
<Content Include="Assets\Numpad\numpad_zero_over.png" />
<Content Include="Assets\Sounds\Ringtone.wma" />
<Content Include="Assets\unknown.png" />
<Content Include="Toolkit.Content\ApplicationBar.Cancel.png" />
<Content Include="Toolkit.Content\ApplicationBar.Check.png" />
<Content Include="Toolkit.Content\ApplicationBar.Delete.png" />
......@@ -342,6 +344,7 @@
<Name>BackEnd</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
......
......@@ -76,7 +76,7 @@ namespace Linphone.Model
}
else
{
Debug.WriteLine("[App] Background process {0} is ready", backgroundProcessID);
Debug.WriteLine("[LinphoneManager] Background process {0} is ready", backgroundProcessID);
}
}
// The background process is now ready.
......
......@@ -207,7 +207,7 @@ namespace Linphone.Model
{
get
{
return GetValueOrDefault<string>(TransportSettingKeyName, resourceManager.GetString("TransportDefault"));
return GetValueOrDefault<string>(TransportSettingKeyName, resourceManager.GetString("Transport"));
}
set
{
......@@ -222,7 +222,7 @@ namespace Linphone.Model
{
get
{
return GetValueOrDefault<bool?>(SendDTFMsRFC2833KeyName, Boolean.Parse(resourceManager.GetString("RFC2833Default")));
return GetValueOrDefault<bool?>(SendDTFMsRFC2833KeyName, Boolean.Parse(resourceManager.GetString("RFC2833")));
}
set
{
......
......@@ -50,28 +50,11 @@
<ActivatableClass ActivatableClassId="Linphone.BackEnd.CallController" ThreadingModel="MTA" />
<ActivatableClass ActivatableClassId="Linphone.BackEnd.Globals" ThreadingModel="MTA" />
</InProcessServer>
<InProcessServer>
<Path>PhoneVoIPApp.BackEnd.DLL</Path>
<ActivatableClass ActivatableClassId="PhoneVoIPApp.BackEnd.CallController" ThreadingModel="MTA" />
<ActivatableClass ActivatableClassId="PhoneVoIPApp.BackEnd.Globals" ThreadingModel="MTA" />
</InProcessServer>
<OutOfProcessServer ServerName="Linphone.BackEnd">
<Path>Linphone.BackEnd.DLL</Path>
<Instancing>multipleInstances</Instancing>
<ActivatableClass ActivatableClassId="Linphone.BackEnd.OutOfProcess.Server" />
</OutOfProcessServer>
<OutOfProcessServer ServerName="PhoneVoIPApp.BackEnd">
<Path>PhoneVoIPApp.BackEnd.DLL</Path>
<Instancing>multipleInstances</Instancing>
<ActivatableClass ActivatableClassId="PhoneVoIPApp.BackEnd.OutOfProcess.Server" />
</OutOfProcessServer>
<ProxyStub ClassId="{06B50718-3528-3B66-BE76-E183AA80D4A5}">
<Path>PhoneVoIPApp.BackEndProxyStub.DLL</Path>
<Interface Name="PhoneVoIPApp.BackEnd.__ICallControllerPublicNonVirtuals" InterfaceId="{06B50718-3528-3B66-BE76-E183AA80D4A5}" />
<Interface Name="PhoneVoIPApp.BackEnd.__IGlobalsPublicNonVirtuals" InterfaceId="{C8AFE1A8-92FC-3783-9520-D6BBC507B24A}" />
<Interface Name="PhoneVoIPApp.BackEnd.__IGlobalsStatics" InterfaceId="{2C1E9C37-6827-38F7-857C-021642CA428B}" />
<Interface Name="PhoneVoIPApp.BackEnd.OutOfProcess.__IServerPublicNonVirtuals" InterfaceId="{7BF79491-56BE-375A-BC22-0058B158F01F}" />
</ProxyStub>
<ProxyStub ClassId="{C140594A-6BD4-3151-944E-28C955632D15}">
<Path>Linphone.BackEndProxyStub.DLL</Path>
<Interface Name="Linphone.BackEnd.__ICallControllerPublicNonVirtuals" InterfaceId="{C140594A-6BD4-3151-944E-28C955632D15}" />
......
......@@ -60,21 +60,30 @@ namespace Linphone.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to 3600.
/// </summary>
internal static string KeepAlive {
get {
return ResourceManager.GetString("KeepAlive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to false.
/// </summary>
internal static string RFC2833Default {
internal static string RFC2833 {
get {
return ResourceManager.GetString("RFC2833Default", resourceCulture);
return ResourceManager.GetString("RFC2833", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to UDP.
/// </summary>
internal static string TransportDefault {
internal static string Transport {
get {
return ResourceManager.GetString("TransportDefault", resourceCulture);
return ResourceManager.GetString("Transport", resourceCulture);
}
}
......
......@@ -117,10 +117,14 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="RFC2833Default" xml:space="preserve">
<data name="KeepAlive" xml:space="preserve">
<value>3600</value>
<comment>Seconds for keep-alive task</comment>
</data>
<data name="RFC2833" xml:space="preserve">
<value>false</value>
</data>
<data name="TransportDefault" xml:space="preserve">
<data name="Transport" xml:space="preserve">
<value>UDP</value>
</data>
<data name="TunnelMode" xml:space="preserve">
......
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