diff --git a/ChangeLog b/ChangeLog index ec9d69718f..ed1699638f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2006-08-03 Khaled Mohammed + * gstreamer-sharp/DynamicSignal.cs: Added the support for Retval. + Also changed the design to use only managed code. + + * gstreamer-sharp/plugins-base/*: Changed the code to use the new + DynamicSignal class. Got rid of DynamicSignalArgs and is using + GLib.SignalArgs. + 2006-07-13 Aaron Bockover * gstreamer-sharp/BindingHelper.cs: Static helper class to assist diff --git a/gstreamer-sharp/Bin.custom b/gstreamer-sharp/Bin.custom index 6c802af6b7..09c88dee95 100644 --- a/gstreamer-sharp/Bin.custom +++ b/gstreamer-sharp/Bin.custom @@ -27,9 +27,11 @@ static extern bool gst_bin_add(IntPtr raw, IntPtr element); public bool Add(Gst.Element element) { -// if(element !=null) -// element.Refcount++; bool raw_ret = gst_bin_add(Handle, element == null ? IntPtr.Zero : element.Handle); + if(raw_ret) { + // Incrmenting the refcount of the element. + Gst.Object.Ref(element.Handle); + } bool ret = raw_ret; return ret; } diff --git a/gstreamer-sharp/BindingHelper.cs b/gstreamer-sharp/BindingHelper.cs index 0fc660dfe8..a2af2634d1 100644 --- a/gstreamer-sharp/BindingHelper.cs +++ b/gstreamer-sharp/BindingHelper.cs @@ -37,10 +37,10 @@ namespace Gst } public static void InvokeProxySignalDelegate(Delegate raiseDelegate, Type type, - object o, GLib.DynamicSignalArgs args) + object o, GLib.SignalArgs args) { - if(!type.IsSubclassOf(typeof(GLib.DynamicSignalArgs))) { - throw new ArgumentException("Args type must derive DynamicSignalArgs"); + if(!type.IsSubclassOf(typeof(GLib.SignalArgs))) { + throw new ArgumentException("Args type must derive SignalArgs"); } if(raiseDelegate != null) { diff --git a/gstreamer-sharp/Clock.custom b/gstreamer-sharp/Clock.custom index e547ee8e2e..3905964418 100644 --- a/gstreamer-sharp/Clock.custom +++ b/gstreamer-sharp/Clock.custom @@ -1,30 +1,30 @@ - [DllImport("gstsharpglue-0.10")] + [DllImport("gstreamersharpglue-0.10")] private extern static ulong gstsharp_gst_clock_get_gst_second(); public static readonly ulong Second = gstsharp_gst_clock_get_gst_second(); - [DllImport("gstsharpglue-0.10")] + [DllImport("gstreamersharpglue-0.10")] private extern static ulong gstsharp_gst_clock_get_gst_msecond(); public static readonly ulong MSecond = gstsharp_gst_clock_get_gst_second(); - [DllImport("gstsharpglue-0.10")] + [DllImport("gstreamersharpglue-0.10")] private extern static ulong gstsharp_gst_clock_get_gst_usecond(); public static readonly ulong USecond = gstsharp_gst_clock_get_gst_second(); - [DllImport("gstsharpglue-0.10")] + [DllImport("gstreamersharpglue-0.10")] private extern static ulong gstsharp_gst_clock_get_gst_nsecond(); public static readonly ulong NSecond = gstsharp_gst_clock_get_gst_second(); - [DllImport("gstsharpglue-0.10")] - private extern static ulong gstsharp_gst_clock_get_clock_time_none(); + [DllImport("gstreamersharpglue-0.10")] + private extern static ulong gstsharp_gst_clock_get_time_none(); - public static readonly ulong TimeNone = gstsharp_gst_clock_get_clock_time_none(); + public static readonly ulong TimeNone = gstsharp_gst_clock_get_time_none(); - [DllImport("gstsharpglue-0.10")] + [DllImport("gstreamersharpglue-0.10")] private extern static bool gstsharp_gst_clock_time_is_valid(ulong time); public static bool TimeIsValid(ulong time) diff --git a/gstreamer-sharp/DynamicSignal.cs b/gstreamer-sharp/DynamicSignal.cs index 5a8c7f6a3e..101d869f26 100644 --- a/gstreamer-sharp/DynamicSignal.cs +++ b/gstreamer-sharp/DynamicSignal.cs @@ -1,160 +1,162 @@ // -// DynamicSignal.cs: C# bindings to g_dynamic_signal to provide -// dynamic runtime signal binding for GObject // -// Authors: -// Aaron Bockover (abockover@novell.com) +// (C) 2006 // -// (C) 2006 Novell, Inc. +// This class implements the functionalities to bind a callback +// function to a signal dynamically. +// // +using GLib; using System; using System.Runtime.InteropServices; +using System.Collections; -namespace GLib -{ - public delegate void DynamicSignalHandler(object o, DynamicSignalArgs args); - - public class DynamicSignalArgs : EventArgs - { - private GLib.Object sender; - private object [] args; +namespace GLib { + + public delegate void DynamicSignalHandler(object o, SignalArgs args); - public DynamicSignalArgs() - { - } - - public DynamicSignalArgs(DynamicSignalArgs args) - { - Sender = args.Sender; - Args = args.Args; - } + delegate void GClosureMarshal (IntPtr closure, ref GLib.Value retval, uint argc, IntPtr argsPtr, + IntPtr invocation_hint, IntPtr data); - public object this[int index] { - get { return Args[index]; } - } + public class DynamicSignal { + + private static readonly int gvalue_struct_size = Marshal.SizeOf(typeof(GLib.Value)); - public GLib.Object Sender { - get { return sender; } - internal set { sender = value; } - } - - public object [] Args { - get { return args; } - internal set { args = value; } - } - } + class Key { + object o; + string signal_name; - public static class DynamicSignal - { - private delegate void DynamicSignalNativeHandler(IntPtr objectPtr, uint argc, - IntPtr argsPtr, IntPtr userdata); - - private static DynamicSignalNativeHandler dynamic_signal_handler = - new DynamicSignalNativeHandler(OnDynamicSignalRaised); - - private static readonly int gvalue_struct_size = Marshal.SizeOf(typeof(GLib.Value)); - - public static void Connect(GLib.Object o, string name, DynamicSignalHandler handler) - { - Connect(o, name, false, handler); - } - - public static void Connect(GLib.Object o, string name, bool after, - DynamicSignalHandler handler) - { - IntPtr entry_ptr = FindRegisteredEntry(o, name); - if(entry_ptr == IntPtr.Zero) { - g_dynamic_signal_connect(o.Handle, name, dynamic_signal_handler, - after, (IntPtr)GCHandle.Alloc(handler)); - return; - } - - Delegate registered_handler = GetEntryHandler(entry_ptr); - if(registered_handler != null) { - Delegate new_handler = Delegate.Combine(registered_handler, handler); - if(new_handler != registered_handler) { - g_dynamic_signal_update_entry_userdata(entry_ptr, - (IntPtr)GCHandle.Alloc(new_handler)); - } - } - } - - public static void Disconnect(GLib.Object o, string name, DynamicSignalHandler handler) - { - IntPtr entry_ptr = FindRegisteredEntry(o, name); - if(entry_ptr == IntPtr.Zero) { - return; - } - - Delegate registered_handler = GetEntryHandler(entry_ptr); - Delegate new_handler = Delegate.Remove(registered_handler, handler); - if(new_handler == null || handler == null) { - g_dynamic_signal_disconnect(o.Handle, name); - return; - } else if(new_handler != null && registered_handler != new_handler) { - g_dynamic_signal_update_entry_userdata(entry_ptr, - (IntPtr)GCHandle.Alloc(new_handler)); - } - } - - private static IntPtr FindRegisteredEntry(GLib.Object o, string name) - { - return g_dynamic_signal_find_registration(o.Handle, name); - } - - private static DynamicSignalHandler GetEntryHandler(IntPtr entryPtr) - { - IntPtr handler_ptr = Marshal.ReadIntPtr(entryPtr, Marshal.SizeOf(typeof(IntPtr))); - return (DynamicSignalHandler)((GCHandle)handler_ptr).Target; - } - - private static void OnDynamicSignalRaised(IntPtr objectPtr, uint argc, - IntPtr argsPtr, IntPtr userdata) - { - GLib.Object gobject = GLib.Object.GetObject(objectPtr, false); - object [] args = new object[argc]; - - for(int i = 0; i < argc; i++) { - IntPtr struct_ptr = (IntPtr)((long)argsPtr + (i * gvalue_struct_size)); - GLib.Value argument = (GLib.Value)Marshal.PtrToStructure( - struct_ptr, typeof(GLib.Value)); - Type type = GType.LookupType(g_value_type(struct_ptr)); - - if(type.IsSubclassOf(typeof(GLib.Opaque))) { - args[i] = GLib.Opaque.GetOpaque(g_value_peek_pointer(struct_ptr), type, true); - } else { - args[i] = argument.Val; - } - } - - DynamicSignalHandler handler = (DynamicSignalHandler)((GCHandle)userdata).Target; - if(handler != null) { - DynamicSignalArgs dargs = new DynamicSignalArgs(); - dargs.Sender = gobject; - dargs.Args = args; - handler(gobject, dargs); - } - } + public Key (object o, string name) { + this.o = o; + signal_name = name; + } - [DllImport("gstreamersharpglue-0.10")] - private static extern uint g_dynamic_signal_connect(IntPtr o, string name, - DynamicSignalNativeHandler callback, bool swapped, IntPtr userdata); - - [DllImport("gstreamersharpglue-0.10")] - private static extern void g_dynamic_signal_disconnect(IntPtr o, string name); - - [DllImport("gstreamersharpglue-0.10")] - private static extern IntPtr g_dynamic_signal_find_registration(IntPtr o, string name); - - [DllImport("gstreamersharpglue-0.10")] - private static extern void g_dynamic_signal_update_entry_userdata(IntPtr entry, IntPtr userdata); + public override bool Equals(object o) { + if(o is Key) { + Key k = (Key) o; + return k.o.Equals(this.o) && signal_name.Equals(k.signal_name); + } + return base.Equals(o); + } - [DllImport("gstreamersharpglue-0.10")] - private static extern IntPtr g_value_type(IntPtr value); + public override int GetHashCode() { + return o.GetHashCode() ^ signal_name.GetHashCode(); + } + } - [DllImport("libgobject-2.0-0.dll")] - private static extern IntPtr g_value_peek_pointer(IntPtr value); - } + class SignalInfo { + uint handlerId; + IntPtr closure; + Delegate registeredHandler; + + public IntPtr Closure { + get { return closure; } + set { closure = value; } + } + + public uint HandlerId { + get { return handlerId; } + set { handlerId = value; } + } + + public Delegate RegisteredHandler { + get { return registeredHandler; } + set { registeredHandler = value; } + } + + public SignalInfo(uint handlerId, IntPtr closure, Delegate registeredHandler) { + this.handlerId = handlerId; + this.closure = closure; + this.registeredHandler = registeredHandler; + } + } + + static Hashtable SignalHandlers = new Hashtable(); + + static GClosureMarshal marshalHandler = new GClosureMarshal(OnMarshal); + + public static void Connect(GLib.Object o, string name, DynamicSignalHandler handler) { + Connect(o, name, false, handler); + } + + public static void Connect(GLib.Object o, string name, + bool after, DynamicSignalHandler handler) + { + Delegate newHandler; + + Key k = new Key(o, name); + + if(SignalHandlers[k] != null) { + SignalInfo si = (SignalInfo) SignalHandlers[k]; + newHandler = Delegate.Combine(si.RegisteredHandler, handler); + si.RegisteredHandler = newHandler; + } + else { + IntPtr closure = g_closure_new_simple(16, IntPtr.Zero); + g_closure_set_meta_marshal(closure, (IntPtr) GCHandle.Alloc(k), marshalHandler); + uint signalId = g_signal_connect_closure(o.Handle, name, closure, after); + SignalHandlers.Add(k, new SignalInfo(signalId, closure, handler)); + } + } + + + public static void Disconnect(GLib.Object o, string name, DynamicSignalHandler handler) { + Key k = new Key(o, name); + if(SignalHandlers[k] != null) + { + SignalInfo si = (SignalInfo) SignalHandlers[k]; + Delegate newHandler = Delegate.Remove(si.RegisteredHandler, handler); + if(newHandler == null || handler == null) { + g_signal_handler_disconnect(o.Handle, si.HandlerId); + SignalHandlers.Remove(k); + } else { + si.RegisteredHandler = newHandler; + } + } + } + + static void OnMarshal(IntPtr closure, ref GLib.Value retval, uint argc, IntPtr argsPtr, + IntPtr ihint, IntPtr data) + { + object [] args = new object[argc - 1]; + object o = ((GLib.Value) Marshal.PtrToStructure(argsPtr, typeof(GLib.Value))).Val; + + for(int i=1; i < argc; i++) { + IntPtr struct_ptr = (IntPtr)((long) argsPtr + (i * gvalue_struct_size)); + GLib.Value argument = (GLib.Value) Marshal.PtrToStructure(struct_ptr, typeof(GLib.Value)); + args[i - 1] = argument.Val; + } + + if(data == IntPtr.Zero) { + Console.Error.WriteLine("No available data"); + } + + Key k = (Key)((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); + if(arg.RetVal != null) { + retval.Val = arg.RetVal; + } + } + } + + + [DllImport("gobject-2.0.dll")] + static extern IntPtr g_closure_new_simple(int size, IntPtr data); + + [DllImport("gobject-2.0.dll")] + static extern uint g_signal_connect_closure(IntPtr instance, + string name, IntPtr closure, bool after); + + [DllImport("gobject-2.0.dll")] + static extern void g_closure_set_meta_marshal(IntPtr closure, IntPtr data, GClosureMarshal marshal); + + [DllImport("gobject-2.0.dll")] + static extern int g_signal_handler_disconnect(IntPtr o, uint handler_id); + } } - diff --git a/gstreamer-sharp/glue/Makefile.am b/gstreamer-sharp/glue/Makefile.am index 21f4488fb3..e8b6cc4d22 100644 --- a/gstreamer-sharp/glue/Makefile.am +++ b/gstreamer-sharp/glue/Makefile.am @@ -1,7 +1,6 @@ lib_LTLIBRARIES = libgstreamersharpglue-0.10.la libgstreamersharpglue_0_10_la_SOURCES = \ - dynamicsignal.c \ clock.c \ message.c \ miniobject.c \ diff --git a/gstreamer-sharp/glue/dynamicsignal.c b/gstreamer-sharp/glue/dynamicsignal.c index 76507b9903..b573a4fd94 100644 --- a/gstreamer-sharp/glue/dynamicsignal.c +++ b/gstreamer-sharp/glue/dynamicsignal.c @@ -20,9 +20,23 @@ typedef void (* DynamicSignalHandler)(GObject *sender, guint argc, GValue *argv, gpointer userdata); +//typedef gpointer (* DynamicSignalHandlerGPointer) (GObject *sender, guint argc, +// GValue *argv, gpointer userdata); + +//typedef gint64 (* DynamicSignalHandlerGint64) (GObject *sender, guint argc, GValue *argv, gpointer userdata); + typedef struct { GObject *object; gpointer userdata; + +/* + typedef union { + DynamicSignalHandler CBVoid; + DynamicSignalHandlerGPointer CBGPointer; + DynamicSignalHandlerGInt64 CBGInt64; + } + CallBack; +*/ DynamicSignalHandler callback; guint id; @@ -159,6 +173,7 @@ g_dynamic_signal_connect(GObject *object, const gchar *signal_name, return entry->id; } + void g_dynamic_signal_disconnect(GObject *object, const gchar *signal_name) { diff --git a/gstreamer-sharp/plugins-base/DecodeBin.cs b/gstreamer-sharp/plugins-base/DecodeBin.cs index 7face8d879..c9d6da5567 100644 --- a/gstreamer-sharp/plugins-base/DecodeBin.cs +++ b/gstreamer-sharp/plugins-base/DecodeBin.cs @@ -14,18 +14,18 @@ namespace Gst { public delegate void NewDecodedPadHandler(object o, NewDecodedPadArgs args); - public class NewDecodedPadArgs : GLib.DynamicSignalArgs + public class NewDecodedPadArgs : GLib.SignalArgs { - public NewDecodedPadArgs(GLib.DynamicSignalArgs args) : base(args) + public NewDecodedPadArgs(GLib.SignalArgs args) : base(args) { } public Gst.Pad Pad { - get { return (Gst.Pad)Args[0]; } + get { return (Gst.Pad)Args[1]; } } public bool Last { - get { return (bool)Args[1]; } + get { return (bool)Args[2]; } } } @@ -37,7 +37,7 @@ namespace Gst { } - protected virtual void OnNewDecodedPad(object o, GLib.DynamicSignalArgs args) + protected virtual void OnNewDecodedPad(object o, GLib.SignalArgs args) { BindingHelper.InvokeProxySignalDelegate(new_decoded_pad_delegate, typeof(NewDecodedPadArgs), o, args); diff --git a/gstreamer-sharp/plugins-base/TypeFindElement.cs b/gstreamer-sharp/plugins-base/TypeFindElement.cs index 38b6a6cb11..10b27b3fb1 100644 --- a/gstreamer-sharp/plugins-base/TypeFindElement.cs +++ b/gstreamer-sharp/plugins-base/TypeFindElement.cs @@ -13,18 +13,18 @@ namespace Gst { public delegate void HaveTypeHandler(object o, HaveTypeArgs args); - public class HaveTypeArgs : GLib.DynamicSignalArgs + public class HaveTypeArgs : GLib.SignalArgs { - public HaveTypeArgs(GLib.DynamicSignalArgs args) : base(args) + public HaveTypeArgs(GLib.SignalArgs args) : base(args) { } public uint Probability { - get { return (uint)Args[0]; } + get { return (uint)Args[1]; } } public Gst.Caps Caps { - get { return (Gst.Caps)Args[1]; } + get { return (Gst.Caps)Args[2]; } } } @@ -41,7 +41,7 @@ namespace Gst return ElementFactory.Make("typefind", name) as TypeFindElement; } - protected virtual void OnHaveType(object o, GLib.DynamicSignalArgs args) + protected virtual void OnHaveType(object o, GLib.SignalArgs args) { BindingHelper.InvokeProxySignalDelegate(have_type_delegate, typeof(HaveTypeArgs), o, args); } diff --git a/sample/HelloWorld.cs b/sample/HelloWorld.cs index 6f17dcbc33..8119fb4b41 100644 --- a/sample/HelloWorld.cs +++ b/sample/HelloWorld.cs @@ -86,9 +86,9 @@ public class HelloWorld return true; } - private void OnHandoff(object o, DynamicSignalArgs args) + private void OnHandoff(object o, SignalArgs args) { - Gst.Buffer buffer = args[0] as Gst.Buffer; + Gst.Buffer buffer = args.Args[0] as Gst.Buffer; Console.WriteLine(buffer.Duration + "\t" + buffer.Timestamp); } diff --git a/tests/Makefile.am b/tests/Makefile.am index d368b16af6..d8a75f3a84 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -3,7 +3,7 @@ NUNIT_FLAGS = @MONO_NUNIT_LIBS@ ASSEMBLY_NAME = gstreamer-tests ASSEMBLY = $(ASSEMBLY_NAME).dll -ASSEMBLY_CSFILES = $(srcdir)/ApplicationTest.cs $(srcdir)/BinTest.cs $(srcdir)/CapsTest.cs $(srcdir)/PadTest.cs $(srcdir)/ElementTest.cs +ASSEMBLY_CSFILES = $(srcdir)/ApplicationTest.cs $(srcdir)/BinTest.cs $(srcdir)/CapsTest.cs $(srcdir)/PadTest.cs $(srcdir)/ElementTest.cs $(srcdir)/PipelineTest.cs NUNIT_TESTER_NAME = ConsoleUi @@ -11,7 +11,7 @@ NUNIT_TESTER = $(NUNIT_TESTER_NAME).exe NUNIT_TESTER_CSFILES = $(srcdir)/$(NUNIT_TESTER_NAME).cs $(ASSEMBLY): $(ASSEMBLY_CSFILES) - $(CSC) $(MCS_FLAGS) $(NUNIT_FLAGS) -out:$@ -target:library -r:$(top_builddir)/gstreamer-sharp/gstreamer-sharp.dll $(ASSEMBLY_CSFILES) + $(CSC) $(MCS_FLAGS) $(NUNIT_FLAGS) -out:$@ -target:library -r:$(top_builddir)/gstreamer-sharp/gstreamer-sharp.dll $(ASSEMBLY_CSFILES) -r:glib-sharp-2.0 $(NUNIT_TESTER): $(NUNIT_TESTER_CSFILES) $(CSC) $(MCS_FLAGS) -out:$@ $(NUNIT_FLAGS) $(NUNIT_TESTER_CSFILES)