wrapper_impl.mustache 21.15 KiB
/*
LinphoneWrapper.cs
Copyright (C) 2017 Belledonne Communications SARL
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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
#if __IOS__
using ObjCRuntime;
#endif
namespace Linphone
#region Wrapper specifics
	/// <summary>
	/// Only contains the LIB_NAME value that represents the library in which all DllImport are made
	/// </summary>
	public class LinphoneWrapper
		public const string VERSION = "{{version}}";
#if __IOS__
		public const string LIB_NAME = "linphone.framework/linphone";
#elif WINDOWS_UWP
		public const string LIB_NAME = "liblinphone"; // With this, it automatically finds liblinphone.dll
#else
		public const string LIB_NAME = "linphone"; // With this, it automatically finds liblinphone.so
#endif
#if WINDOWS_UWP
		public const string BELLE_SIP_LIB_NAME = "bellesip";
		public const string BCTOOLBOX_LIB_NAME = "bctoolbox";
#else
		public const string BELLE_SIP_LIB_NAME = LIB_NAME;
		public const string BCTOOLBOX_LIB_NAME = LIB_NAME;
#endif
/// https://docs.microsoft.com/fr-fr/xamarin/cross-platform/app-fundamentals/building-cross-platform-applications/platform-divergence-abstraction-divergent-implementation#android
#if __ANDROID__
		[DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
		static extern void setAndroidLogHandler();
#endif
#if __IOS__
		[DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
		static extern void linphone_iphone_enable_logs();
#endif
		/// <summary>
		/// Registers the native log handler in Linphone.
		/// </summary>
		public static void setNativeLogHandler()
#if __ANDROID__
			setAndroidLogHandler();
#elif __IOS__
			linphone_iphone_enable_logs();
#endif
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
} } /// <summary> /// All methods that returns a LinphoneStatus with a value != 0 as an error code in C are translated in C# by throwing a LinphoneException /// </summary> #if WINDOWS_UWP public class LinphoneException : System.Exception { public LinphoneException() : base() { } public LinphoneException(string message) : base(message) { } public LinphoneException(string message, System.Exception inner) : base(message, inner) { } } #else [Serializable()] public class LinphoneException : System.Exception { public LinphoneException() : base() { } public LinphoneException(string message) : base(message) { } public LinphoneException(string message, System.Exception inner) : base(message, inner) { } protected LinphoneException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } #endif [StructLayout(LayoutKind.Sequential)] /// <summary> /// Parent class for a Linphone public objects /// </summary> public class LinphoneObject { internal IntPtr nativePtr; internal GCHandle handle; internal List<IntPtr> string_ptr_list; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void OnLinphoneObjectDataDestroyed(IntPtr data); [DllImport(LinphoneWrapper.BELLE_SIP_LIB_NAME, CallingConvention = CallingConvention.Cdecl)] #if WINDOWS_UWP static extern int belle_sip_object_data_set(IntPtr ptr, string name, IntPtr data, IntPtr cb); #else static extern int belle_sip_object_data_set(IntPtr ptr, string name, IntPtr data, OnLinphoneObjectDataDestroyed cb); #endif [DllImport(LinphoneWrapper.BELLE_SIP_LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr belle_sip_object_data_get(IntPtr ptr, string name); [DllImport(LinphoneWrapper.BELLE_SIP_LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr belle_sip_object_ref(IntPtr ptr); [DllImport(LinphoneWrapper.BELLE_SIP_LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern void belle_sip_object_unref(IntPtr ptr); [DllImport(LinphoneWrapper.BELLE_SIP_LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern void belle_sip_object_data_remove(IntPtr ptr, string name); [DllImport(LinphoneWrapper.BCTOOLBOX_LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr bctbx_list_next(IntPtr ptr); [DllImport(LinphoneWrapper.BCTOOLBOX_LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr bctbx_list_get_data(IntPtr ptr); [DllImport(LinphoneWrapper.BCTOOLBOX_LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr bctbx_list_append(IntPtr elem, IntPtr data); ~LinphoneObject() { //Console.WriteLine("Destroying " + this.ToString());
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
if (nativePtr != IntPtr.Zero) { //Console.WriteLine("Unreffing " + this.ToString()); belle_sip_object_data_remove(nativePtr, "cs_obj"); belle_sip_object_unref(nativePtr); handle.Free(); } } internal static T fromNativePtr<T>(IntPtr ptr, bool takeRef=true) where T : LinphoneObject, new() { if (ptr == IntPtr.Zero) return null; IntPtr objPtr = belle_sip_object_data_get(ptr, "cs_obj"); if (objPtr != IntPtr.Zero) { T obj = null; GCHandle handle = GCHandle.FromIntPtr(objPtr); if (handle.IsAllocated) { obj = (T)handle.Target; } if (obj == null) { //Console.WriteLine("Handle target is null " + handle.Target); objPtr = IntPtr.Zero; } else { //Console.WriteLine("Using existing " + obj.ToString()); return obj; } } if (objPtr == IntPtr.Zero) { T obj = new T(); //Console.WriteLine("Creating " + obj.ToString()); if (takeRef) { ptr = belle_sip_object_ref(ptr); //Console.WriteLine("Reffing " + obj.ToString()); } obj.nativePtr = ptr; obj.handle = GCHandle.Alloc(obj, GCHandleType.WeakTrackResurrection); objPtr = GCHandle.ToIntPtr(obj.handle); #if WINDOWS_UWP belle_sip_object_data_set(ptr, "cs_obj", objPtr, IntPtr.Zero); #else belle_sip_object_data_set(ptr, "cs_obj", objPtr, null); #endif return obj; } return null; } internal static IEnumerable<string> MarshalStringArray(IntPtr listPtr) { if (listPtr != IntPtr.Zero) { IntPtr ptr = listPtr; while (ptr != IntPtr.Zero) { IntPtr dataPtr = bctbx_list_get_data(ptr); if (dataPtr == IntPtr.Zero) { break; } string key = Marshal.PtrToStringAnsi(dataPtr); yield return key; ptr = bctbx_list_next(ptr); }
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
} } internal static IEnumerable<T> MarshalBctbxList<T>(IntPtr listPtr) where T : LinphoneObject, new() { if (listPtr != IntPtr.Zero) { IntPtr ptr = listPtr; while (ptr != IntPtr.Zero) { IntPtr dataPtr = bctbx_list_get_data(ptr); if (dataPtr == IntPtr.Zero) { break; } T obj = fromNativePtr<T>(dataPtr); yield return obj; ptr = bctbx_list_next(ptr); } } } internal protected IntPtr StringArrayToBctbxList(IEnumerable<string> stringlist) { IntPtr bctbx_list = IntPtr.Zero; string_ptr_list = new List<IntPtr>(); foreach (string s in stringlist) { IntPtr string_ptr = Marshal.StringToHGlobalAnsi(s); bctbx_list = bctbx_list_append(bctbx_list, string_ptr); string_ptr_list.Add(string_ptr); } return bctbx_list; } internal protected void CleanStringArrayPtrs() { foreach (IntPtr string_ptr in string_ptr_list) { Marshal.FreeHGlobal(string_ptr); } } internal static IntPtr ObjectArrayToBctbxList<T>(IEnumerable<T> objlist) where T : LinphoneObject, new() { IntPtr bctbx_list = IntPtr.Zero; foreach (T ptr in objlist) { bctbx_list = bctbx_list_append(bctbx_list, ptr.nativePtr); } return bctbx_list; } } public class MediastreamerFactory { public IntPtr nativePtr; [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern int ms_factory_enable_filter_from_name(IntPtr nativePtr, string name, char enabled); public void enableFilterFromName(string name, bool enabled) { ms_factory_enable_filter_from_name(nativePtr, name, enabled ? (char)1 : (char)0); } [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern void ms_devices_info_add(IntPtr devices_info, string manufacturer, string model, string platform, uint flags, int delay, int recommended_rate); [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
static extern IntPtr ms_factory_get_devices_info(IntPtr factory); public void addDevicesInfo(string manufacturer, string model, string platform, uint flags, int delay, int recommended_rate) { ms_devices_info_add(ms_factory_get_devices_info(nativePtr), manufacturer, model, platform, flags, delay, recommended_rate); } } #endregion #region Enums {{#enums}} {{#enum}} {{#doc}} {{#lines}} /// {{{line}}} {{/lines}} {{/doc}}{{#isFlag}}[Flags]{{/isFlag}} public enum {{enumName}} { {{#values}} {{#doc}} {{#lines}} /// {{{line}}} {{/lines}} {{/doc}} {{name}} = {{{value}}}, {{/values}} } {{/enum}} {{/enums}} #endregion #region Listeners {{#interfaces}} {{#interface}} [StructLayout(LayoutKind.Sequential)] public class {{interfaceName}} : LinphoneObject { ~{{interfaceName}}() { unregister(); } [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern void {{set_user_data_name}}(IntPtr thiz, IntPtr listener); [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr {{get_user_data_name}}(IntPtr thiz); {{#methods}} [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] {{#cb_setter}} #if WINDOWS_UWP static extern void {{name}}(IntPtr thiz, IntPtr cb); #else static extern void {{name}}(IntPtr thiz, {{name_private}} cb); #endif {{/cb_setter}} {{#delegate}} [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void {{name_private}}({{params_private}}); public delegate void {{name_public}}({{{params_public}}}); private {{name_private}} {{var_private}}; private {{name_public}} {{var_public}}; #if __IOS__ [MonoPInvokeCallback(typeof({{name_private}}))]
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
#endif private static void {{cb_name}}({{params_private}}) { {{interfaceClassName}} thiz = fromNativePtr<{{interfaceClassName}}>({{first_param}}); {{interfaceName}} current_listener = thiz.CurrentCallbacks; if (current_listener != null) { current_listener.{{var_public}}?.Invoke({{{params}}}); } } public {{name_public}} {{name}} { get { return {{var_public}}; } set { {{var_public}} = value; #if WINDOWS_UWP {{var_private}} = {{cb_name}}; IntPtr cb = Marshal.GetFunctionPointerForDelegate({{var_private}}); {{c_name_setter}}(nativePtr, cb); #else {{c_name_setter}}(nativePtr, {{cb_name}}); #endif } } {{/delegate}} {{/methods}} internal void register() { IntPtr listener = {{get_user_data_name}}(nativePtr); if (listener == IntPtr.Zero) { GCHandle _handle = GCHandle.Alloc(this, GCHandleType.Normal); listener = GCHandle.ToIntPtr(_handle); } else { GCHandle _handle = GCHandle.FromIntPtr(listener); if (_handle.Target == this) { return; } else { _handle.Free(); _handle = GCHandle.Alloc(this, GCHandleType.Normal); listener = GCHandle.ToIntPtr(_handle); } } {{set_user_data_name}}(nativePtr, listener); } internal void unregister() { IntPtr listener = {{get_user_data_name}}(nativePtr); {{set_user_data_name}}(nativePtr, IntPtr.Zero); if (listener != IntPtr.Zero) { GCHandle.FromIntPtr(listener).Free(); } } } {{/interface}} {{/interfaces}} #endregion #region Classes {{#classes}}
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
{{#_class}} {{#doc}} {{#lines}} /// {{{line}}} {{/lines}} {{/doc}} [StructLayout(LayoutKind.Sequential)] public class {{className}} : LinphoneObject { {{#isLinphoneFactory}} #if __ANDROID__ static Factory() { Java.Lang.JavaSystem.LoadLibrary("c++_shared"); Java.Lang.JavaSystem.LoadLibrary("bctoolbox"); Java.Lang.JavaSystem.LoadLibrary("ortp"); Java.Lang.JavaSystem.LoadLibrary("mediastreamer"); Java.Lang.JavaSystem.LoadLibrary("linphone"); } #endif {{/isLinphoneFactory}} {{#isLinphoneCall}} /// Get the native window handle of the video window, casted as an unsigned long. public string NativeVideoWindowIdString { get { return Marshal.PtrToStringUni(linphone_call_get_native_video_window_id(nativePtr)); } set { IntPtr string_ptr_to_remove = linphone_call_get_native_video_window_id(nativePtr); IntPtr string_ptr = Marshal.StringToHGlobalUni(value); linphone_call_set_native_video_window_id(nativePtr, string_ptr); if(string_ptr_to_remove != IntPtr.Zero) Marshal.FreeHGlobal(string_ptr_to_remove); } } {{/isLinphoneCall}} {{#isLinphoneCore}} [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr linphone_core_get_ms_factory(IntPtr thiz); public MediastreamerFactory MsFactory { get { IntPtr ptr = linphone_core_get_ms_factory(nativePtr); MediastreamerFactory factory = new MediastreamerFactory(); factory.nativePtr = ptr; return factory; } } /// Get the native window handle of the video window. public string NativeVideoWindowIdString { get { return Marshal.PtrToStringUni(linphone_core_get_native_video_window_id(nativePtr)); } set { IntPtr string_ptr_to_remove = linphone_core_get_native_video_window_id(nativePtr); if(string_ptr_to_remove != IntPtr.Zero) Marshal.FreeHGlobal(string_ptr_to_remove); IntPtr string_ptr = Marshal.StringToHGlobalUni(value); linphone_core_set_native_video_window_id(nativePtr, string_ptr); } }
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
/// Get the native window handle of the video preview window. public string NativePreviewWindowIdString { get { return Marshal.PtrToStringUni(linphone_core_get_native_preview_window_id(nativePtr)); } set { IntPtr string_ptr_to_remove = linphone_core_get_native_preview_window_id(nativePtr); if(string_ptr_to_remove != IntPtr.Zero) Marshal.FreeHGlobal(string_ptr_to_remove); IntPtr string_ptr = Marshal.StringToHGlobalUni(value); linphone_core_set_native_preview_window_id(nativePtr, string_ptr); } } {{/isLinphoneCore}} {{#listener}} [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr linphone_factory_create_{{listener_constructor}}_cbs(IntPtr factory); [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr linphone_{{listener_constructor}}_add_callbacks(IntPtr thiz, IntPtr cbs); [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr linphone_{{listener_constructor}}_remove_callbacks(IntPtr thiz, IntPtr cbs); ~{{className}}() { if (listener != null) { linphone_{{listener_constructor}}_remove_callbacks(nativePtr, listener.nativePtr); } } private {{interfaceName}} listener; public {{interfaceName}} Listener { get { if (listener == null) { IntPtr nativeListener = linphone_factory_create_{{listener_constructor}}_cbs(IntPtr.Zero); listener = fromNativePtr<{{interfaceName}}>(nativeListener, false); linphone_{{listener_constructor}}_add_callbacks(nativePtr, nativeListener); listener.register(); } return listener; } } {{/listener}} {{#dllImports}} [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] {{{prototype}}} {{#has_second_prototype}} [DllImport(LinphoneWrapper.LIB_NAME, CallingConvention = CallingConvention.Cdecl)] {{second_prototype}} {{/has_second_prototype}} {{#has_property}} {{#doc}} {{#lines}} /// {{{line}}} {{/lines}} {{/doc}} {{property_static}}public {{{property_return}}} {{property_name}} {
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
{{#has_getter}} get { {{#is_string}} IntPtr stringPtr = {{getter_c_name}}({{getter_nativePtr}}); return Marshal.PtrToStringAnsi(stringPtr); {{/is_string}} {{#is_bool}} return {{getter_c_name}}({{getter_nativePtr}}) != 0; {{/is_bool}} {{#is_class}} IntPtr ptr = {{getter_c_name}}({{getter_nativePtr}}); {{{property_return}}} obj = fromNativePtr<{{return}}>(ptr, {{takeRef}}); return obj; {{/is_class}} {{#is_enum}} return {{getter_c_name}}({{getter_nativePtr}}); {{/is_enum}} {{#is_generic}} return {{getter_c_name}}({{getter_nativePtr}}); {{/is_generic}} {{#is_string_list}} return MarshalStringArray({{getter_c_name}}({{getter_nativePtr}})); {{/is_string_list}} {{#is_class_list}} return MarshalBctbxList<{{{list_type}}}>({{getter_c_name}}({{getter_nativePtr}})); {{/is_class_list}} } {{/has_getter}} {{#has_setter}} set { {{#is_string}} {{#exception}}int exception_result = {{/exception}}{{setter_c_name}}({{setter_nativePtr}}value); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{property_name}} setter returned value " + exception_result);{{/exception}} {{/is_string}} {{#is_bool}} {{#exception}}int exception_result = {{/exception}}{{setter_c_name}}({{setter_nativePtr}}value ? (char)1 : (char)0); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{property_name}} setter returned value " + exception_result);{{/exception}} {{/is_bool}} {{#is_class}} {{#exception}}int exception_result = {{/exception}}{{setter_c_name}}({{setter_nativePtr}}value.nativePtr); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{property_name}} setter returned value " + exception_result);{{/exception}} {{/is_class}} {{#is_enum}} {{#exception}}int exception_result = {{/exception}}{{setter_c_name}}({{setter_nativePtr}}(int)value); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{property_name}} setter returned value " + exception_result);{{/exception}} {{/is_enum}} {{#is_generic}} {{#exception}}int exception_result = {{/exception}}{{setter_c_name}}({{setter_nativePtr}}value); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{property_name}} setter returned value " + exception_result);{{/exception}} {{/is_generic}} {{#is_string_list}} {{#exception}}int exception_result = {{/exception}}{{setter_c_name}}({{setter_nativePtr}}StringArrayToBctbxList(value)); CleanStringArrayPtrs(); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{property_name}} setter returned value " + exception_result);{{/exception}} {{/is_string_list}} {{#is_class_list}} {{#exception}}int exception_result = {{/exception}}{{setter_c_name}}({{setter_nativePtr}}ObjectArrayToBctbxList<{{{list_type}}}>(value)); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{property_name}} setter returned value " + exception_result);{{/exception}} {{/is_class_list}} } {{/has_setter}} } {{/has_property}} {{#has_impl}} {{#impl}} {{#doc}} {{#lines}} /// {{{line}}}
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
{{/lines}} {{/doc}} public {{static}}{{override}}{{{type}}} {{name}}({{{args}}}) { {{#is_string}} IntPtr stringPtr = {{c_name}}({{nativePtr}}{{{c_args}}}); string returnVal = Marshal.PtrToStringAnsi(stringPtr); {{/is_string}} {{#is_bool}} {{#hasReturn}}bool returnVal = {{/hasReturn}}{{c_name}}({{nativePtr}}{{{c_args}}}) == (char)0 ? false : true; {{/is_bool}} {{#is_class}} IntPtr ptr = {{c_name}}({{nativePtr}}{{{c_args}}}); {{type}} returnVal = fromNativePtr<{{type}}>(ptr, {{takeRef}}); {{/is_class}} {{#is_enum}} {{#exception}}int exception_result = {{/exception}}{{#hasReturn}}{{{type}}} returnVal = {{/hasReturn}}{{c_name}}({{nativePtr}}{{{c_args}}}); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{name}} returned value " + exception_result);{{/exception}} {{/is_enum}} {{#is_generic}} {{#exception}}int exception_result = {{/exception}}{{#hasReturn}}{{{type}}} returnVal = {{/hasReturn}}{{c_name}}({{nativePtr}}{{{c_args}}}); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{name}} returned value" + exception_result);{{/exception}} {{/is_generic}} {{#is_string_list}} IEnumerable<string> returnVal = MarshalStringArray({{c_name}}({{nativePtr}}{{{c_args}}})); {{/is_string_list}} {{#is_class_list}} IEnumerable<{{{list_type}}}> returnVal = MarshalBctbxList<{{{list_type}}}>({{c_name}}({{nativePtr}}{{{c_args}}})); {{/is_class_list}} {{#clean_string_list_ptrs}}CleanStringArrayPtrs();{{/clean_string_list_ptrs}} {{#hasReturn}}return returnVal;{{/hasReturn}} } {{/impl}} {{/has_impl}} {{/dllImports}} } {{/_class}} {{/classes}} #endregion }