Custom Signal Handler for Element.cs

git-svn-id: svn://anonsvn.mono-project.com/source/branches/abock/gstreamer-sharp@61891 e3ebcda4-bce8-0310-ba0a-eca2169e7518
This commit is contained in:
Khaled Mohammed 2006-06-21 07:25:57 +00:00
parent 5c14766d47
commit d09ded2065
8 changed files with 208 additions and 5 deletions

View file

@ -1,9 +1,24 @@
2006-06-21 Khaled Mohammed <khaled.mohammed@gmail.com>
* gstreamer-sharp/DynamicSignalHandlerGenerator.cs: This class is
reponsible for generating a custom delegate class which supports
variable number of parameters.
* gstreamer-sharp/DyanmicSignalMarshalHandler.cs: This is an abstract
class and is derived by the new type generated by the Generator.
This class makes it easy for me to work with the new type.
* gstreamer-sharp/Element.custom: Added functions to add a custom signal,
a function which marshall's the signal parameters.
* sample/HelloWorld.cs: Added a sample to show the usuage of a custom signal.
2006-06-04 Khaled Mohammed <khaled.mohammed@gmail.com>
* gstreamer/glue/Bin.c: added this file to the source. It has only one
* gstreamer-sharp/glue/Bin.c: added this file to the source. It has only one
function which gives offset of *children in the C struct.
* gstreamer/glue/Makefile.am: added Bin.c to the list of C source that
* gstreamer-sharp/glue/Makefile.am: added Bin.c to the list of C source that
must be compiled.
* tests/ElementTest.cs: added NUnit tests for Element class.

View file

@ -23,6 +23,17 @@
}
}
[DllImport("gstreamer-0.10.dll")]
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);
bool ret = raw_ret;
return ret;
}
public bool AddMany(params Element[] elements)
{
if(elements == null) {
@ -37,3 +48,6 @@
return true;
}

View file

@ -0,0 +1,112 @@
//
// Authors
// Khaled Mohammed < Khaled.Mohammed@gmail.com >
//
// (C) 2006 Novell
//
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
namespace Gst {
public class DynamicSignalHandlerGenerator {
Type _NewType;
public Type NewType {
get { return _NewType; }
set { _NewType = value; }
}
public DynamicSignalHandlerGenerator(Type [] eventParams, string ASSEMBLY_NAME, string classname) {
// Define the parameters of marshall handler
Type [] paramTypes = new Type[eventParams.Length + 1];
for(int i=0; i < paramTypes.Length; i++)
paramTypes[i] = typeof(IntPtr);
Type [] paramBeginInvokeTypes = new Type[eventParams.Length + 2];
for(int i=0; i < paramBeginInvokeTypes.Length - 2 ; i++)
paramBeginInvokeTypes[i] = typeof(IntPtr);
paramBeginInvokeTypes[paramBeginInvokeTypes.Length - 2] = typeof(System.AsyncCallback);
paramBeginInvokeTypes[paramBeginInvokeTypes.Length - 1] = typeof(object);
// defining the assembly
AssemblyName dynamic_assembly_name = new AssemblyName();
dynamic_assembly_name.Name = ASSEMBLY_NAME;
AssemblyBuilder dynamic_assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
dynamic_assembly_name, AssemblyBuilderAccess.RunAndSave);
// create the dll file in the memory
ModuleBuilder dynamic_module = dynamic_assembly.DefineDynamicModule(ASSEMBLY_NAME, ASSEMBLY_NAME + ".dll");
TypeBuilder dynamic_class = dynamic_module.DefineType(ASSEMBLY_NAME + "." + classname, TypeAttributes.Public, typeof(Gst.DynamicSignalMarshalHandler));
MethodBuilder method_CSCB = dynamic_class.DefineMethod("CustomSignalCallback", MethodAttributes.Public | MethodAttributes.HideBySig, typeof(void), paramTypes );
ILGenerator method_IL = method_CSCB.GetILGenerator();
method_IL.Emit(OpCodes.Ldc_I4, paramTypes.Length);
method_IL.Emit(OpCodes.Newarr, typeof(IntPtr));
for(int i=0; i < paramTypes.Length; i++) {
method_IL.Emit(OpCodes.Dup);
method_IL.Emit(OpCodes.Ldc_I4, i);
method_IL.Emit(OpCodes.Ldelema, typeof(IntPtr));
method_IL.Emit(OpCodes.Ldarg, i+1);
method_IL.Emit(OpCodes.Stobj, typeof(IntPtr));
}
method_IL.Emit(OpCodes.Call, typeof(Gst.Element).GetMethod("CustomMarshaller"));
method_IL.Emit(OpCodes.Ret);
// define delegate
TypeBuilder tbDelegate = dynamic_class.DefineNestedType("CustomSignalDelegate", TypeAttributes.NestedPublic | TypeAttributes.Sealed, typeof(MulticastDelegate), null);
// CustomSignalDelegate()
ConstructorBuilder constructor = tbDelegate.DefineConstructor(MethodAttributes.Public | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig, CallingConventions.Standard, new Type [] { typeof(object), typeof(IntPtr) });
constructor.SetImplementationFlags (MethodImplAttributes.Runtime);
//constructor_IL = constructor.GetILGenerator();
//constructor_IL.Emit(OpCodes.Ret);
MethodBuilder method = tbDelegate.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig , typeof(void), paramTypes);
method.SetImplementationFlags (MethodImplAttributes.Runtime);
// .method public virtual hidebysig newslot
// instance default class [mscorlib]System.IAsyncResult BeginInvoke (native int arg0, native int arg1, native int gch, // class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed
method = tbDelegate.DefineMethod("BeginInvoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot, typeof(System.IAsyncResult), paramBeginInvokeTypes);
method.SetImplementationFlags(MethodImplAttributes.Runtime);
// .method public virtual hidebysig newslot
// instance default void EndInvoke (class [mscorlib]System.IAsyncResult result) runtime managed
method = tbDelegate.DefineMethod("EndInvoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, typeof(void), new Type [] { typeof(System.IAsyncResult) });
method.SetImplementationFlags(MethodImplAttributes.Runtime);
// .method public virtual hidebysig
// instance default class [mscorlib]System.Delegate Func () cil managed
method = dynamic_class.DefineMethod("Func", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig , typeof(Delegate), null);
method_IL = method.GetILGenerator();
method_IL.Emit(OpCodes.Ldarg_0);
method_IL.Emit(OpCodes.Ldftn, method_CSCB);
method_IL.Emit(OpCodes.Newobj, constructor);
method_IL.Emit(OpCodes.Ret);
_NewType = dynamic_class.CreateType();
dynamic_assembly.Save(ASSEMBLY_NAME + ".dll");
}
}
}

View file

@ -0,0 +1,14 @@
//
// Authors
// Khaled Mohammed < Khaled.Mohammed@gmail.com >
//
// (C) 2006 Novell
//
using System;
namespace Gst {
public abstract class DynamicSignalMarshalHandler {
public abstract Delegate Func();
}
}

View file

@ -42,3 +42,43 @@
{
return gst_element_query_duration(Handle, ref format, out duration);
}
static Type [] paramTypes;
public void AddCustomEvent(string name, Delegate onCustom ) {
System.Reflection.ParameterInfo [] pi = onCustom.Method.GetParameters();
paramTypes = new Type[pi.Length];
for(int i=0; i < paramTypes.Length; i++) {
paramTypes[i] = pi[i].ParameterType;
}
string DYNAMIC_ASSEMBLY = "Gst.DynamicSignals.Element." + Name + "." + name;
string DYNAMIC_CLASS = "NewDSMH";
DynamicSignalHandlerGenerator dshGenerator = new DynamicSignalHandlerGenerator(paramTypes, DYNAMIC_ASSEMBLY, DYNAMIC_CLASS);
Type NewType = System.Reflection.Assembly.LoadFile(DYNAMIC_ASSEMBLY + ".dll").GetType(DYNAMIC_ASSEMBLY + "." + DYNAMIC_CLASS);
DynamicSignalMarshalHandler dsmh = Activator.CreateInstance(NewType) as DynamicSignalMarshalHandler;
GLib.Signal sig = GLib.Signal.Lookup (this, name, dsmh.Func());
sig.AddDelegate(onCustom);
}
public static void CustomMarshaller(params IntPtr [] args) {
GLib.Signal sig = ((GCHandle) args[args.Length - 1]).Target as GLib.Signal;
object [] newargs = new object[args.Length - 1];
for(int i=0; i < newargs.Length; i++) {
if(paramTypes[i].IsSubclassOf(typeof(GLib.Object))) {
newargs[i] = GLib.Object.GetObject(args[i]);
}
else if(paramTypes[i].IsSubclassOf(typeof(GLib.Opaque))) {
newargs[i] = GLib.Opaque.GetOpaque(args[i], paramTypes[i], true);
}
}
Delegate d = sig.Handler as Delegate;
d.DynamicInvoke(newargs);
}

View file

@ -6,6 +6,8 @@
<attr path="/api/namespace/object[@name='Bin']/field[@name='Children']" name="hidden">1</attr>
<attr path="/api/namespace/object[@name='Bin']/method[@name='Add']" name="hidden">1</attr>
<attr path="/api/namespace/object[@name='Element']/signal[@name='NoMorePads']" name="name">HasNoMorePads</attr>
<!-- Hidden as the parameter name conflicts with generated code -->

View file

@ -41,6 +41,8 @@ sources = \
Version.cs \
AssemblyInfo.cs \
CommonTags.cs \
DynamicSignalMarshalHandler.cs \
DynamicSignalHandlerGenerator.cs \
plugins-base/PlayBin.cs \
plugins-base/DecodeBin.cs

View file

@ -1,4 +1,4 @@
TARGETS = playbin-player.exe decodebin-transcoder.exe
TARGETS = playbin-player.exe decodebin-transcoder.exe helloworld.exe
DEBUGS = $(addsuffix .mdb, $(TARGETS))
assemblies=$(top_builddir)/gstreamer-sharp/gstreamer-sharp.dll
@ -11,6 +11,9 @@ playbin-player.exe: $(srcdir)/PlayBinPlayer.cs $(assemblies)
decodebin-transcoder.exe: $(srcdir)/DecodeBinTranscoder.cs $(assemblies)
$(CSC) -out:$@ $(GLIBSHARP_LIBS) $(references) $(srcdir)/DecodeBinTranscoder.cs
helloworld.exe: $(srcdir)/HelloWorld.cs $(assemblies)
$(CSC) -out:$@ $(GLIBSHARP_LIBS) $(references) $(srcdir)/HelloWorld.cs
noinst_SCRIPTS = $(TARGETS)
CLEANFILES = $(TARGETS) $(DEBUGS)
@ -18,4 +21,5 @@ MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = \
PlayBinPlayer.cs \
DecodeBinTranscoder.cs
DecodeBinTranscoder.cs \
HelloWorld.cs