mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-19 22:05:58 +00:00
Don't allow subclassing of element bindings
...and clean up/simplify the DynamicSignal stuff.
This commit is contained in:
parent
0196d9b622
commit
8ece992223
9 changed files with 126 additions and 98 deletions
|
@ -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}");
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ clean-local:
|
|||
|
||||
sources = \
|
||||
DynamicSignal.cs \
|
||||
BindingHelper.cs \
|
||||
Application.cs \
|
||||
Version.cs \
|
||||
AssemblyInfo.cs \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
|
||||
using System;
|
||||
|
||||
using GLib;
|
||||
|
||||
using Gst;
|
||||
using Gst.BasePlugins;
|
||||
|
||||
|
||||
public class PlayBinPlayer
|
||||
{
|
||||
private static MainLoop loop;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue