1 /* 2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - mod_managed 3 * Copyright (C) 2008, Michael Giagnocavo <mgg@giagnocavo.net> 4 * 5 * Version: MPL 1.1 6 * 7 * The contents of this file are subject to the Mozilla Public License Version 8 * 1.1 (the "License"); you may not use this file except in compliance with 9 * the License. You may obtain a copy of the License at 10 * http://www.mozilla.org/MPL/ 11 * 12 * Software distributed under the License is distributed on an "AS IS" basis, 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 * for the specific language governing rights and limitations under the 15 * License. 16 * 17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - mod_managed 18 * 19 * The Initial Developer of the Original Code is 20 * Michael Giagnocavo <mgg@giagnocavo.net> 21 * Portions created by the Initial Developer are Copyright (C) 22 * the Initial Developer. All Rights Reserved. 23 * 24 * Contributor(s): 25 * 26 * Michael Giagnocavo <mgg@giagnocavo.net> 27 * 28 * EventBinding.cs - Helpers for switch_event_bind function 29 * 30 */ 31 using System; 32 using System.Collections.Generic; 33 using System.Linq; 34 using System.Text; 35 using System.Runtime.InteropServices; 36 using System.Reflection; 37 using FreeSWITCH.Native; 38 39 namespace FreeSWITCH 40 { 41 public class SwitchEventWrap : switch_event, IDisposable 42 { 43 private bool disposed; 44 private SWIGTYPE_p_p_switch_event p_p_switch_event; 45 private IntPtr native_ptr_ptr; 46 SwitchEventWrap(IntPtr ptrPtr)47 internal SwitchEventWrap(IntPtr ptrPtr) : base((IntPtr)Marshal.PtrToStructure(ptrPtr, typeof(IntPtr)), false) 48 { 49 native_ptr_ptr = ptrPtr; 50 p_p_switch_event = new SWIGTYPE_p_p_switch_event(ptrPtr, false); 51 } 52 ~SwitchEventWrap()53 ~SwitchEventWrap() 54 { 55 dispose(); 56 } 57 Dispose()58 public override void Dispose() 59 { 60 dispose(); 61 GC.SuppressFinalize(this); 62 } 63 dispose()64 internal void dispose() 65 { 66 if (disposed) return; 67 disposed = true; 68 freeswitch.switch_event_destroy(p_p_switch_event); 69 Marshal.FreeCoTaskMem(native_ptr_ptr); 70 } 71 } 72 73 public class EventBinding : IDisposable 74 { 75 76 public class EventBindingArgs : EventArgs 77 { 78 public switch_event EventObj { get; set; } 79 } 80 81 //typedef void (*switch_event_callback_t) (switch_event_t *); 82 83 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] switch_event_callback_delegate(IntPtr event_data)84 delegate void switch_event_callback_delegate(IntPtr event_data); 85 86 readonly switch_event_callback_delegate del; // Prevent GC 87 readonly SWIGTYPE_p_f_p_switch_event__void function; 88 EventBinding(SWIGTYPE_p_f_p_switch_event__void function, switch_event_callback_delegate origDelegate)89 private EventBinding(SWIGTYPE_p_f_p_switch_event__void function, switch_event_callback_delegate origDelegate) 90 { 91 this.function = function; 92 this.del = origDelegate; 93 } 94 bool disposed; Dispose()95 public void Dispose() 96 { 97 dispose(); 98 GC.SuppressFinalize(this); 99 } dispose()100 void dispose() 101 { 102 if (disposed) return; 103 // HACK: FS crashes if we unbind after shutdown is pretty complete. This is still a race condition. 104 if (freeswitch.switch_core_ready() == switch_bool_t.SWITCH_FALSE) return; 105 freeswitch.switch_event_unbind_callback(this.function); 106 disposed = true; 107 } ~EventBinding()108 ~EventBinding() 109 { 110 dispose(); 111 } SwitchEventDupe(switch_event evt)112 public static switch_event SwitchEventDupe(switch_event evt) 113 { 114 IntPtr clone_ptr_ptr = Marshal.AllocCoTaskMem(IntPtr.Size); 115 freeswitch.switch_event_dup(new SWIGTYPE_p_p_switch_event(clone_ptr_ptr, false), evt); 116 SwitchEventWrap dupe_evt = new SwitchEventWrap(clone_ptr_ptr); 117 return dupe_evt; 118 } Bind(string id, switch_event_types_t event_types, string subclass_name, Action<EventBindingArgs> f, bool dupe)119 public static IDisposable Bind(string id, switch_event_types_t event_types, string subclass_name, Action<EventBindingArgs> f, bool dupe) 120 { 121 switch_event_callback_delegate boundFunc; 122 if (dupe) 123 { 124 boundFunc = (eventObj) => 125 { 126 var args = new EventBindingArgs { EventObj = SwitchEventDupe(new switch_event(eventObj,false)) }; 127 f(args); 128 }; 129 } 130 else 131 { 132 boundFunc = (eventObj) => 133 { 134 var args = new EventBindingArgs { EventObj = new switch_event(eventObj, false) }; 135 f(args); 136 }; 137 } 138 var fp = Marshal.GetFunctionPointerForDelegate(boundFunc); 139 var swigFp = new SWIGTYPE_p_f_p_switch_event__void(fp, false); 140 var res = freeswitch.switch_event_bind(id, event_types, subclass_name, swigFp, null); 141 if (res != switch_status_t.SWITCH_STATUS_SUCCESS) 142 { 143 throw new InvalidOperationException("Call to switch_event_bind failed, result: " + res + "."); 144 } 145 return new EventBinding(swigFp, boundFunc); 146 } 147 } 148 }