Updated DynamicSignal.cs and files plugins-base to use the new

DynamicSignal class.


git-svn-id: svn://anonsvn.mono-project.com/source/branches/abock/gstreamer-sharp@63336 e3ebcda4-bce8-0310-ba0a-eca2169e7518
This commit is contained in:
Khaled Mohammed 2006-08-04 04:00:43 +00:00
parent 73ed037fa4
commit 0e15441c8c
11 changed files with 198 additions and 172 deletions

View file

@ -1,3 +1,11 @@
2006-08-03 Khaled Mohammed <khaled.mohammed@gmail.com>
* 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 <aaron@abock.org> 2006-07-13 Aaron Bockover <aaron@abock.org>
* gstreamer-sharp/BindingHelper.cs: Static helper class to assist * gstreamer-sharp/BindingHelper.cs: Static helper class to assist

View file

@ -27,9 +27,11 @@
static extern bool gst_bin_add(IntPtr raw, IntPtr element); static extern bool gst_bin_add(IntPtr raw, IntPtr element);
public bool Add(Gst.Element 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); 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; bool ret = raw_ret;
return ret; return ret;
} }

View file

@ -37,10 +37,10 @@ namespace Gst
} }
public static void InvokeProxySignalDelegate(Delegate raiseDelegate, Type type, public static void InvokeProxySignalDelegate(Delegate raiseDelegate, Type type,
object o, GLib.DynamicSignalArgs args) object o, GLib.SignalArgs args)
{ {
if(!type.IsSubclassOf(typeof(GLib.DynamicSignalArgs))) { if(!type.IsSubclassOf(typeof(GLib.SignalArgs))) {
throw new ArgumentException("Args type must derive DynamicSignalArgs"); throw new ArgumentException("Args type must derive SignalArgs");
} }
if(raiseDelegate != null) { if(raiseDelegate != null) {

View file

@ -1,30 +1,30 @@
[DllImport("gstsharpglue-0.10")] [DllImport("gstreamersharpglue-0.10")]
private extern static ulong gstsharp_gst_clock_get_gst_second(); private extern static ulong gstsharp_gst_clock_get_gst_second();
public static readonly ulong Second = 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(); private extern static ulong gstsharp_gst_clock_get_gst_msecond();
public static readonly ulong MSecond = gstsharp_gst_clock_get_gst_second(); 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(); private extern static ulong gstsharp_gst_clock_get_gst_usecond();
public static readonly ulong USecond = gstsharp_gst_clock_get_gst_second(); 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(); private extern static ulong gstsharp_gst_clock_get_gst_nsecond();
public static readonly ulong NSecond = gstsharp_gst_clock_get_gst_second(); public static readonly ulong NSecond = gstsharp_gst_clock_get_gst_second();
[DllImport("gstsharpglue-0.10")] [DllImport("gstreamersharpglue-0.10")]
private extern static ulong gstsharp_gst_clock_get_clock_time_none(); 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); private extern static bool gstsharp_gst_clock_time_is_valid(ulong time);
public static bool TimeIsValid(ulong time) public static bool TimeIsValid(ulong time)

View file

@ -1,160 +1,162 @@
// //
// DynamicSignal.cs: C# bindings to g_dynamic_signal to provide
// dynamic runtime signal binding for GObject
// //
// Authors: // (C) 2006
// Aaron Bockover (abockover@novell.com)
// //
// (C) 2006 Novell, Inc. // This class implements the functionalities to bind a callback
// function to a signal dynamically.
//
// //
using GLib;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Collections;
namespace GLib namespace GLib {
{
public delegate void DynamicSignalHandler(object o, DynamicSignalArgs args); public delegate void DynamicSignalHandler(object o, SignalArgs args);
public class DynamicSignalArgs : EventArgs
{
private GLib.Object sender;
private object [] args;
public DynamicSignalArgs() delegate void GClosureMarshal (IntPtr closure, ref GLib.Value retval, uint argc, IntPtr argsPtr,
{ IntPtr invocation_hint, IntPtr data);
}
public DynamicSignalArgs(DynamicSignalArgs args)
{
Sender = args.Sender;
Args = args.Args;
}
public object this[int index] { public class DynamicSignal {
get { return Args[index]; }
} private static readonly int gvalue_struct_size = Marshal.SizeOf(typeof(GLib.Value));
public GLib.Object Sender { class Key {
get { return sender; } object o;
internal set { sender = value; } string signal_name;
}
public object [] Args {
get { return args; }
internal set { args = value; }
}
}
public static class DynamicSignal public Key (object o, string name) {
{ this.o = o;
private delegate void DynamicSignalNativeHandler(IntPtr objectPtr, uint argc, signal_name = name;
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);
}
}
[DllImport("gstreamersharpglue-0.10")] public override bool Equals(object o) {
private static extern uint g_dynamic_signal_connect(IntPtr o, string name, if(o is Key) {
DynamicSignalNativeHandler callback, bool swapped, IntPtr userdata); Key k = (Key) o;
return k.o.Equals(this.o) && signal_name.Equals(k.signal_name);
[DllImport("gstreamersharpglue-0.10")] }
private static extern void g_dynamic_signal_disconnect(IntPtr o, string name); return base.Equals(o);
}
[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);
[DllImport("gstreamersharpglue-0.10")] public override int GetHashCode() {
private static extern IntPtr g_value_type(IntPtr value); return o.GetHashCode() ^ signal_name.GetHashCode();
}
}
[DllImport("libgobject-2.0-0.dll")] class SignalInfo {
private static extern IntPtr g_value_peek_pointer(IntPtr value); 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);
}
} }

View file

@ -1,7 +1,6 @@
lib_LTLIBRARIES = libgstreamersharpglue-0.10.la lib_LTLIBRARIES = libgstreamersharpglue-0.10.la
libgstreamersharpglue_0_10_la_SOURCES = \ libgstreamersharpglue_0_10_la_SOURCES = \
dynamicsignal.c \
clock.c \ clock.c \
message.c \ message.c \
miniobject.c \ miniobject.c \

View file

@ -20,9 +20,23 @@
typedef void (* DynamicSignalHandler)(GObject *sender, guint argc, typedef void (* DynamicSignalHandler)(GObject *sender, guint argc,
GValue *argv, gpointer userdata); 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 { typedef struct {
GObject *object; GObject *object;
gpointer userdata; gpointer userdata;
/*
typedef union {
DynamicSignalHandler CBVoid;
DynamicSignalHandlerGPointer CBGPointer;
DynamicSignalHandlerGInt64 CBGInt64;
}
CallBack;
*/
DynamicSignalHandler callback; DynamicSignalHandler callback;
guint id; guint id;
@ -159,6 +173,7 @@ g_dynamic_signal_connect(GObject *object, const gchar *signal_name,
return entry->id; return entry->id;
} }
void void
g_dynamic_signal_disconnect(GObject *object, const gchar *signal_name) g_dynamic_signal_disconnect(GObject *object, const gchar *signal_name)
{ {

View file

@ -14,18 +14,18 @@ namespace Gst
{ {
public delegate void NewDecodedPadHandler(object o, NewDecodedPadArgs args); 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 { public Gst.Pad Pad {
get { return (Gst.Pad)Args[0]; } get { return (Gst.Pad)Args[1]; }
} }
public bool Last { 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, BindingHelper.InvokeProxySignalDelegate(new_decoded_pad_delegate,
typeof(NewDecodedPadArgs), o, args); typeof(NewDecodedPadArgs), o, args);

View file

@ -13,18 +13,18 @@ namespace Gst
{ {
public delegate void HaveTypeHandler(object o, HaveTypeArgs args); 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 { public uint Probability {
get { return (uint)Args[0]; } get { return (uint)Args[1]; }
} }
public Gst.Caps Caps { 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; 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); BindingHelper.InvokeProxySignalDelegate(have_type_delegate, typeof(HaveTypeArgs), o, args);
} }

View file

@ -86,9 +86,9 @@ public class HelloWorld
return true; 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); Console.WriteLine(buffer.Duration + "\t" + buffer.Timestamp);
} }

View file

@ -3,7 +3,7 @@ NUNIT_FLAGS = @MONO_NUNIT_LIBS@
ASSEMBLY_NAME = gstreamer-tests ASSEMBLY_NAME = gstreamer-tests
ASSEMBLY = $(ASSEMBLY_NAME).dll 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 NUNIT_TESTER_NAME = ConsoleUi
@ -11,7 +11,7 @@ NUNIT_TESTER = $(NUNIT_TESTER_NAME).exe
NUNIT_TESTER_CSFILES = $(srcdir)/$(NUNIT_TESTER_NAME).cs NUNIT_TESTER_CSFILES = $(srcdir)/$(NUNIT_TESTER_NAME).cs
$(ASSEMBLY): $(ASSEMBLY_CSFILES) $(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) $(NUNIT_TESTER): $(NUNIT_TESTER_CSFILES)
$(CSC) $(MCS_FLAGS) -out:$@ $(NUNIT_FLAGS) $(NUNIT_TESTER_CSFILES) $(CSC) $(MCS_FLAGS) -out:$@ $(NUNIT_FLAGS) $(NUNIT_TESTER_CSFILES)