diff options
-rw-r--r-- | elementgen/elementgen.cs | 12 | ||||
-rw-r--r-- | gstreamer-sharp/BindingHelper.cs | 50 | ||||
-rw-r--r-- | gstreamer-sharp/DynamicSignal.cs | 108 | ||||
-rw-r--r-- | gstreamer-sharp/Makefile.am | 1 | ||||
-rw-r--r-- | gstreamer-sharp/Object.custom | 12 | ||||
-rw-r--r-- | gstreamer-sharp/baseplugins/playbin.custom | 10 | ||||
-rw-r--r-- | samples/DecodeBinTranscoder.cs | 13 | ||||
-rw-r--r-- | samples/PlayBinPlayer.cs | 4 | ||||
-rw-r--r-- | samples/TypeFind.cs | 14 |
9 files changed, 126 insertions, 98 deletions
diff --git a/elementgen/elementgen.cs b/elementgen/elementgen.cs index d3e6139..c2e207b 100644 --- a/elementgen/elementgen.cs +++ b/elementgen/elementgen.cs @@ -255,7 +255,7 @@ public class ElementGen { string class_name = (ei.class_name != null) ? ei.class_name : ei.gtype_name.StartsWith ("Gst") ? ei.gtype_name.Substring (3) : ei.gtype_name; - writer.Write ("\tpublic class " + class_name + " : "); + writer.Write ("\tpublic sealed class " + class_name + " : "); for (int i = 1; i < ei.hierarchy.Count; i++) { string parent_type = (string) ei.hierarchy[i]; string parent_managed_type = CTypeToManagedType (parent_type, api_doc); @@ -349,19 +349,13 @@ public class ElementGen { } writer.WriteLine ("\t\t}\n"); - writer.WriteLine ("\t\tprivate Delegate " + managed_name + "_delegate;\n"); - - writer.WriteLine ("\t\tprotected virtual void On" + managed_name + " (object o, GLib.SignalArgs args) {"); - writer.WriteLine ("\t\t\tBindingHelper.InvokeProxySignalDelegate (" + managed_name + "_delegate, typeof (" + managed_name + "Args), o, args);"); - writer.WriteLine ("\t\t}\n"); - writer.WriteLine ("\t\tpublic event " + managed_name + "Handler " + managed_name + " {"); writer.WriteLine ("\t\t\tadd {"); - writer.WriteLine ("\t\t\t\t" + managed_name + "_delegate = BindingHelper.AddProxySignalDelegate (this, \"" + si.name + "\", On" + managed_name + ", " + managed_name + "_delegate, value);"); + writer.WriteLine ("\t\t\t\tDynamicSignal.Connect (this, \"" + si.name + "\", value);"); writer.WriteLine ("\t\t\t}\n"); writer.WriteLine ("\t\t\tremove {"); - writer.WriteLine ("\t\t\t\t" + managed_name + "_delegate = BindingHelper.RemoveProxySignalDelegate (this, \"" + si.name + "\", On" + managed_name + ", " + managed_name + "_delegate, value);"); + writer.WriteLine ("\t\t\t\tDynamicSignal.Disconnect (this, \"" + si.name + "\", value);"); writer.WriteLine ("\t\t\t}"); writer.WriteLine ("\t\t}"); } diff --git a/gstreamer-sharp/BindingHelper.cs b/gstreamer-sharp/BindingHelper.cs deleted file mode 100644 index dc4b544..0000000 --- a/gstreamer-sharp/BindingHelper.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// BindingHelper.cs: Utility methods to make creating -// element bindings by hand an easier task -// -// Authors: -// Aaron Bockover (abockover@novell.com) -// -// Copyright (C) 2006 Novell, Inc. -// - -using System; -using GLib; - -namespace Gst { - public static class BindingHelper { - public static Delegate AddProxySignalDelegate (GLib.Object o, string signal, - DynamicSignalHandler baseHandler, Delegate existingHandler, Delegate addHandler) { - if (existingHandler == null) { - DynamicSignal.Connect (o, signal, baseHandler); - } - - return Delegate.Combine (existingHandler, addHandler); - } - - public static Delegate RemoveProxySignalDelegate (GLib.Object o, string signal, - DynamicSignalHandler baseHandler, Delegate existingHandler, Delegate removeHandler) { - Delegate temp_delegate = Delegate.Remove (existingHandler, removeHandler); - if (temp_delegate == null) { - DynamicSignal.Disconnect (o, signal, baseHandler); - } - - return temp_delegate; - } - - public static void InvokeProxySignalDelegate (Delegate raiseDelegate, Type type, - object o, GLib.SignalArgs args) { - if (!type.IsSubclassOf (typeof (GLib.SignalArgs))) { - throw new ArgumentException ("Args type must derive SignalArgs"); - } - - if (raiseDelegate != null) { - GLib.SignalArgs new_args = (GLib.SignalArgs) Activator.CreateInstance (type); - new_args.RetVal = args.RetVal; - new_args.Args = args.Args; - - raiseDelegate.DynamicInvoke (new object [] { o, new_args }); - } - } - } -} diff --git a/gstreamer-sharp/DynamicSignal.cs b/gstreamer-sharp/DynamicSignal.cs index 1acd2a0..4e82cee 100644 --- a/gstreamer-sharp/DynamicSignal.cs +++ b/gstreamer-sharp/DynamicSignal.cs @@ -10,16 +10,17 @@ using GLib; using System; +using System.Reflection; using System.Runtime.InteropServices; using System.Collections; namespace Gst { - public delegate void DynamicSignalHandler (object o, SignalArgs args); - delegate void GClosureMarshal (IntPtr closure, ref GLib.Value retval, uint argc, IntPtr argsPtr, IntPtr invocation_hint, IntPtr data); + public delegate void SignalHandler (object o, SignalArgs args); + public static class DynamicSignal { private static readonly int gvalue_struct_size = Marshal.SizeOf (typeof (GLib.Value)); @@ -50,6 +51,7 @@ namespace Gst { uint handlerId; IntPtr closure; Delegate registeredHandler; + Type argsType; public IntPtr Closure { get { @@ -78,10 +80,79 @@ namespace Gst { } } + public Type ArgsType { + get { + return argsType; + } + set { + argsType = value; + } + } + public SignalInfo (uint handlerId, IntPtr closure, Delegate registeredHandler) { this.handlerId = handlerId; this.closure = closure; this.registeredHandler = registeredHandler; + + if (!IsValidDelegate (registeredHandler)) + throw new Exception ("Invalid delegate"); + + MethodInfo mi = registeredHandler.Method; + ParameterInfo[] parms = mi.GetParameters (); + this.argsType = parms[1].ParameterType; + } + + public void UpdateArgsType (Delegate d) { + if (!IsCompatibleDelegate (d)) + throw new Exception ("Incompatible delegate"); + + MethodInfo mi = d.Method; + ParameterInfo[] parms = mi.GetParameters (); + + Type t1 = parms[1].ParameterType; + Type t2 = argsType; + + if (t1 == t2) + return; + + if (t1.IsSubclassOf (t2)) + argsType = t1; + else if (t2.IsSubclassOf (t1)) + argsType = t2; + else + throw new Exception ("Incompatible delegate"); + } + + public bool IsCompatibleDelegate (Delegate d) { + if (!IsValidDelegate (d)) + return false; + + MethodInfo mi = d.Method; + ParameterInfo[] parms = mi.GetParameters (); + + if (parms[1].ParameterType != this.argsType && + !parms[1].ParameterType.IsSubclassOf (this.argsType) && + !this.argsType.IsSubclassOf (parms[1].ParameterType)) + return false; + + return true; + } + + public static bool IsValidDelegate (Delegate d) { + MethodInfo mi = d.Method; + + if (mi.ReturnType != typeof (void)) + return false; + + ParameterInfo[] parms = mi.GetParameters (); + if (parms.Length != 2) + return false; + + if (parms[1].ParameterType != typeof (GLib.SignalArgs) && + !parms[1].ParameterType.IsSubclassOf (typeof (GLib.SignalArgs))) + return false; + + return true; } } @@ -89,23 +160,42 @@ namespace Gst { static GClosureMarshal marshalHandler = new GClosureMarshal (OnMarshal); - public static void Connect (GLib.Object o, string name, DynamicSignalHandler handler) { + public static void Connect (GLib.Object o, string name, SignalHandler handler) { + Connect (o, name, false, (Delegate) handler); + } + + public static void Connect (GLib.Object o, string name, + bool after, SignalHandler handler) { + Connect (o, name, after, (Delegate) handler); + } + + public static void Connect (GLib.Object o, string name, Delegate handler) { Connect (o, name, false, handler); } static int g_closure_sizeof = gstsharp_g_closure_sizeof (); public static void Connect (GLib.Object o, string name, - bool after, DynamicSignalHandler handler) { + bool after, Delegate handler) { Delegate newHandler; ObjectSignalKey k = new ObjectSignalKey (o, name); + if (!SignalInfo.IsValidDelegate (handler)) + throw new Exception ("Invalid delegate"); + if (SignalHandlers[k] != null) { SignalInfo si = (SignalInfo) SignalHandlers[k]; + if (!si.IsCompatibleDelegate (handler)) + throw new Exception ("Incompatible delegate"); + newHandler = Delegate.Combine (si.RegisteredHandler, handler); + si.UpdateArgsType (handler); si.RegisteredHandler = newHandler; } else { + if (!SignalInfo.IsValidDelegate (handler)) + throw new Exception ("Invalid delegate"); + IntPtr closure = g_closure_new_simple (g_closure_sizeof, IntPtr.Zero); g_closure_set_meta_marshal (closure, (IntPtr) GCHandle.Alloc (k), marshalHandler); uint signalId = g_signal_connect_closure (o.Handle, name, closure, after); @@ -116,7 +206,7 @@ namespace Gst { [DllImport ("gstreamersharpglue-0.10.dll") ] static extern int gstsharp_g_closure_sizeof (); - public static void Disconnect (GLib.Object o, string name, DynamicSignalHandler handler) { + public static void Disconnect (GLib.Object o, string name, Delegate handler) { ObjectSignalKey k = new ObjectSignalKey (o, name); if (SignalHandlers[k] != null) { SignalInfo si = (SignalInfo) SignalHandlers[k]; @@ -143,15 +233,15 @@ namespace Gst { if (data == IntPtr.Zero) { Console.Error.WriteLine ("No available data"); + return; } ObjectSignalKey k = (ObjectSignalKey) ( (GCHandle) data).Target; if (k != null) { - SignalArgs arg = new SignalArgs(); - arg.Args = args; SignalInfo si = (SignalInfo) SignalHandlers[k]; - DynamicSignalHandler handler = (DynamicSignalHandler) si.RegisteredHandler; - handler (o, arg); + GLib.SignalArgs arg = (GLib.SignalArgs) Activator.CreateInstance (si.ArgsType); + arg.Args = args; + si.RegisteredHandler.DynamicInvoke (new object[] {o, arg}); if (arg.RetVal != null) { retval.Val = arg.RetVal; } diff --git a/gstreamer-sharp/Makefile.am b/gstreamer-sharp/Makefile.am index d43b1b0..9a978a1 100644 --- a/gstreamer-sharp/Makefile.am +++ b/gstreamer-sharp/Makefile.am @@ -38,7 +38,6 @@ clean-local: sources = \ DynamicSignal.cs \ - BindingHelper.cs \ Application.cs \ Version.cs \ AssemblyInfo.cs \ diff --git a/gstreamer-sharp/Object.custom b/gstreamer-sharp/Object.custom index 6af7057..afc2763 100644 --- a/gstreamer-sharp/Object.custom +++ b/gstreamer-sharp/Object.custom @@ -49,11 +49,19 @@ public PropertyInfo[] Properties { } } -public void Connect (string signal, DynamicSignalHandler handler) { +public void Connect (string signal, SignalHandler handler) { DynamicSignal.Connect (this, signal, handler); } -public void Disconnect (string signal, DynamicSignalHandler handler) { +public void Disconnect (string signal, SignalHandler handler) { + DynamicSignal.Disconnect (this, signal, handler); +} + +public void Connect (string signal, Delegate handler) { + DynamicSignal.Connect (this, signal, handler); +} + +public void Disconnect (string signal, Delegate handler) { DynamicSignal.Disconnect (this, signal, handler); } diff --git a/gstreamer-sharp/baseplugins/playbin.custom b/gstreamer-sharp/baseplugins/playbin.custom index 073e043..b212821 100644 --- a/gstreamer-sharp/baseplugins/playbin.custom +++ b/gstreamer-sharp/baseplugins/playbin.custom @@ -103,19 +103,13 @@ public class StreamInfo : GLib.Object { } - private Delegate Muted_delegate; - - protected virtual void OnMuted (object o, GLib.SignalArgs args) { - BindingHelper.InvokeProxySignalDelegate (Muted_delegate, typeof (MutedArgs), o, args); - } - public event MutedHandler Muted { add { - Muted_delegate = BindingHelper.AddProxySignalDelegate (this, "muted", OnMuted, Muted_delegate, value); + DynamicSignal.Connect (this, "muted", value); } remove { - Muted_delegate = BindingHelper.RemoveProxySignalDelegate (this, "muted", OnMuted, Muted_delegate, value); + DynamicSignal.Disconnect (this, "muted", value); } } diff --git a/samples/DecodeBinTranscoder.cs b/samples/DecodeBinTranscoder.cs index e9757c6..414cb36 100644 --- a/samples/DecodeBinTranscoder.cs +++ b/samples/DecodeBinTranscoder.cs @@ -9,6 +9,7 @@ using System; using Gst; +using Gst.CorePlugins; using Gst.BasePlugins; public delegate void ErrorHandler(object o, ErrorArgs args); @@ -28,8 +29,8 @@ public class ProgressArgs : EventArgs public class DecodeBinTranscoder : IDisposable { private Pipeline pipeline; - private Element filesrc; - private Element filesink; + private FileSrc filesrc; + private FileSink filesink; private Element audioconvert; private Element encoder; private DecodeBin decodebin; @@ -47,8 +48,8 @@ public class DecodeBinTranscoder : IDisposable public void Transcode(string inputFile, string outputFile) { - filesrc["location"] = inputFile; - filesink["location"] = outputFile; + filesrc.Location = inputFile; + filesink.Location = outputFile; pipeline.SetState(State.Playing); progress_timeout = GLib.Timeout.Add(250, OnProgressTimeout); @@ -92,8 +93,8 @@ public class DecodeBinTranscoder : IDisposable { pipeline = new Pipeline("pipeline"); - filesrc = ElementFactory.Make("filesrc", "filesrc"); - filesink = ElementFactory.Make("filesink", "filesink"); + filesrc = ElementFactory.Make("filesrc", "filesrc") as FileSrc; + filesink = ElementFactory.Make("filesink", "filesink") as FileSink; audioconvert = ElementFactory.Make("audioconvert", "audioconvert"); encoder = ElementFactory.Make("wavenc", "wavenc"); decodebin = ElementFactory.Make("decodebin", "decodebin") as DecodeBin; diff --git a/samples/PlayBinPlayer.cs b/samples/PlayBinPlayer.cs index daff707..88110f4 100644 --- a/samples/PlayBinPlayer.cs +++ b/samples/PlayBinPlayer.cs @@ -1,12 +1,8 @@ - using System; - using GLib; - using Gst; using Gst.BasePlugins; - public class PlayBinPlayer { private static MainLoop loop; diff --git a/samples/TypeFind.cs b/samples/TypeFind.cs index 8915fe2..af34678 100644 --- a/samples/TypeFind.cs +++ b/samples/TypeFind.cs @@ -11,11 +11,11 @@ public static class GstTypefindTest Application.Init(); Pipeline pipeline = new Pipeline("pipeline"); - Element source = ElementFactory.Make("filesrc", "source"); + FileSrc source = FileSrc.Make("source"); typefind = TypeFindElement.Make("typefind"); - Element sink = ElementFactory.Make("fakesink", "sink"); + FakeSink sink = FakeSink.Make("sink"); - source["location"] = args[0]; + source.Location = args[0]; typefind.HaveType += OnHaveType; @@ -26,16 +26,12 @@ public static class GstTypefindTest pipeline.SetState(State.Paused); pipeline.SetState(State.Null); - source.Dispose(); - typefind.Dispose(); - sink.Dispose(); pipeline.Dispose(); } - private static void OnHaveType(object o, GLib.SignalArgs args) + private static void OnHaveType(object o, TypeFindElement.HaveTypeArgs args) { - Caps caps = args.Args[1] as Caps; - Console.WriteLine("MimeType: {0}", caps); + Console.WriteLine("MimeType: {0}", args.Caps); } } |