mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-19 16:21:17 +00:00
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:
parent
5c14766d47
commit
d09ded2065
8 changed files with 208 additions and 5 deletions
19
ChangeLog
19
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
112
gstreamer-sharp/DynamicSignalHandlerGenerator.cs
Normal file
112
gstreamer-sharp/DynamicSignalHandlerGenerator.cs
Normal 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");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
14
gstreamer-sharp/DynamicSignalMarshalHandler.cs
Normal file
14
gstreamer-sharp/DynamicSignalMarshalHandler.cs
Normal 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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -41,6 +41,8 @@ sources = \
|
|||
Version.cs \
|
||||
AssemblyInfo.cs \
|
||||
CommonTags.cs \
|
||||
DynamicSignalMarshalHandler.cs \
|
||||
DynamicSignalHandlerGenerator.cs \
|
||||
plugins-base/PlayBin.cs \
|
||||
plugins-base/DecodeBin.cs
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue