From d45b43983e1a9b4c2b84e657864d602440aee39a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 11 Apr 2009 17:52:50 +0200 Subject: [PATCH] Add initial support for our custom GValue types and for setting/getting MiniObjects from/to GValues --- gstreamer-sharp/Application.cs | 2 +- gstreamer-sharp/Gstreamer.metadata | 3 + gstreamer-sharp/Makefile.am | 1 + gstreamer-sharp/MiniObject.custom | 24 + gstreamer-sharp/Value.cs | 536 ++++++++++++++++++ gstreamer-sharp/glue/Makefile.am | 4 +- .../glue/{dynamicsignal.c => gobject.c} | 6 + 7 files changed, 573 insertions(+), 3 deletions(-) create mode 100644 gstreamer-sharp/Value.cs rename gstreamer-sharp/glue/{dynamicsignal.c => gobject.c} (71%) diff --git a/gstreamer-sharp/Application.cs b/gstreamer-sharp/Application.cs index fd2e20e33e..4e08ae10bd 100644 --- a/gstreamer-sharp/Application.cs +++ b/gstreamer-sharp/Application.cs @@ -73,7 +73,7 @@ namespace Gst { } else { progargs = argv.GetArgs (argc); args = new string[argc - 1]; - Array.Copy (progargs, 1, args, 0, argc - 1); + System.Array.Copy (progargs, 1, args, 0, argc - 1); } } diff --git a/gstreamer-sharp/Gstreamer.metadata b/gstreamer-sharp/Gstreamer.metadata index dd0e23f9f4..51009c8e9a 100644 --- a/gstreamer-sharp/Gstreamer.metadata +++ b/gstreamer-sharp/Gstreamer.metadata @@ -305,4 +305,7 @@ out 1 + + + 1 diff --git a/gstreamer-sharp/Makefile.am b/gstreamer-sharp/Makefile.am index dd838d2b80..cc08953584 100644 --- a/gstreamer-sharp/Makefile.am +++ b/gstreamer-sharp/Makefile.am @@ -44,6 +44,7 @@ sources = \ AssemblyInfo.cs \ CommonTags.cs \ GError.cs \ + Value.cs \ plugins-base/PlayBin.cs \ plugins-base/DecodeBin.cs \ plugins-base/TypeFindElement.cs diff --git a/gstreamer-sharp/MiniObject.custom b/gstreamer-sharp/MiniObject.custom index d84dcc6bde..ab6146532f 100644 --- a/gstreamer-sharp/MiniObject.custom +++ b/gstreamer-sharp/MiniObject.custom @@ -1,3 +1,27 @@ protected MiniObject () : base (IntPtr.Zero) { } + + public static MiniObject NewFromValue (GLib.Value val) { + IntPtr type = gstsharp_g_value_type (ref val); + GLib.GType gtype = new GLib.GType (type); + + return (MiniObject) GLib.Opaque.GetOpaque (gst_value_get_mini_object (ref val), (Type) gtype, false); + } + + public static explicit operator GLib.Value (MiniObject o) { + GLib.Value val = new GLib.Value (new GLib.GType (gstsharp_g_type_from_instance (o.Handle))); + + gst_value_set_mini_object (ref val, o.Handle); + + return val; + } + + [DllImport("gstreamersharpglue-0.10.dll")] + private static extern IntPtr gstsharp_g_type_from_instance (IntPtr o); + [DllImport("gstreamersharpglue-0.10.dll")] + private static extern IntPtr gstsharp_g_value_type (ref GLib.Value val); + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_value_get_mini_object (ref GLib.Value v); + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_set_mini_object (ref GLib.Value v, IntPtr o); diff --git a/gstreamer-sharp/Value.cs b/gstreamer-sharp/Value.cs new file mode 100644 index 0000000000..13398ae1b2 --- /dev/null +++ b/gstreamer-sharp/Value.cs @@ -0,0 +1,536 @@ +// Wrapper for GLib.Value to add support for GstFraction, GstFourcc, Gst*Range, ... + +using System; +using System.Collections; +using System.Runtime.InteropServices; +using GLib; + +/* TODO: intersect, compare, substract, .... */ +namespace Gst { + public static class Value { + public static object GetValue (GLib.Value val) { + IntPtr type = gstsharp_g_value_type (ref val); + GType gtype = new GType (type); + + if (type == Fraction.GType.Val) + return new Fraction (val); + else if (type == DoubleRange.GType.Val) + return new DoubleRange (val); + else if (type == IntRange.GType.Val) + return new IntRange (val); + else if (type == FractionRange.GType.Val) + return new FractionRange (val); + else if (type == Fourcc.GType.Val) + return new Fourcc (val); + else if (type == Date.GType.Val) + return new Date (val); + else if (type == Gst.List.GType.Val) + return new Gst.List (val); + else if (type == Gst.Array.GType.Val) + return new Gst.Array (val); + else if (((Type) gtype).IsSubclassOf (typeof (Gst.MiniObject))) + return MiniObject.NewFromValue (val); + else + return val.Val; + } + + [DllImport("gstreamersharpglue-0.10.dll")] + private static extern IntPtr gstsharp_g_value_type (ref GLib.Value val); + + public static GLib.Value CreateValue (object o) { + if (o.GetType () == typeof (Fraction)) + return (GLib.Value) ((Fraction) o); + else if (o.GetType () == typeof (DoubleRange)) + return (GLib.Value) ((DoubleRange) o); + else if (o.GetType () == typeof (IntRange)) + return (GLib.Value) ((IntRange) o); + else if (o.GetType () == typeof (FractionRange)) + return (GLib.Value) ((FractionRange) o); + else if (o.GetType () == typeof (Fourcc)) + return (GLib.Value) ((Fourcc) o); + else if (o.GetType () == typeof (Date)) + return (GLib.Value) ((Date) o); + else if (o.GetType () == typeof (DateTime)) + return (GLib.Value) (new Date ((DateTime) o)); + else if (o.GetType () == typeof (Gst.List)) + return (GLib.Value) ((Gst.List) o); + else if (o.GetType () == typeof (Gst.Array)) + return (GLib.Value) ((Gst.Array) o); + else if (o.GetType ().IsSubclassOf (typeof (Gst.MiniObject))) + return (GLib.Value) ((MiniObject) o); + else + return new GLib.Value (o); + } + } + + public struct Fraction { + public int Numerator { + get { + return numerator; + } + + set { + numerator = value; + Reduce (); + } + } + + public int Denominator { + get { + return denominator; + } + + set { + if (denominator == 0) + throw new ArgumentException (); + + denominator = value; + Reduce (); + } + } + + private int numerator; + private int denominator; + + public static GLib.GType GType { + get { + return new GType (gst_fraction_get_type ()); + } + } + + private void Reduce () { + int gcd = GreatestCommonDivisor (this); + + if (gcd != 0) { + this.numerator /= gcd; + this.denominator /= gcd; + } + } + + private static int GreatestCommonDivisor (Fraction fraction) { + int a = fraction.numerator; + int b = fraction.denominator; + + while (b != 0) { + int temp = a; + + a = b; + b = temp % b; + } + return Math.Abs (a); + } + + public Fraction (int numerator, int denominator) { + if (denominator == 0) + throw new ArgumentException (); + + this.numerator = numerator; + this.denominator = denominator; + Reduce (); + } + + public Fraction (GLib.Value val) : this () { + this.numerator = gst_value_get_fraction_numerator (ref val); + this.denominator = gst_value_get_fraction_denominator (ref val); + } + + public override string ToString () { + return String.Format ("{0}/{1}", numerator, denominator); + } + + public static explicit operator GLib.Value (Fraction fraction) { + GLib.Value val = new GLib.Value (Fraction.GType); + gst_value_set_fraction (ref val, fraction.Numerator, fraction.Denominator); + + return val; + } + + public static explicit operator double (Fraction fraction) { + return ((double) fraction.numerator) / ((double) fraction.denominator); + } + + public static Fraction operator + (Fraction a, Fraction b) { + return new Fraction ((a.Numerator * b.Denominator) + (b.Numerator * a.Denominator), a.Denominator * b.Denominator); + } + + public static Fraction operator - (Fraction a, Fraction b) { + return new Fraction ((a.Numerator * b.Denominator) - (b.Numerator * a.Denominator), a.Denominator * b.Denominator); + } + + public static Fraction operator * (Fraction a, Fraction b) { + return new Fraction (a.Numerator * b.Numerator, a.Denominator * b.Denominator); + } + + public static Fraction operator / (Fraction a, Fraction b) { + return new Fraction (a.Numerator * b.Denominator, a.Denominator * b.Numerator); + } + + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_set_fraction (ref GLib.Value v, int numerator, int denominator); + [DllImport("gstreamer-0.10.dll")] + private static extern int gst_value_get_fraction_numerator (ref GLib.Value v); + [DllImport("gstreamer-0.10.dll")] + private static extern int gst_value_get_fraction_denominator (ref GLib.Value v); + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_fraction_get_type (); + } + + public struct DoubleRange { + public double Min; + public double Max; + + public static GLib.GType GType { + get { + return new GType (gst_double_range_get_type ()); + } + } + + public DoubleRange (double min, double max) { + if (min > max) + throw new ArgumentException (); + + this.Min = min; + this.Max = max; + } + + public DoubleRange (GLib.Value val) : this () { + this.Min = gst_value_get_double_range_min (ref val); + this.Max = gst_value_get_double_range_max (ref val); + } + + public override string ToString () { + return String.Format ("[{0}, {1}]", Min, Max); + } + + public static explicit operator GLib.Value (DoubleRange range) { + GLib.Value val = new GLib.Value (DoubleRange.GType); + + gst_value_set_double_range (ref val, range.Min, range.Max); + return val; + } + + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_double_range_get_type (); + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_set_double_range (ref GLib.Value v, double min, double max); + [DllImport("gstreamer-0.10.dll")] + private static extern double gst_value_get_double_range_min (ref GLib.Value v); + [DllImport("gstreamer-0.10.dll")] + private static extern double gst_value_get_double_range_max (ref GLib.Value v); + } + + public struct IntRange { + public int Min; + public int Max; + + public static GLib.GType GType { + get { + return new GType (gst_int_range_get_type ()); + } + } + + public IntRange (int min, int max) { + if (min > max) + throw new ArgumentException (); + + this.Min = min; + this.Max = max; + } + + public IntRange (GLib.Value val) : this () { + this.Min = gst_value_get_int_range_min (ref val); + this.Max = gst_value_get_int_range_max (ref val); + } + + public override string ToString () { + return String.Format ("[{0}, {1}]", Min, Max); + } + + public static explicit operator GLib.Value (IntRange range) { + GLib.Value val = new GLib.Value (IntRange.GType); + + gst_value_set_int_range (ref val, range.Min, range.Max); + return val; + } + + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_int_range_get_type (); + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_set_int_range (ref GLib.Value v, int min, int max); + [DllImport("gstreamer-0.10.dll")] + private static extern int gst_value_get_int_range_min (ref GLib.Value v); + [DllImport("gstreamer-0.10.dll")] + private static extern int gst_value_get_int_range_max (ref GLib.Value v); + } + + public struct FractionRange { + public Fraction Min; + public Fraction Max; + + public static GLib.GType GType { + get { + return new GType (gst_fraction_range_get_type ()); + } + } + + public FractionRange (Fraction min, Fraction max) { + double a = (double) min, b = (double) max; + + if (a > b) + throw new ArgumentException(); + + this.Min = min; + this.Max = max; + } + + public FractionRange (GLib.Value val) : this () { + IntPtr min_ptr, max_ptr; + GLib.Value min, max; + + min_ptr = gst_value_get_fraction_range_min (ref val); + max_ptr = gst_value_get_fraction_range_max (ref val); + + min = (GLib.Value) Marshal.PtrToStructure (min_ptr, typeof (GLib.Value)); + max = (GLib.Value) Marshal.PtrToStructure (max_ptr, typeof (GLib.Value)); + this.Min = (Fraction) Gst.Value.GetValue (min); + this.Max = (Fraction) Gst.Value.GetValue (max); + } + + public override string ToString () { + return String.Format ("[{0}, {1}]", Min, Max); + } + + public static explicit operator GLib.Value (FractionRange range) { + GLib.Value val = new GLib.Value (FractionRange.GType); + + GLib.Value min = (GLib.Value) (range.Min); + GLib.Value max = (GLib.Value) (range.Max); + gst_value_set_fraction_range (ref val, ref min, ref max); + return val; + } + + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_fraction_range_get_type (); + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_set_fraction_range (ref GLib.Value v, ref GLib.Value min, ref GLib.Value max); + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_value_get_fraction_range_min (ref GLib.Value v); + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_value_get_fraction_range_max (ref GLib.Value v); + } + + public struct Fourcc { + public uint Val; + + public static GLib.GType GType { + get { + return new GType (gst_fourcc_get_type ()); + } + } + + public Fourcc (uint fourcc) { + this.Val = fourcc; + } + + public Fourcc (char[] fourcc) { + if (fourcc.Length != 4) + throw new ArgumentException (); + + this.Val = (uint) ((((byte) fourcc[0]) << 24) | + (((byte) fourcc[1]) << 16) | + (((byte) fourcc[2]) << 8) | + (((byte) fourcc[3]) << 0)); + } + + public Fourcc (string fourcc) { + if (fourcc.Length != 4) + throw new ArgumentException (); + + this.Val = (uint) ((((byte) fourcc[0]) << 24) | + (((byte) fourcc[1]) << 16) | + (((byte) fourcc[2]) << 8) | + (((byte) fourcc[3]) << 0)); + } + + public Fourcc (GLib.Value val) : this (gst_value_get_fourcc (ref val)) { + } + + public override string ToString () { + return String.Format ("{0}{1}{2}{3}", (char) ((Val >> 24) & 0xff), + (char) ((Val >> 16) & 0xff), + (char) ((Val >> 8) & 0xff), + (char) ((Val >> 0) & 0xff)); + } + + public static explicit operator GLib.Value (Fourcc fourcc) { + GLib.Value val = new GLib.Value (Fourcc.GType); + + gst_value_set_fourcc (ref val, fourcc.Val); + return val; + } + + public static explicit operator char[] (Fourcc fourcc) { + return new char[] {(char) ((fourcc.Val >> 24) & 0xff), + (char) ((fourcc.Val >> 16) & 0xff), + (char) ((fourcc.Val >> 8) & 0xff), + (char) ((fourcc.Val >> 0) & 0xff)}; + } + + public static explicit operator string (Fourcc fourcc) { + return fourcc.ToString (); + } + + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_fourcc_get_type (); + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_set_fourcc (ref GLib.Value v, uint fourcc); + [DllImport("gstreamer-0.10.dll")] + private static extern uint gst_value_get_fourcc (ref GLib.Value v); + + } + + public struct Date { + public DateTime Val; + + public static GLib.GType GType { + get { + return new GType (gst_date_get_type ()); + } + } + + public Date (DateTime date) { + this.Val = date; + } + + public Date (int day, int month, int year) { + this.Val = new DateTime (year, month, day); + } + + public Date (GLib.Value val) { + IntPtr date = gst_value_get_date (ref val); + + this.Val = new DateTime (g_date_get_year (date), g_date_get_month (date), g_date_get_day (date)); + } + + public override string ToString () { + return Val.ToString (); + } + + public static explicit operator GLib.Value (Date date) { + GLib.Value val = new GLib.Value (Date.GType); + IntPtr date_ptr = g_date_new_dmy ((byte) date.Val.Day, (int) date.Val.Month, (ushort) date.Val.Year); + + gst_value_set_date (ref val, date_ptr); + + GLib.Marshaller.Free (date_ptr); + + return val; + } + + [DllImport("libglib-2.0-0.dll")] + private static extern byte g_date_get_day (IntPtr date); + [DllImport("libglib-2.0-0.dll")] + private static extern int g_date_get_month (IntPtr date); + [DllImport("libglib-2.0-0.dll")] + private static extern ushort g_date_get_year (IntPtr date); + [DllImport("libglib-2.0-0.dll")] + private static extern IntPtr g_date_new_dmy (byte day, int month, ushort year); + + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_date_get_type (); + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_value_get_date (ref GLib.Value val); + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_set_date (ref GLib.Value val, IntPtr date); + } + + public struct List { + private IList content; + + public static GLib.GType GType { + get { + return new GType (gst_value_list_get_type ()); + } + } + + public List (IList content) { + this.content = content; + } + + public List (GLib.Value val) { + this.content = new ArrayList (); + + uint n = gst_value_list_get_size (ref val); + for (uint i = 0; i < n; i++) { + IntPtr v_ptr = gst_value_list_get_value (ref val, i); + GLib.Value v = (GLib.Value) Marshal.PtrToStructure (v_ptr, typeof (GLib.Value)); + this.content.Add (Gst.Value.GetValue (v)); + } + } + + public static explicit operator GLib.Value (List l) { + GLib.Value val = new GLib.Value (List.GType); + + foreach (object o in l.content) { + GLib.Value v = Gst.Value.CreateValue (o); + gst_value_list_append_value (ref val, ref v); + } + + return val; + } + + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_value_list_get_type (); + [DllImport("gstreamer-0.10.dll")] + private static extern uint gst_value_list_get_size (ref GLib.Value val); + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_value_list_get_value (ref GLib.Value val, uint index); + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_list_append_value (ref GLib.Value val, ref GLib.Value el); + } + + public struct Array { + private IList content; + + public static GLib.GType GType { + get { + return new GType (gst_value_array_get_type ()); + } + } + + public Array (IList content) { + this.content = content; + } + + public Array (GLib.Value val) { + this.content = new ArrayList (); + + uint n = gst_value_array_get_size (ref val); + for (uint i = 0; i < n; i++) { + IntPtr v_ptr = gst_value_array_get_value (ref val, i); + GLib.Value v = (GLib.Value) Marshal.PtrToStructure (v_ptr, typeof (GLib.Value)); + this.content.Add (Gst.Value.GetValue (v)); + } + } + + public static explicit operator GLib.Value (Array a) { + GLib.Value val = new GLib.Value (Gst.Array.GType); + + foreach (object o in a.content) { + GLib.Value v = Gst.Value.CreateValue (o); + gst_value_array_append_value (ref val, ref v); + } + + return val; + } + + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_value_array_get_type (); + [DllImport("gstreamer-0.10.dll")] + private static extern uint gst_value_array_get_size (ref GLib.Value val); + [DllImport("gstreamer-0.10.dll")] + private static extern IntPtr gst_value_array_get_value (ref GLib.Value val, uint index); + [DllImport("gstreamer-0.10.dll")] + private static extern void gst_value_array_append_value (ref GLib.Value val, ref GLib.Value el); + } +} diff --git a/gstreamer-sharp/glue/Makefile.am b/gstreamer-sharp/glue/Makefile.am index 6321e17f8f..2d5fdbf529 100644 --- a/gstreamer-sharp/glue/Makefile.am +++ b/gstreamer-sharp/glue/Makefile.am @@ -6,8 +6,8 @@ libgstreamersharpglue_0_10_la_SOURCES = \ message.c \ miniobject.c \ bin.c \ - dynamicsignal.c \ - gerror.c + gerror.c \ + gobject.c nodist_libgstreamersharpglue_0_10_la_SOURCES = generated.c diff --git a/gstreamer-sharp/glue/dynamicsignal.c b/gstreamer-sharp/glue/gobject.c similarity index 71% rename from gstreamer-sharp/glue/dynamicsignal.c rename to gstreamer-sharp/glue/gobject.c index 61d2bdea5d..8dbaafa03f 100644 --- a/gstreamer-sharp/glue/dynamicsignal.c +++ b/gstreamer-sharp/glue/gobject.c @@ -11,3 +11,9 @@ gstsharp_g_type_from_instance (GTypeInstance * instance) { return G_TYPE_FROM_INSTANCE (instance); } + +GType +gstsharp_g_value_type (const GValue *val) { + return G_VALUE_TYPE (val); +} +