Commit 2bc03527 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

C++ Interface for Liblinphone started

parent d3a3b1c4
using Microsoft.Phone.Networking.Voip;
using Microsoft.Phone.Scheduler;
using Linphone.BackEnd;
using Linphone.BackEnd.OutOfProcess;
using Microsoft.Phone.Networking.Voip;
using Microsoft.Phone.Scheduler;
using Linphone.BackEnd;
using Linphone.BackEnd.OutOfProcess;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;
using System;
namespace Linphone.Agents
{
public class LinphoneScheduledAgent : ScheduledTaskAgent
{
// Indicates if this agent instance is handling an incoming call or not
private bool isIncomingCallAgent;
public LinphoneScheduledAgent()
{
using System;
namespace Linphone.Agents
{
public class LinphoneScheduledAgent : ScheduledTaskAgent
{
// Indicates if this agent instance is handling an incoming call or not
private bool isIncomingCallAgent;
public LinphoneScheduledAgent()
{
}
protected override void OnInvoke(ScheduledTask task)
......@@ -61,20 +61,20 @@ namespace Linphone.Agents
throw new InvalidOperationException(string.Format("Unknown scheduled task type {0}", task.GetType()));
}
}
}
private void OnIncomingCallDialogDismissed()
{
Debug.WriteLine("[IncomingCallAgent] Incoming call processing is now complete.");
base.NotifyComplete();
}
protected override void OnCancel()
}
private void OnIncomingCallDialogDismissed()
{
Debug.WriteLine("[{0}] Cancel requested.", this.isIncomingCallAgent ? "IncomingCallAgent" : "KeepAliveAgent");
base.NotifyComplete();
}
}
}
Debug.WriteLine("[IncomingCallAgent] Incoming call processing is now complete.");
base.NotifyComplete();
}
protected override void OnCancel()
{
Debug.WriteLine("[{0}] Cancel requested.", this.isIncomingCallAgent ? "IncomingCallAgent" : "KeepAliveAgent");
base.NotifyComplete();
}
}
}
This diff is collapsed.
#include "CallController.h"
#include "Server.h"
using namespace Linphone::BackEnd;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Phone::Media::Devices;
using namespace Windows::Phone::Networking::Voip;
#include "CallController.h"
#include "Server.h"
using namespace Linphone::BackEnd;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Phone::Media::Devices;
using namespace Windows::Phone::Networking::Voip;
bool CallController::OnIncomingCallReceived(Platform::String^ contactName, Platform::String^ contactNumber, IncomingCallDialogDismissedCallback^ incomingCallDialogDismissedCallback)
{
std::lock_guard<std::recursive_mutex> lock(g_apiLock);
{
std::lock_guard<std::recursive_mutex> lock(g_apiLock);
VoipPhoneCall^ incomingCall = nullptr;
try
{
......@@ -42,37 +42,37 @@ bool CallController::OnIncomingCallReceived(Platform::String^ contactName, Platf
incomingCall->AnswerRequested += this->acceptCallRequestedHandler;
incomingCall->RejectRequested += this->rejectCallRequestedHandler;
return true;
}
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),
}
CallController::CallController() :
callInProgressPageUri(L"/Views/InCall.xaml"),
voipServiceName(nullptr),
defaultContactImageUri(nullptr),
linphoneImageUri(nullptr),
ringtoneUri(nullptr)
{
this->callCoordinator = VoipCallCoordinator::GetDefault();
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->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()
{
}
this->rejectCallRequestedHandler = ref new TypedEventHandler<VoipPhoneCall^, CallRejectEventArgs^>(this, &CallController::OnRejectCallRequested);
}
CallController::~CallController()
{
}
#pragma once
#include <windows.phone.networking.voip.h>
#include "ApiLock.h"
namespace Linphone
{
namespace BackEnd
{
// Forward declaration
#pragma once
#include <windows.phone.networking.voip.h>
#include "ApiLock.h"
namespace Linphone
{
namespace BackEnd
{
// Forward declaration
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:
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
private:
// Only the server can create an instance of this object
friend ref class Linphone::BackEnd::Globals;
Platform::String^ voipServiceName;
Platform::String^ voipServiceName;
// The relative URI to the call-in-progress page
Platform::String ^callInProgressPageUri;
......@@ -41,21 +41,21 @@ namespace Linphone
Windows::Foundation::Uri^ ringtoneUri;
// The VoIP call coordinator
Windows::Phone::Networking::Voip::VoipCallCoordinator^ callCoordinator;
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();
};
}
}
// Constructor and destructor
CallController();
~CallController();
};
}
}
......@@ -140,10 +140,32 @@ CallController^ Globals::CallController::get()
return this->callController;
}
LinphoneCoreFactory^ Globals::LinphoneCoreFactory::get()
{
if (this->linphoneCoreFactory == nullptr)
{
// Make sure only one API call is in progress at a time
std::lock_guard<std::recursive_mutex> lock(g_apiLock);
if (this->linphoneCoreFactory == nullptr)
{
this->linphoneCoreFactory = ref new Linphone::BackEnd::LinphoneCoreFactory();
}
}
return this->linphoneCoreFactory;
}
LinphoneCore^ Globals::LinphoneCore::get()
{
return this->linphoneCoreFactory->LinphoneCore;
}
Globals::Globals() :
started(false),
serverRegistrationCookie(NULL),
callController(nullptr),
linphoneCoreFactory(nullptr),
noOtherBackgroundProcessEvent(NULL),
backgroundReadyEvent(NULL)
{
......
#pragma once
#include <roapi.h>
#include "LinphoneCoreFactory.h"
namespace Linphone
{
......@@ -8,6 +9,8 @@ namespace Linphone
{
// Forward declarations
ref class CallController;
ref class LinphoneCoreFactory;
ref class LinphoneCore;
// A singleton container that is used to hold other global singletons and background process-wide static state.
// Another purpose of this class is to start the out-of-process WinRT server, so that the UI process
......@@ -39,6 +42,16 @@ namespace Linphone
Linphone::BackEnd::CallController^ get();
}
property Linphone::BackEnd::LinphoneCoreFactory^ LinphoneCoreFactory
{
Linphone::BackEnd::LinphoneCoreFactory^ get();
}
property Linphone::BackEnd::LinphoneCore^ LinphoneCore
{
Linphone::BackEnd::LinphoneCore^ get();
}
private:
// Default constructor
Globals();
......@@ -72,6 +85,8 @@ namespace Linphone
// The call controller object
Linphone::BackEnd::CallController^ callController;
Linphone::BackEnd::LinphoneCoreFactory^ linphoneCoreFactory;
};
}
}
#pragma once
namespace Linphone
{
public ref class LinphoneAuthInfo sealed
{
};
}
\ No newline at end of file
#include "LinphoneCore.h"
using namespace Linphone::BackEnd;
LinphoneCore::LinphoneCore()
{
}
LinphoneCore::~LinphoneCore()
{
}
Platform::String^ LinphoneCore::ToString()
{
return "Hello World!";
}
\ No newline at end of file
#pragma once
//#include "LinphoneProxyConfig.h";
//#include "LinphoneAuthInfo.h";
namespace Linphone
{
namespace BackEnd
{
public ref class LinphoneCore sealed
{
public:
LinphoneCore();
Platform::String^ ToString();
/*void ClearProxyConfigs();
void AddProxyConfig(LinphoneProxyConfig^ proxyCfg);
void SetDefaultProxyConfig(LinphoneProxyConfig^ proxyCfg);
LinphoneProxyConfig^ GetDefaultProxyConfig();
void ClearAuthInfos();
void AddAuthInfo(LinphoneAuthInfo^ info);*/
private:
~LinphoneCore();
};
}
}
\ No newline at end of file
#include "LinphoneCoreFactory.h"
using namespace Linphone::BackEnd;
void LinphoneCoreFactory::CreateLinphoneCore()
{
this->linphoneCore = ref new Linphone::BackEnd::LinphoneCore();
}
LinphoneCore^ LinphoneCoreFactory::LinphoneCore::get()
{
return this->linphoneCore;
}
LinphoneCoreFactory::LinphoneCoreFactory() :
linphoneCore(nullptr)
{
}
LinphoneCoreFactory::~LinphoneCoreFactory()
{
}
\ No newline at end of file
#pragma once
#include "LinphoneCore.h";
namespace Linphone
{
namespace BackEnd
{
ref class LinphoneCore;
public ref class LinphoneCoreFactory sealed
{
public:
property Linphone::BackEnd::LinphoneCore^ LinphoneCore
{
Linphone::BackEnd::LinphoneCore^ get();
}
LinphoneCoreFactory();
void CreateLinphoneCore();
private:
Linphone::BackEnd::LinphoneCore^ linphoneCore;
~LinphoneCoreFactory();
};
}
}
\ No newline at end of file
#pragma once
namespace Linphone
{
public ref class LinphoneProxyConfig sealed
{
};
}
\ No newline at end of file
......@@ -13,17 +13,14 @@ namespace Linphone
public ref class Server sealed
{
public:
// Constructor
Server()
{
}
// Destructor
virtual ~Server()
{
}
// Called by the UI process to get the call controller object
property CallController^ CallController
{
Linphone::BackEnd::CallController^ get()
......@@ -32,7 +29,21 @@ namespace Linphone
};
}
// Add methods and properties to get other objects here, as required.
property LinphoneCoreFactory^ LinphoneCoreFactory
{
Linphone::BackEnd::LinphoneCoreFactory^ get()
{
return Globals::Instance->LinphoneCoreFactory;
};
}
property LinphoneCore^ LinphoneCore
{
Linphone::BackEnd::LinphoneCore^ get()
{
return Globals::Instance->LinphoneCore;
};
}
};
}
}
......
No preview for this file type
......@@ -8,6 +8,14 @@
<CurrentDeployCmdId>256</CurrentDeployCmdId>
<CurrentDeployID>30F105C9-681E-420b-A277-7C086EAD8A4E</CurrentDeployID>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<CurrentDeployCmdId>256</CurrentDeployCmdId>
<CurrentDeployID>30F105C9-681E-420b-A277-7C086EAD8A4E</CurrentDeployID>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<CurrentDeployCmdId>256</CurrentDeployCmdId>
<CurrentDeployID>30F105C9-681E-420b-A277-7C086EAD8A4E</CurrentDeployID>
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{C089C8C0-30E0-4E22-80C0-CE093F111A43}">
......
......@@ -43,7 +43,7 @@ namespace Linphone.Model
private static readonly TimeSpan indefiniteWait = new TimeSpan(0, 0, 0, 0, -1);
/// <summary>
/// Starts and connects the LinphoneManager to the background process (linphonecore)
/// Starts and connects the UI to the background process
/// </summary>
public void ConnectBackgroundProcessToInterface()
{
......@@ -84,14 +84,14 @@ namespace Linphone.Model
// and in that case, the following statement would fail - so, at this point, we don't explicitly guard against this condition.
// Create an instance of the server in the background process.
this.server = (Server)WindowsRuntimeMarshal.GetActivationFactory(typeof(Server)).ActivateInstance();
server = (Server)WindowsRuntimeMarshal.GetActivationFactory(typeof(Server)).ActivateInstance();
// Un-set an event that indicates that the UI process is disconnected from the background process.
// The VoIP background process waits for this event to get set before shutting down.
// This ensures that the VoIP background agent host process doesn't shut down while the UI process is connected to it.
string uiDisconnectedEventName = Globals.GetUiDisconnectedEventName((uint)backgroundProcessID);
this.uiDisconnectedEvent = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset, name: uiDisconnectedEventName);
this.uiDisconnectedEvent.Reset();
uiDisconnectedEvent = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset, name: uiDisconnectedEventName);
uiDisconnectedEvent.Reset();
// The UI process is now connected to the background process
BackgroundProcessConnected = true;
......@@ -99,7 +99,7 @@ namespace Linphone.Model
}
/// <summary>
/// disconnects the LinphoneManager from the background process (linphonecore)
/// Disconnects the UI from the background process
/// </summary>
public void DisconnectBackgroundProcessFromInterface()
{
......@@ -114,15 +114,15 @@ namespace Linphone.Model
// From this point onwards, it is no longer safe to use any objects in the VoIP background process,
// or for the VoIP background process to call back into this process.
this.server = null;
server = null;
// Lastly, set the event that indicates that the UI is no longer connected to the background process.
if (this.uiDisconnectedEvent == null)
if (uiDisconnectedEvent == null)
throw new InvalidOperationException("The ConnectUi method must be called before this method is called");
this.uiDisconnectedEvent.Set();
this.uiDisconnectedEvent.Dispose();
this.uiDisconnectedEvent = null;
uiDisconnectedEvent.Set();
uiDisconnectedEvent.Dispose();
uiDisconnectedEvent = null;
}
/// <summary>
......@@ -189,8 +189,7 @@ namespace Linphone.Model
/// <param name="sipAddress">SIP address to call</param>
public void NewOutgoingCall(String sipAddress)
{
//TileManager tileManager = TileManager.Instance;
//tileManager.UpdateTileWithMissedCalls(new Random().Next(10));
}
/// <summary>
......
......@@ -47,7 +47,10 @@
<ActivatableClasses>
<InProcessServer>
<Path>Linphone.BackEnd.DLL</Path>
<ActivatableClass ActivatableClassId="Linphone.BackEnd.IncomingCallDialogDismissedCallback" ThreadingModel="MTA" />
<ActivatableClass ActivatableClassId="Linphone.BackEnd.CallController" ThreadingModel="MTA" />
<ActivatableClass ActivatableClassId="Linphone.BackEnd.LinphoneCore" ThreadingModel="MTA" />
<ActivatableClass ActivatableClassId="Linphone.BackEnd.LinphoneCoreFactory" ThreadingModel="MTA" />
<ActivatableClass ActivatableClassId="Linphone.BackEnd.Globals" ThreadingModel="MTA" />
</InProcessServer>
<OutOfProcessServer ServerName="Linphone.BackEnd">
......@@ -58,6 +61,8 @@
<ProxyStub ClassId="{C140594A-6BD4-3151-944E-28C955632D15}">
<Path>Linphone.BackEndProxyStub.DLL</Path>
<Interface Name="Linphone.BackEnd.__ICallControllerPublicNonVirtuals" InterfaceId="{C140594A-6BD4-3151-944E-28C955632D15}" />
<Interface Name="Linphone.BackEnd.__ILinphoneCorePublicNonVirtuals" InterfaceId="{AD1665A5-4674-381B-8F09-A529144A2E95}" />
<Interface Name="Linphone.BackEnd.__ILinphoneCoreFactoryPublicNonVirtuals" InterfaceId="{3597B0A3-1ABD-3226-88B2-7E1A95D0182D}" />
<Interface Name="Linphone.BackEnd.__IGlobalsPublicNonVirtuals" InterfaceId="{74C65E76-06C7-38A6-9E0A-61E3739B7E1E}" />
<Interface Name="Linphone.BackEnd.__IGlobalsStatics" InterfaceId="{CE34112C-C406-3477-BBB4-7E1F99EE776C}" />
<Interface Name="Linphone.BackEnd.OutOfProcess.__IServerPublicNonVirtuals" InterfaceId="{EBDEF036-447F-3D47-B33F-715068ACD4CC}" />
......
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