From 08ea583412ceaa49a11084e92d542c5f6565f0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 12 May 2009 15:27:13 +0200 Subject: [PATCH] Add Enum/FlagsInfo to query a GEnum/GFlags type --- gstreamer-sharp/EnumInfo.cs | 204 ++++++++++++++++++++++++++++++++++ gstreamer-sharp/Makefile.am | 1 + gstreamer-sharp/Object.custom | 23 ++-- 3 files changed, 220 insertions(+), 8 deletions(-) create mode 100644 gstreamer-sharp/EnumInfo.cs diff --git a/gstreamer-sharp/EnumInfo.cs b/gstreamer-sharp/EnumInfo.cs new file mode 100644 index 0000000000..758c8ac8ba --- /dev/null +++ b/gstreamer-sharp/EnumInfo.cs @@ -0,0 +1,204 @@ +using GLib; +using Gst; +using System; +using System.Runtime.InteropServices; + +namespace Gst { + + public struct EnumValue { + internal int value; + public int Value { + get { + return value; + } + } + + internal string value_name; + public string Name { + get { + return value_name; + } + } + + internal string value_nick; + public string Nick { + get { + return value_nick; + } + } + } + + public struct FlagsValue { + internal uint value; + public uint Value { + get { + return value; + } + } + + internal string value_name; + public string Name { + get { + return value_name; + } + } + + internal string value_nick; + public string Nick { + get { + return value_nick; + } + } + } + + public struct EnumInfo { + [StructLayout (LayoutKind.Sequential) ] + struct GTypeClass { + IntPtr gtype; + } + + [StructLayout (LayoutKind.Sequential) ] + struct GEnumClass { + GTypeClass gclass; + public int minimum; + public int maximum; + public uint n_values; + public IntPtr values; + } + + [StructLayout (LayoutKind.Sequential) ] + struct GEnumValue { + public int value; + public IntPtr value_name; + public IntPtr value_nick; + } + + [DllImport ("libgobject-2.0-0.dll") ] + static extern IntPtr g_type_class_ref (IntPtr gtype); + [DllImport ("libgobject-2.0-0.dll") ] + static extern void g_type_class_unref (IntPtr gclass); + [DllImport ("libgobject-2.0-0.dll") ] + static extern bool g_type_is_a (IntPtr type, IntPtr is_a_type); + + int min; + public int Min { + get { + return min; + } + } + + int max; + public int Max { + get { + return max; + } + } + + EnumValue[] values; + public EnumValue[] Values { + get { + return values; + } + } + + public static bool IsEnumType (GLib.GType gtype) { + return (g_type_is_a (gtype.Val, GType.Enum.Val)); + } + + public EnumInfo (GLib.GType gtype) { + if (!IsEnumType (gtype)) + throw new ArgumentException (); + + IntPtr class_ptr = g_type_class_ref (gtype.Val); + if (class_ptr == IntPtr.Zero) + throw new Exception (); + + GEnumClass klass = (GEnumClass) Marshal.PtrToStructure (class_ptr, typeof (GEnumClass)); + this.min = klass.minimum; + this.max = klass.maximum; + + values = new EnumValue[klass.n_values]; + int unmanaged_struct_size = Marshal.SizeOf (typeof (GEnumValue)); + for (int i = 0; i < klass.n_values; i++) { + GEnumValue gv = (GEnumValue) Marshal.PtrToStructure (new IntPtr (klass.values.ToInt64() + i * unmanaged_struct_size), typeof (GEnumValue)); + values[i].value = gv.value; + values[i].value_name = GLib.Marshaller.Utf8PtrToString (gv.value_name); + values[i].value_nick = GLib.Marshaller.Utf8PtrToString (gv.value_nick); + } + + g_type_class_unref (class_ptr); + + } + } + + public struct FlagsInfo { + [StructLayout (LayoutKind.Sequential) ] + struct GTypeClass { + IntPtr gtype; + } + + [StructLayout (LayoutKind.Sequential) ] + struct GFlagsClass { + GTypeClass gclass; + public uint mask; + public uint n_values; + public IntPtr values; + } + + [StructLayout (LayoutKind.Sequential) ] + struct GFlagsValue { + public uint value; + public IntPtr value_name; + public IntPtr value_nick; + } + + [DllImport ("libgobject-2.0-0.dll") ] + static extern IntPtr g_type_class_ref (IntPtr gtype); + [DllImport ("libgobject-2.0-0.dll") ] + static extern void g_type_class_unref (IntPtr gclass); + [DllImport ("libgobject-2.0-0.dll") ] + static extern bool g_type_is_a (IntPtr type, IntPtr is_a_type); + + uint mask; + public uint Mask { + get { + return mask; + } + } + + FlagsValue[] values; + public FlagsValue[] Values { + get { + return values; + } + } + + public static bool IsFlagsType (GLib.GType gtype) { + return (g_type_is_a (gtype.Val, GType.Flags.Val)); + } + + public FlagsInfo (GLib.GType gtype) { + if (!IsFlagsType (gtype)) + throw new ArgumentException (); + + IntPtr class_ptr = g_type_class_ref (gtype.Val); + if (class_ptr == IntPtr.Zero) + throw new Exception (); + + GFlagsClass klass = (GFlagsClass) Marshal.PtrToStructure (class_ptr, typeof (GFlagsClass)); + this.mask = klass.mask; + + values = new FlagsValue[klass.n_values]; + int unmanaged_struct_size = Marshal.SizeOf (typeof (GFlagsValue)); + for (int i = 0; i < klass.n_values; i++) { + GFlagsValue gv = (GFlagsValue) Marshal.PtrToStructure (new IntPtr (klass.values.ToInt64() + i * unmanaged_struct_size), typeof (GFlagsValue)); + values[i].value = gv.value; + values[i].value_name = GLib.Marshaller.Utf8PtrToString (gv.value_name); + values[i].value_nick = GLib.Marshaller.Utf8PtrToString (gv.value_nick); + } + + g_type_class_unref (class_ptr); + } + + } +} diff --git a/gstreamer-sharp/Makefile.am b/gstreamer-sharp/Makefile.am index 605da90eb1..78716fe14a 100644 --- a/gstreamer-sharp/Makefile.am +++ b/gstreamer-sharp/Makefile.am @@ -45,6 +45,7 @@ sources = \ GError.cs \ Value.cs \ PropertyInfo.cs \ + EnumInfo.cs \ Iterator.cs \ GstSharp.PadQueryTypeFunctionNative.cs \ PadQueryTypeFunction.cs \ diff --git a/gstreamer-sharp/Object.custom b/gstreamer-sharp/Object.custom index 2cb0f51aa7..5e38ce742a 100644 --- a/gstreamer-sharp/Object.custom +++ b/gstreamer-sharp/Object.custom @@ -62,7 +62,8 @@ public PropertyInfo[] Properties { ret[i].controllable = ( (pspec.Flags & (1 << 9)) != 0); /* TODO: Add more flags later, like the mutable flags */ - ret[i].type = (System.Type) new GLib.GType (pspec.ValueType); + ret[i].gtype = new GLib.GType (pspec.ValueType); + ret[i].type = (System.Type) ret[i].gtype; try { GLib.Value v = new GLib.Value (new GLib.GType (pspec.ValueType)); @@ -70,14 +71,20 @@ public PropertyInfo[] Properties { ret[i].dflt = v.Val; v.Dispose (); - GLib.Value min = new GLib.Value (new GLib.GType (pspec.ValueType)); - GLib.Value max = new GLib.Value (new GLib.GType (pspec.ValueType)); - if (gstsharp_g_param_spec_get_range (pspec_ptr, ref min, ref max)) { - ret[i].min = (object) min.Val; - ret[i].max = (object) max.Val; + if (EnumInfo.IsEnumType (ret[i].gtype)) { + EnumInfo ei = new EnumInfo (ret[i].gtype); + ret[i].min = ei.Min; + ret[i].max = ei.Max; + } else { + GLib.Value min = new GLib.Value (new GLib.GType (pspec.ValueType)); + GLib.Value max = new GLib.Value (new GLib.GType (pspec.ValueType)); + if (gstsharp_g_param_spec_get_range (pspec_ptr, ref min, ref max)) { + ret[i].min = (object) min.Val; + ret[i].max = (object) max.Val; + } + min.Dispose (); + max.Dispose (); } - min.Dispose (); - max.Dispose (); } catch (Exception) {} }