| This directory contains an example Unity native plugin for Windows OS. |
| The APIs use Platform Invoke (P/Invoke) technology as required by Unity native plugin. |
| This plugin dll can also be used by Windows C# applications other than Unity. |
| |
| An example of wrapping native plugin into a C# managed class in Unity is given as following: |
| |
| using System; |
| using System.Runtime.InteropServices; |
| |
| namespace SimplePeerConnectionM { |
| // This is a managed wrap up class for the native c style peer connection APIs. |
| public class PeerConnectionM { |
| //private const string dll_path = "SimplePeerConnection"; |
| private const string dll_path = "webrtc_unity_plugin"; |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern int CreatePeerConnection(); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool ClosePeerConnection(int peer_connection_id); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool AddStream(int peer_connection_id, bool audio_only); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool AddDataChannel(int peer_connection_id); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool CreateOffer(int peer_connection_id); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool CreateAnswer(int peer_connection_id); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool SendDataViaDataChannel(int peer_connection_id, string data); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool SetAudioControl(int peer_connection_id, bool is_mute, bool is_record); |
| |
| [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
| private delegate void LocalDataChannelReadyInternalDelegate(); |
| public delegate void LocalDataChannelReadyDelegate(int id); |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool RegisterOnLocalDataChannelReady(int peer_connection_id, LocalDataChannelReadyInternalDelegate callback); |
| |
| [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
| private delegate void DataFromDataChannelReadyInternalDelegate(string s); |
| public delegate void DataFromDataChannelReadyDelegate(int id, string s); |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool RegisterOnDataFromDataChannelReady(int peer_connection_id, DataFromDataChannelReadyInternalDelegate callback); |
| |
| [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
| private delegate void FailureMessageInternalDelegate(string msg); |
| public delegate void FailureMessageDelegate(int id, string msg); |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool RegisterOnFailure(int peer_connection_id, FailureMessageInternalDelegate callback); |
| |
| [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
| private delegate void AudioBusReadyInternalDelegate(IntPtr data, int bits_per_sample, |
| int sample_rate, int number_of_channels, int number_of_frames); |
| public delegate void AudioBusReadyDelegate(int id, IntPtr data, int bits_per_sample, |
| int sample_rate, int number_of_channels, int number_of_frames); |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool RegisterOnAudioBusReady(int peer_connection_id, AudioBusReadyInternalDelegate callback); |
| |
| [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
| private delegate void LocalSdpReadytoSendInternalDelegate(string s); |
| public delegate void LocalSdpReadytoSendDelegate(int id, string s); |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool RegisterOnLocalSdpReadytoSend(int peer_connection_id, LocalSdpReadytoSendInternalDelegate callback); |
| |
| [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
| private delegate void IceCandiateReadytoSendInternalDelegate(string s); |
| public delegate void IceCandiateReadytoSendDelegate(int id, string s); |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool RegisterOnIceCandiateReadytoSend(int peer_connection_id, IceCandiateReadytoSendInternalDelegate callback); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern int ReceivedSdp(int peer_connection_id, string sdp); |
| |
| [DllImport(dll_path, CallingConvention = CallingConvention.Cdecl)] |
| private static extern bool ReceivedIceCandidate(int peer_connection_id, string ice_candidate); |
| |
| public void CreatePeerConnectionM() { |
| peer_connection_id_ = CreatePeerConnection(); |
| RegisterCallbacks(); |
| } |
| |
| private void RegisterCallbacks() { |
| localDataChannelReadyDelegate_ = new LocalDataChannelReadyInternalDelegate(RaiseLocalDataChannelReady); |
| RegisterOnLocalDataChannelReady(peer_connection_id_, localDataChannelReadyDelegate_); |
| |
| dataFromDataChannelReadyDelegate_ = new DataFromDataChannelReadyInternalDelegate(RaiseDataFromDataChannelReady); |
| RegisterOnDataFromDataChannelReady(peer_connection_id_, dataFromDataChannelReadyDelegate_); |
| |
| failureMessageDelegate_ = new FailureMessageInternalDelegate(RaiseFailureMessage); |
| RegisterOnFailure(peer_connection_id_, failureMessageDelegate_); |
| |
| audioBusReadyDelegate_ = new AudioBusReadyInternalDelegate(RaiseAudioBusReady); |
| RegisterOnAudioBusReady(peer_connection_id_, audioBusReadyDelegate_); |
| |
| localSdpReadytoSendDelegate_ = new LocalSdpReadytoSendInternalDelegate(RaiseLocalSdpReadytoSend); |
| RegisterOnLocalSdpReadytoSend(peer_connection_id_, localSdpReadytoSendDelegate_); |
| |
| iceCandiateReadytoSendDelegate_ = new IceCandiateReadytoSendInternalDelegate(RaiseIceCandiateReadytoSend); |
| RegisterOnIceCandiateReadytoSend(peer_connection_id_, iceCandiateReadytoSendDelegate_); |
| } |
| |
| public void ClosePeerConnectionM() { |
| ClosePeerConnection(peer_connection_id_); |
| peer_connection_id_ = -1; |
| } |
| |
| // Return -1 if Peerconnection is not available. |
| public int GetUniqueId() { |
| return peer_connection_id_; |
| } |
| |
| public void AddStreamM(bool audio_only) { |
| AddStream(peer_connection_id_, audio_only); |
| } |
| |
| public void AddDataChannelM() { |
| AddDataChannel(peer_connection_id_); |
| } |
| |
| public void CreateOfferM() { |
| CreateOffer(peer_connection_id_); |
| } |
| |
| public void CreateAnswerM() { |
| CreateAnswer(peer_connection_id_); |
| } |
| |
| public void SendDataViaDataChannelM(string data) { |
| SendDataViaDataChannel(peer_connection_id_, data); |
| } |
| |
| public void SetAudioControl(bool is_mute, bool is_record) { |
| SetAudioControl(peer_connection_id_, is_mute, is_record); |
| } |
| |
| public void ReceivedSdpM(string sdp) { |
| peer_connection_id_ = ReceivedSdp(peer_connection_id_, sdp); |
| RegisterCallbacks(); |
| } |
| |
| public void ReceivedIceCandidateM(string ice_candidate) { |
| ReceivedIceCandidate(peer_connection_id_, ice_candidate); |
| } |
| |
| private void RaiseLocalDataChannelReady() { |
| if (OnLocalDataChannelReady != null) |
| OnLocalDataChannelReady(peer_connection_id_); |
| } |
| |
| private void RaiseDataFromDataChannelReady(string data) { |
| if (OnDataFromDataChannelReady != null) |
| OnDataFromDataChannelReady(peer_connection_id_, data); |
| } |
| |
| private void RaiseFailureMessage(string msg) { |
| if (OnFailureMessage != null) |
| OnFailureMessage(peer_connection_id_, msg); |
| } |
| |
| private void RaiseAudioBusReady(IntPtr data, int bits_per_sample, |
| int sample_rate, int number_of_channels, int number_of_frames) { |
| if (OnAudioBusReady != null) |
| OnAudioBusReady(peer_connection_id_, data, bits_per_sample, sample_rate, |
| number_of_channels, number_of_frames); |
| } |
| |
| private void RaiseLocalSdpReadytoSend(string msg) { |
| if (OnLocalSdpReadytoSend != null) |
| OnLocalSdpReadytoSend(peer_connection_id_, msg); |
| } |
| |
| private void RaiseIceCandiateReadytoSend(string msg) { |
| if (OnIceCandiateReadytoSend != null) |
| OnIceCandiateReadytoSend(peer_connection_id_, msg); |
| } |
| |
| private LocalDataChannelReadyInternalDelegate localDataChannelReadyDelegate_ = null; |
| public event LocalDataChannelReadyDelegate OnLocalDataChannelReady; |
| |
| private DataFromDataChannelReadyInternalDelegate dataFromDataChannelReadyDelegate_ = null; |
| public event DataFromDataChannelReadyDelegate OnDataFromDataChannelReady; |
| |
| private FailureMessageInternalDelegate failureMessageDelegate_ = null; |
| public event FailureMessageDelegate OnFailureMessage; |
| |
| private AudioBusReadyInternalDelegate audioBusReadyDelegate_ = null; |
| public event AudioBusReadyDelegate OnAudioBusReady; |
| |
| private LocalSdpReadytoSendInternalDelegate localSdpReadytoSendDelegate_ = null; |
| public event LocalSdpReadytoSendDelegate OnLocalSdpReadytoSend; |
| |
| private IceCandiateReadytoSendInternalDelegate iceCandiateReadytoSendDelegate_ = null; |
| public event IceCandiateReadytoSendDelegate OnIceCandiateReadytoSend; |
| |
| private int peer_connection_id_ = -1; |
| } |
| } |