[DllImport ("gstreamersharpglue-0.10.dll") ] static extern uint gst__controllersharp_gst__controller_controlsource_get_get_value_offset (); static uint get_value_offset = gst__controllersharp_gst__controller_controlsource_get_get_value_offset (); [StructLayout (LayoutKind.Sequential) ] struct GstValueArray { public IntPtr property_name; public int nbsamples; public ulong sample_interval; public IntPtr values; } [StructLayout (LayoutKind.Sequential) ] struct GstControlSourceCallbacks { public GetValueCallbackNative get_value; public GetValueArrayCallbackNative get_value_array; } delegate bool GetValueCallbackNative (IntPtr raw, ulong timestamp, ref GLib.Value val); delegate bool GetValueArrayCallbackNative (IntPtr raw, ulong timestamp, ref GstValueArray va); public delegate bool GetValueCallback (ulong timestamp, ref GLib.Value value); public delegate System.Array GetValueArrayCallback (ulong timestamp, int nsamples, ulong interval); private GetValueCallbackWrapper GetValue_cb_wrapper; private GetValueArrayCallbackWrapper GetValueArray_cb_wrapper; private class GetValueCallbackWrapper { public bool NativeCallback (IntPtr raw, ulong timestamp, ref GLib.Value val) { try { bool __ret = managed (timestamp, ref val); return __ret; } catch (Exception e) { GLib.ExceptionManager.RaiseUnhandledException (e, true); // NOTREACHED: Above call does not return. throw e; } } internal GetValueCallbackNative NativeDelegate; GetValueCallback managed; public GetValueCallbackWrapper (GetValueCallback managed) { this.managed = managed; if (managed != null) NativeDelegate = new GetValueCallbackNative (NativeCallback); } public static GetValueCallback GetManagedDelegate (GetValueCallbackNative native) { if (native == null) return null; GetValueCallbackWrapper wrapper = (GetValueCallbackWrapper) native.Target; if (wrapper == null) return null; return wrapper.managed; } } private class GetValueArrayCallbackWrapper { public bool NativeCallback (IntPtr raw, ulong timestamp, ref GstValueArray va) { try { System.Array values = managed (timestamp, va.nbsamples, va.sample_interval); if (values == null) return false; System.Type t = values.GetType (); if (t == typeof (string[])) { string[] ret = (string[]) values; for (int i = 0; i < va.nbsamples; i++) { Marshal.WriteIntPtr (va.values, i * IntPtr.Size, GLib.Marshaller.StringToPtrGStrdup (ret[i])); } } else if (t == typeof (short[])) { short[] ret = (short[]) values; for (int i = 0; i < va.nbsamples; i++) { Marshal.WriteInt16 (va.values, i * 2, ret[i]); } } else if (t == typeof (ushort[])) { ushort[] ret = (ushort[]) values; for (int i = 0; i < va.nbsamples; i++) { Marshal.WriteInt16 (va.values, i * 2, (short) ret[i]); } } else if (t == typeof (int[])) { int[] ret = (int[]) values; for (int i = 0; i < va.nbsamples; i++) { Marshal.WriteInt32 (va.values, i * 4, ret[i]); } } else if (t == typeof (uint[])) { uint[] ret = (uint[]) values; for (int i = 0; i < va.nbsamples; i++) { Marshal.WriteInt32 (va.values, i * 4, (int) ret[i]); } } else if (t == typeof (long[])) { long[] ret = (long[]) values; for (int i = 0; i < va.nbsamples; i++) { Marshal.WriteInt64 (va.values, i * 8, ret[i]); } } else if (t == typeof (ulong[])) { ulong[] ret = (ulong[]) values; for (int i = 0; i < va.nbsamples; i++) { Marshal.WriteInt64 (va.values, i * 8, (long) ret[i]); } } else if (t == typeof (float[])) { float[] ret = (float[]) values; Marshal.Copy (ret, 0, va.values, va.nbsamples); } else if (t == typeof (double[])) { double[] ret = (double[]) values; Marshal.Copy (ret, 0, va.values, va.nbsamples); } else if (t == typeof (bool[])) { bool[] ret = (bool[]) values; for (int i = 0; i < va.nbsamples; i++) { Marshal.WriteInt32 (va.values, i * 4, ret[i] == false ? 0 : 1); } } return true; } catch (Exception e) { GLib.ExceptionManager.RaiseUnhandledException (e, true); // NOTREACHED: Above call does not return. throw e; } } internal GetValueArrayCallbackNative NativeDelegate; GetValueArrayCallback managed; public GetValueArrayCallbackWrapper (GetValueArrayCallback managed) { this.managed = managed; if (managed != null) NativeDelegate = new GetValueArrayCallbackNative (NativeCallback); } public static GetValueArrayCallback GetManagedDelegate (GetValueArrayCallbackNative native) { if (native == null) return null; GetValueArrayCallbackWrapper wrapper = (GetValueArrayCallbackWrapper) native.Target; if (wrapper == null) return null; return wrapper.managed; } } public void SetCallbacks (GetValueCallback get_value, GetValueArrayCallback get_value_array) { IntPtr off = new IntPtr (Handle.ToInt64 () + get_value_offset); GstControlSourceCallbacks cbs = (GstControlSourceCallbacks) Marshal.PtrToStructure (new IntPtr (Handle.ToInt64 () + get_value_offset), typeof (GstControlSourceCallbacks)); GetValueCallbackWrapper gv_wr = new GetValueCallbackWrapper (get_value); GetValueArrayCallbackWrapper gva_wr = new GetValueArrayCallbackWrapper (get_value_array); GetValue_cb_wrapper = gv_wr; GetValueArray_cb_wrapper = gva_wr; cbs.get_value = gv_wr.NativeCallback; cbs.get_value_array = gva_wr.NativeCallback; Marshal.StructureToPtr (cbs, off, false); } [DllImport ("gstreamersharpglue-0.10.dll") ] static extern bool gst__controllersharp_gst__controller_controlsource_base_bind (IntPtr handle, IntPtr pspec); [DllImport ("gstreamersharpglue-0.10.dll") ] static extern void gst__controllersharp_gst__controller_controlsource_override_bind (IntPtr gtype, BindNativeDelegate cb); [GLib.CDeclCallback] delegate bool BindNativeDelegate (IntPtr handler, IntPtr pspec); static BindNativeDelegate Bind_cb_delegate; static BindNativeDelegate BindVMCallback { get { if (Bind_cb_delegate == null) Bind_cb_delegate = new BindNativeDelegate (Bind_cb); return Bind_cb_delegate; } } static void OverrideBind (GLib.GType gtype) { OverrideBind (gtype, BindVMCallback); } static void OverrideBind (GLib.GType gtype, BindNativeDelegate callback) { gst__controllersharp_gst__controller_controlsource_override_bind (gtype.Val, callback); } static bool Bind_cb (IntPtr inst, IntPtr pspec) { try { ControlSource __obj = GLib.Object.GetObject (inst, false) as ControlSource; Gst.PropertyInfo pinfo = new Gst.PropertyInfo (pspec); return __obj.OnBind (pinfo); } catch (Exception e) { GLib.ExceptionManager.RaiseUnhandledException (e, false); return false; } } [DllImport ("libgobject-2.0-0.dll") ] static extern IntPtr g_object_class_find_property (IntPtr klass, IntPtr property); [GLib.DefaultSignalHandler (Type=typeof (Gst.Controller.ControlSource), ConnectionMethod="OverrideBind") ] protected virtual bool OnBind (Gst.PropertyInfo pinfo) { IntPtr klass = Marshal.ReadIntPtr (Handle); IntPtr native_property = GLib.Marshaller.StringToPtrGStrdup (pinfo.Name); IntPtr pspec = g_object_class_find_property (klass, native_property); GLib.Marshaller.Free (native_property); if (pspec == IntPtr.Zero) return false; return gst__controllersharp_gst__controller_controlsource_base_bind (this.Handle, pspec); } [DllImport ("libgstcontroller-0.10.dll") ] static extern bool gst_control_source_get_value_array (IntPtr raw, ulong timestamp, ref GstValueArray value_array); [DllImport ("libglib-2.0-0.dll") ] static extern IntPtr g_try_malloc (int size); static readonly Type[] supported_types = new Type[] { typeof (string), typeof (short), typeof (ushort), typeof (int), typeof (uint), typeof (long), typeof (ulong), typeof (float), typeof (double), typeof (bool) }; public System.Array GetValueArray (ulong timestamp, int nsamples, ulong interval) { GstValueArray va = new GstValueArray (); GLib.Value v = GLib.Value.Empty; if (!GetValue (0, ref v)) return null; System.Type t = v.Val.GetType (); v.Dispose (); bool supported = false; foreach (System.Type tmp in supported_types) if (tmp == t) supported = true; if (!supported) throw new Exception ("Unsupported type '" + t + "'"); int eltsize = Marshal.SizeOf (t); va.values = g_try_malloc (eltsize * nsamples); if (va.values == IntPtr.Zero) throw new OutOfMemoryException (); va.nbsamples = nsamples; va.sample_interval = interval; bool raw_ret = gst_control_source_get_value_array (Handle, timestamp, ref va); if (!raw_ret) { GLib.Marshaller.Free (va.values); return null; } System.Array values = Array.CreateInstance (t, nsamples); if (t == typeof (string)) { string[] ret = (string[]) values; for (int i = 0; i < nsamples; i++) { IntPtr str = Marshal.ReadIntPtr (va.values, i * IntPtr.Size); ret[i] = GLib.Marshaller.PtrToStringGFree (str); } } else if (t == typeof (short)) { short[] ret = (short[]) values; for (int i = 0; i < nsamples; i++) { ret[i] = Marshal.ReadInt16 (va.values, i * 2); } } else if (t == typeof (ushort)) { ushort[] ret = (ushort[]) values; for (int i = 0; i < nsamples; i++) { ret[i] = (ushort) Marshal.ReadInt16 (va.values, i * 2); } } else if (t == typeof (int)) { int[] ret = (int[]) values; for (int i = 0; i < nsamples; i++) { ret[i] = Marshal.ReadInt32 (va.values, i * 4); } } else if (t == typeof (uint)) { uint[] ret = (uint[]) values; for (int i = 0; i < nsamples; i++) { ret[i] = (uint) Marshal.ReadInt32 (va.values, i * 4); } } else if (t == typeof (long)) { long[] ret = (long[]) values; for (int i = 0; i < nsamples; i++) { ret[i] = Marshal.ReadInt64 (va.values, i * 8); } } else if (t == typeof (ulong)) { ulong[] ret = (ulong[]) values; for (int i = 0; i < nsamples; i++) { ret[i] = (ulong) Marshal.ReadInt64 (va.values, i * 8); } } else if (t == typeof (float)) { float[] ret = (float[]) values; Marshal.Copy (va.values, ret, 0, nsamples); } else if (t == typeof (double)) { double[] ret = (double[]) values; Marshal.Copy (va.values, ret, 0, nsamples); } else if (t == typeof (bool)) { bool[] ret = (bool[]) values; for (int i = 0; i < nsamples; i++) { ret[i] = Marshal.ReadInt32 (va.values, i * 4) != 0; } } GLib.Marshaller.Free (va.values); return values; }