1 #pragma warning disable CS1591
3 using System.Runtime.InteropServices;
4 using System.Collections.Generic;
6 using System.Threading;
7 using System.ComponentModel;
12 /// <summary>Generic interface for objects that can write data from a provided memory.
13 /// This interface allows external objects to transparently write data to this object and be notified whether more data can be written or if it's reached capacity.
15 /// Calls to <see cref="Efl.Io.IWriter.Write"/> may or may not block: that's not up to this interface to specify. The user can check with event "can_write,changed" or property <see cref="Efl.Io.IWriter.CanWrite"/> to known whenever a write could push more data.
16 /// (Since EFL 1.22)</summary>
17 [Efl.Io.IWriterConcrete.NativeMethods]
18 public interface IWriter :
19 Efl.Eo.IWrapper, IDisposable
21 /// <summary>If <c>true</c> will notify <see cref="Efl.Io.IWriter.Write"/> can be called without blocking or failing.
22 /// (Since EFL 1.22)</summary>
23 /// <returns><c>true</c> if it can be written without blocking or failure, <c>false</c> otherwise</returns>
25 /// <summary>If <c>true</c> will notify <see cref="Efl.Io.IWriter.Write"/> can be called without blocking or failing.
26 /// (Since EFL 1.22)</summary>
27 /// <param name="can_write"><c>true</c> if it can be written without blocking or failure, <c>false</c> otherwise</param>
28 void SetCanWrite(bool can_write);
29 /// <summary>Writes data from a pre-populated buffer.
30 /// This operation will be executed immediately and may or may not block the caller thread for some time. The details of blocking behavior is defined by the implementation and may be subject to other parameters such as non-blocking flags, maximum timeout or even retry attempts.
32 /// You can understand this method as write(2) libc function.
33 /// (Since EFL 1.22)</summary>
34 /// <param name="slice">Provides a pre-populated memory to be used up to slice.len. The returned slice will be adapted as length will be set to the actually used amount of bytes, which can be smaller than the request.</param>
35 /// <param name="remaining">Convenience to output the remaining parts of slice that was not written. If the full slice was written, this will be a slice of zero-length.</param>
36 /// <returns>0 on succeed, a mapping of errno otherwise</returns>
37 Eina.Error Write(ref Eina.Slice slice, ref Eina.Slice remaining);
38 /// <summary>Notifies can_write property changed.
39 /// If <see cref="Efl.Io.IWriter.CanWrite"/> is <c>true</c> there is data to <see cref="Efl.Io.IWriter.Write"/> without blocking/error. If <see cref="Efl.Io.IWriter.CanWrite"/> is <c>false</c>, <see cref="Efl.Io.IWriter.Write"/> would either block or fail.
41 /// Note that usually this event is dispatched from inside <see cref="Efl.Io.IWriter.Write"/>, thus before it returns.
42 /// (Since EFL 1.22)</summary>
43 event EventHandler<Efl.Io.IWriterCanWriteChangedEvt_Args> CanWriteChangedEvt;
44 /// <summary>If <c>true</c> will notify <see cref="Efl.Io.IWriter.Write"/> can be called without blocking or failing.
45 /// (Since EFL 1.22)</summary>
46 /// <value><c>true</c> if it can be written without blocking or failure, <c>false</c> otherwise</value>
52 ///<summary>Event argument wrapper for event <see cref="Efl.Io.IWriter.CanWriteChangedEvt"/>.</summary>
53 public class IWriterCanWriteChangedEvt_Args : EventArgs {
54 ///<summary>Actual event payload.</summary>
55 public bool arg { get; set; }
57 /// <summary>Generic interface for objects that can write data from a provided memory.
58 /// This interface allows external objects to transparently write data to this object and be notified whether more data can be written or if it's reached capacity.
60 /// Calls to <see cref="Efl.Io.IWriter.Write"/> may or may not block: that's not up to this interface to specify. The user can check with event "can_write,changed" or property <see cref="Efl.Io.IWriter.CanWrite"/> to known whenever a write could push more data.
61 /// (Since EFL 1.22)</summary>
62 sealed public class IWriterConcrete :
67 ///<summary>Pointer to the native class description.</summary>
68 public System.IntPtr NativeClass
72 if (((object)this).GetType() == typeof(IWriterConcrete))
74 return GetEflClassStatic();
78 return Efl.Eo.ClassRegister.klassFromType[((object)this).GetType()];
83 private Dictionary<(IntPtr desc, object evtDelegate), (IntPtr evtCallerPtr, Efl.EventCb evtCaller)> eoEvents = new Dictionary<(IntPtr desc, object evtDelegate), (IntPtr evtCallerPtr, Efl.EventCb evtCaller)>();
84 private readonly object eventLock = new object();
85 private System.IntPtr handle;
86 ///<summary>Pointer to the native instance.</summary>
87 public System.IntPtr NativeHandle
89 get { return handle; }
92 [System.Runtime.InteropServices.DllImport(efl.Libs.Efl)] internal static extern System.IntPtr
93 efl_io_writer_interface_get();
94 /// <summary>Initializes a new instance of the <see cref="IWriter"/> class.
95 /// Internal usage: This is used when interacting with C code and should not be used directly.</summary>
96 private IWriterConcrete(System.IntPtr raw)
100 ///<summary>Destructor.</summary>
106 ///<summary>Releases the underlying native instance.</summary>
107 private void Dispose(bool disposing)
109 if (handle != System.IntPtr.Zero)
112 handle = IntPtr.Zero;
114 IntPtr gcHandlePtr = IntPtr.Zero;
115 if (eoEvents.Count != 0)
117 GCHandle gcHandle = GCHandle.Alloc(eoEvents);
118 gcHandlePtr = GCHandle.ToIntPtr(gcHandle);
123 Efl.Eo.Globals.efl_mono_native_dispose(h, gcHandlePtr);
127 Monitor.Enter(Efl.All.InitLock);
128 if (Efl.All.MainLoopInitialized)
130 Efl.Eo.Globals.efl_mono_thread_safe_native_dispose(h, gcHandlePtr);
133 Monitor.Exit(Efl.All.InitLock);
139 ///<summary>Releases the underlying native instance.</summary>
140 public void Dispose()
143 GC.SuppressFinalize(this);
146 /// <summary>Verifies if the given object is equal to this one.</summary>
147 /// <param name="instance">The object to compare to.</param>
148 /// <returns>True if both objects point to the same native object.</returns>
149 public override bool Equals(object instance)
151 var other = instance as Efl.Object;
156 return this.NativeHandle == other.NativeHandle;
159 /// <summary>Gets the hash code for this object based on the native pointer it points to.</summary>
160 /// <returns>The value of the pointer, to be used as the hash code of this object.</returns>
161 public override int GetHashCode()
163 return this.NativeHandle.ToInt32();
166 /// <summary>Turns the native pointer into a string representation.</summary>
167 /// <returns>A string with the type and the native pointer for this object.</returns>
168 public override String ToString()
170 return $"{this.GetType().Name}@[{this.NativeHandle.ToInt32():x}]";
173 ///<summary>Adds a new event handler, registering it to the native event. For internal use only.</summary>
174 ///<param name="lib">The name of the native library definining the event.</param>
175 ///<param name="key">The name of the native event.</param>
176 ///<param name="evtCaller">Delegate to be called by native code on event raising.</param>
177 ///<param name="evtDelegate">Managed delegate that will be called by evtCaller on event raising.</param>
178 private void AddNativeEventHandler(string lib, string key, Efl.EventCb evtCaller, object evtDelegate)
180 IntPtr desc = Efl.EventDescription.GetNative(lib, key);
181 if (desc == IntPtr.Zero)
183 Eina.Log.Error($"Failed to get native event {key}");
186 if (eoEvents.ContainsKey((desc, evtDelegate)))
188 Eina.Log.Warning($"Event proxy for event {key} already registered!");
192 IntPtr evtCallerPtr = Marshal.GetFunctionPointerForDelegate(evtCaller);
193 if (!Efl.Eo.Globals.efl_event_callback_priority_add(handle, desc, 0, evtCallerPtr, IntPtr.Zero))
195 Eina.Log.Error($"Failed to add event proxy for event {key}");
199 eoEvents[(desc, evtDelegate)] = (evtCallerPtr, evtCaller);
200 Eina.Error.RaiseIfUnhandledException();
203 ///<summary>Removes the given event handler for the given event. For internal use only.</summary>
204 ///<param name="lib">The name of the native library definining the event.</param>
205 ///<param name="key">The name of the native event.</param>
206 ///<param name="evtDelegate">The delegate to be removed.</param>
207 private void RemoveNativeEventHandler(string lib, string key, object evtDelegate)
209 IntPtr desc = Efl.EventDescription.GetNative(lib, key);
210 if (desc == IntPtr.Zero)
212 Eina.Log.Error($"Failed to get native event {key}");
216 var evtPair = (desc, evtDelegate);
217 if (eoEvents.TryGetValue(evtPair, out var caller))
219 if (!Efl.Eo.Globals.efl_event_callback_del(handle, desc, caller.evtCallerPtr, IntPtr.Zero))
221 Eina.Log.Error($"Failed to remove event proxy for event {key}");
225 eoEvents.Remove(evtPair);
226 Eina.Error.RaiseIfUnhandledException();
230 Eina.Log.Error($"Trying to remove proxy for event {key} when it is nothing registered.");
234 /// <summary>Notifies can_write property changed.
235 /// If <see cref="Efl.Io.IWriter.CanWrite"/> is <c>true</c> there is data to <see cref="Efl.Io.IWriter.Write"/> without blocking/error. If <see cref="Efl.Io.IWriter.CanWrite"/> is <c>false</c>, <see cref="Efl.Io.IWriter.Write"/> would either block or fail.
237 /// Note that usually this event is dispatched from inside <see cref="Efl.Io.IWriter.Write"/>, thus before it returns.
238 /// (Since EFL 1.22)</summary>
239 public event EventHandler<Efl.Io.IWriterCanWriteChangedEvt_Args> CanWriteChangedEvt
245 var wRef = new WeakReference(this);
246 Efl.EventCb callerCb = (IntPtr data, ref Efl.Event.NativeStruct evt) =>
248 var obj = wRef.Target as Efl.Eo.IWrapper;
251 Efl.Io.IWriterCanWriteChangedEvt_Args args = new Efl.Io.IWriterCanWriteChangedEvt_Args();
252 args.arg = evt.Info != IntPtr.Zero;
255 value?.Invoke(obj, args);
259 Eina.Log.Error(e.ToString());
260 Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);
265 string key = "_EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED";
266 AddNativeEventHandler(efl.Libs.Efl, key, callerCb, value);
274 string key = "_EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED";
275 RemoveNativeEventHandler(efl.Libs.Efl, key, value);
279 ///<summary>Method to raise event CanWriteChangedEvt.</summary>
280 public void OnCanWriteChangedEvt(Efl.Io.IWriterCanWriteChangedEvt_Args e)
282 var key = "_EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED";
283 IntPtr desc = Efl.EventDescription.GetNative(efl.Libs.Efl, key);
284 if (desc == IntPtr.Zero)
286 Eina.Log.Error($"Failed to get native event {key}");
290 IntPtr info = Eina.PrimitiveConversion.ManagedToPointerAlloc(e.arg ? (byte) 1 : (byte) 0);
293 Efl.Eo.Globals.efl_event_callback_call(this.NativeHandle, desc, info);
297 Marshal.FreeHGlobal(info);
300 /// <summary>If <c>true</c> will notify <see cref="Efl.Io.IWriter.Write"/> can be called without blocking or failing.
301 /// (Since EFL 1.22)</summary>
302 /// <returns><c>true</c> if it can be written without blocking or failure, <c>false</c> otherwise</returns>
303 public bool GetCanWrite() {
304 var _ret_var = Efl.Io.IWriterConcrete.NativeMethods.efl_io_writer_can_write_get_ptr.Value.Delegate(this.NativeHandle);
305 Eina.Error.RaiseIfUnhandledException();
308 /// <summary>If <c>true</c> will notify <see cref="Efl.Io.IWriter.Write"/> can be called without blocking or failing.
309 /// (Since EFL 1.22)</summary>
310 /// <param name="can_write"><c>true</c> if it can be written without blocking or failure, <c>false</c> otherwise</param>
311 public void SetCanWrite(bool can_write) {
312 Efl.Io.IWriterConcrete.NativeMethods.efl_io_writer_can_write_set_ptr.Value.Delegate(this.NativeHandle,can_write);
313 Eina.Error.RaiseIfUnhandledException();
315 /// <summary>Writes data from a pre-populated buffer.
316 /// This operation will be executed immediately and may or may not block the caller thread for some time. The details of blocking behavior is defined by the implementation and may be subject to other parameters such as non-blocking flags, maximum timeout or even retry attempts.
318 /// You can understand this method as write(2) libc function.
319 /// (Since EFL 1.22)</summary>
320 /// <param name="slice">Provides a pre-populated memory to be used up to slice.len. The returned slice will be adapted as length will be set to the actually used amount of bytes, which can be smaller than the request.</param>
321 /// <param name="remaining">Convenience to output the remaining parts of slice that was not written. If the full slice was written, this will be a slice of zero-length.</param>
322 /// <returns>0 on succeed, a mapping of errno otherwise</returns>
323 public Eina.Error Write(ref Eina.Slice slice, ref Eina.Slice remaining) {
324 var _ret_var = Efl.Io.IWriterConcrete.NativeMethods.efl_io_writer_write_ptr.Value.Delegate(this.NativeHandle,ref slice, ref remaining);
325 Eina.Error.RaiseIfUnhandledException();
328 /// <summary>If <c>true</c> will notify <see cref="Efl.Io.IWriter.Write"/> can be called without blocking or failing.
329 /// (Since EFL 1.22)</summary>
330 /// <value><c>true</c> if it can be written without blocking or failure, <c>false</c> otherwise</value>
331 public bool CanWrite {
332 get { return GetCanWrite(); }
333 set { SetCanWrite(value); }
335 private static IntPtr GetEflClassStatic()
337 return Efl.Io.IWriterConcrete.efl_io_writer_interface_get();
339 /// <summary>Wrapper for native methods and virtual method delegates.
340 /// For internal use by generated code only.</summary>
341 public class NativeMethods : Efl.Eo.NativeClass
343 private static Efl.Eo.NativeModule Module = new Efl.Eo.NativeModule( efl.Libs.Efl);
344 /// <summary>Gets the list of Eo operations to override.</summary>
345 /// <returns>The list of Eo operations to be overload.</returns>
346 public override System.Collections.Generic.List<Efl_Op_Description> GetEoOps(System.Type type)
348 var descs = new System.Collections.Generic.List<Efl_Op_Description>();
349 var methods = Efl.Eo.Globals.GetUserMethods(type);
351 if (efl_io_writer_can_write_get_static_delegate == null)
353 efl_io_writer_can_write_get_static_delegate = new efl_io_writer_can_write_get_delegate(can_write_get);
356 if (methods.FirstOrDefault(m => m.Name == "GetCanWrite") != null)
358 descs.Add(new Efl_Op_Description() {api_func = Efl.Eo.FunctionInterop.LoadFunctionPointer(Module.Module, "efl_io_writer_can_write_get"), func = Marshal.GetFunctionPointerForDelegate(efl_io_writer_can_write_get_static_delegate) });
361 if (efl_io_writer_can_write_set_static_delegate == null)
363 efl_io_writer_can_write_set_static_delegate = new efl_io_writer_can_write_set_delegate(can_write_set);
366 if (methods.FirstOrDefault(m => m.Name == "SetCanWrite") != null)
368 descs.Add(new Efl_Op_Description() {api_func = Efl.Eo.FunctionInterop.LoadFunctionPointer(Module.Module, "efl_io_writer_can_write_set"), func = Marshal.GetFunctionPointerForDelegate(efl_io_writer_can_write_set_static_delegate) });
371 if (efl_io_writer_write_static_delegate == null)
373 efl_io_writer_write_static_delegate = new efl_io_writer_write_delegate(write);
376 if (methods.FirstOrDefault(m => m.Name == "Write") != null)
378 descs.Add(new Efl_Op_Description() {api_func = Efl.Eo.FunctionInterop.LoadFunctionPointer(Module.Module, "efl_io_writer_write"), func = Marshal.GetFunctionPointerForDelegate(efl_io_writer_write_static_delegate) });
383 /// <summary>Returns the Eo class for the native methods of this class.</summary>
384 /// <returns>The native class pointer.</returns>
385 public override IntPtr GetEflClass()
387 return Efl.Io.IWriterConcrete.efl_io_writer_interface_get();
390 #pragma warning disable CA1707, SA1300, SA1600
392 [return: MarshalAs(UnmanagedType.U1)]
393 private delegate bool efl_io_writer_can_write_get_delegate(System.IntPtr obj, System.IntPtr pd);
395 [return: MarshalAs(UnmanagedType.U1)]
396 public delegate bool efl_io_writer_can_write_get_api_delegate(System.IntPtr obj);
398 public static Efl.Eo.FunctionWrapper<efl_io_writer_can_write_get_api_delegate> efl_io_writer_can_write_get_ptr = new Efl.Eo.FunctionWrapper<efl_io_writer_can_write_get_api_delegate>(Module, "efl_io_writer_can_write_get");
400 private static bool can_write_get(System.IntPtr obj, System.IntPtr pd)
402 Eina.Log.Debug("function efl_io_writer_can_write_get was called");
403 Efl.Eo.IWrapper wrapper = Efl.Eo.Globals.PrivateDataGet(pd);
406 bool _ret_var = default(bool);
409 _ret_var = ((IWriter)wrapper).GetCanWrite();
413 Eina.Log.Warning($"Callback error: {e.ToString()}");
414 Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);
422 return efl_io_writer_can_write_get_ptr.Value.Delegate(Efl.Eo.Globals.efl_super(obj, Efl.Eo.Globals.efl_class_get(obj)));
426 private static efl_io_writer_can_write_get_delegate efl_io_writer_can_write_get_static_delegate;
429 private delegate void efl_io_writer_can_write_set_delegate(System.IntPtr obj, System.IntPtr pd, [MarshalAs(UnmanagedType.U1)] bool can_write);
432 public delegate void efl_io_writer_can_write_set_api_delegate(System.IntPtr obj, [MarshalAs(UnmanagedType.U1)] bool can_write);
434 public static Efl.Eo.FunctionWrapper<efl_io_writer_can_write_set_api_delegate> efl_io_writer_can_write_set_ptr = new Efl.Eo.FunctionWrapper<efl_io_writer_can_write_set_api_delegate>(Module, "efl_io_writer_can_write_set");
436 private static void can_write_set(System.IntPtr obj, System.IntPtr pd, bool can_write)
438 Eina.Log.Debug("function efl_io_writer_can_write_set was called");
439 Efl.Eo.IWrapper wrapper = Efl.Eo.Globals.PrivateDataGet(pd);
445 ((IWriter)wrapper).SetCanWrite(can_write);
449 Eina.Log.Warning($"Callback error: {e.ToString()}");
450 Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);
457 efl_io_writer_can_write_set_ptr.Value.Delegate(Efl.Eo.Globals.efl_super(obj, Efl.Eo.Globals.efl_class_get(obj)), can_write);
461 private static efl_io_writer_can_write_set_delegate efl_io_writer_can_write_set_static_delegate;
464 private delegate Eina.Error efl_io_writer_write_delegate(System.IntPtr obj, System.IntPtr pd, ref Eina.Slice slice, ref Eina.Slice remaining);
467 public delegate Eina.Error efl_io_writer_write_api_delegate(System.IntPtr obj, ref Eina.Slice slice, ref Eina.Slice remaining);
469 public static Efl.Eo.FunctionWrapper<efl_io_writer_write_api_delegate> efl_io_writer_write_ptr = new Efl.Eo.FunctionWrapper<efl_io_writer_write_api_delegate>(Module, "efl_io_writer_write");
471 private static Eina.Error write(System.IntPtr obj, System.IntPtr pd, ref Eina.Slice slice, ref Eina.Slice remaining)
473 Eina.Log.Debug("function efl_io_writer_write was called");
474 Efl.Eo.IWrapper wrapper = Efl.Eo.Globals.PrivateDataGet(pd);
477 remaining = default(Eina.Slice); Eina.Error _ret_var = default(Eina.Error);
480 _ret_var = ((IWriter)wrapper).Write(ref slice, ref remaining);
484 Eina.Log.Warning($"Callback error: {e.ToString()}");
485 Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);
493 return efl_io_writer_write_ptr.Value.Delegate(Efl.Eo.Globals.efl_super(obj, Efl.Eo.Globals.efl_class_get(obj)), ref slice, ref remaining);
497 private static efl_io_writer_write_delegate efl_io_writer_write_static_delegate;
499 #pragma warning restore CA1707, SA1300, SA1600