mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 21:16:24 +00:00
2006-07-12 Aaron Bockover <aaron@abock.org>
* sample/HelloWorld.cs: Cleaned up, works with new dynamic signal stuff * gstreamer-sharp.mdp: Updated MonoDevelop project * gstreamer-sharp/glue/dynamicsignal.c: * gstreamer-sharp/DynamicSignal.cs: Added DynamicSignal support for runtime GObject signal binding * gstreamer-sharp/glue/Makefile.am: * gstreamer-sharp/Makefile.am: Updated build * gstreamer-sharp/Element.custom: Removed old DynamicSignal stuff and added pass-thru/proxy Connect/Disconnect methods on top of GLib.DynamicSignal * gstreamer-sharp/DynamicSignalHandlerGenerator.cs: * gstreamer-sharp/DynamicSignalMarshalHandler.cs: Removed * gstreamer-sharp/gstreamer-sharp.dll.config.in: Updated maps, removed old 0.8 maps git-svn-id: svn://anonsvn.mono-project.com/source/branches/abock/gstreamer-sharp@62542 e3ebcda4-bce8-0310-ba0a-eca2169e7518
This commit is contained in:
parent
448405d86a
commit
0c76171b89
11 changed files with 466 additions and 282 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
2006-07-12 Aaron Bockover <aaron@abock.org>
|
||||
|
||||
* sample/HelloWorld.cs: Cleaned up, works with new dynamic signal stuff
|
||||
|
||||
* gstreamer-sharp.mdp: Updated MonoDevelop project
|
||||
|
||||
* gstreamer-sharp/glue/dynamicsignal.c:
|
||||
* gstreamer-sharp/DynamicSignal.cs: Added DynamicSignal support for
|
||||
runtime GObject signal binding
|
||||
|
||||
* gstreamer-sharp/glue/Makefile.am:
|
||||
* gstreamer-sharp/Makefile.am: Updated build
|
||||
|
||||
* gstreamer-sharp/Element.custom: Removed old DynamicSignal
|
||||
stuff and added pass-thru/proxy Connect/Disconnect methods on
|
||||
top of GLib.DynamicSignal
|
||||
|
||||
* gstreamer-sharp/DynamicSignalHandlerGenerator.cs:
|
||||
* gstreamer-sharp/DynamicSignalMarshalHandler.cs: Removed
|
||||
|
||||
* gstreamer-sharp/gstreamer-sharp.dll.config.in: Updated maps, removed
|
||||
old 0.8 maps
|
||||
|
||||
2006-07-12 Aaron Bockover <aaron@abock.org>
|
||||
|
||||
* gstreamer-sharp.mds:
|
||||
|
|
|
@ -39,8 +39,9 @@
|
|||
<File name="./gstreamer-sharp/plugins-base/DecodeBin.cs" subtype="Code" buildaction="Compile" />
|
||||
<File name="./sample/PlayBinPlayer.cs" subtype="Code" buildaction="Compile" />
|
||||
<File name="./sample/DecodeBinTranscoder.cs" subtype="Code" buildaction="Compile" />
|
||||
<File name="./gstreamer-sharp/DynamicSignalHandlerGenerator.cs" subtype="Code" buildaction="Compile" />
|
||||
<File name="./gstreamer-sharp/DynamicSignalMarshalHandler.cs" subtype="Code" buildaction="Compile" />
|
||||
<File name="./gstreamer-sharp/glue/dynamicsignal.c" subtype="Code" buildaction="Nothing" />
|
||||
<File name="./gstreamer-sharp/DynamicSignal.cs" subtype="Code" buildaction="Compile" />
|
||||
<File name="./sample/HelloWorld.cs" subtype="Code" buildaction="Compile" />
|
||||
</Contents>
|
||||
<References />
|
||||
</Project>
|
151
gstreamer-sharp/DynamicSignal.cs
Normal file
151
gstreamer-sharp/DynamicSignal.cs
Normal file
|
@ -0,0 +1,151 @@
|
|||
//
|
||||
// DynamicSignal.cs: C# bindings to g_dynamic_signal to provide
|
||||
// dynamic runtime signal binding for GObject
|
||||
//
|
||||
// Authors:
|
||||
// Aaron Bockover (abockover@novell.com)
|
||||
//
|
||||
// (C) 2006 Novell, Inc.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace GLib
|
||||
{
|
||||
public delegate void DynamicSignalHandler(object o, DynamicSignalArgs args);
|
||||
|
||||
public class DynamicSignalArgs : EventArgs
|
||||
{
|
||||
private GLib.Object sender;
|
||||
private object [] args;
|
||||
|
||||
internal DynamicSignalArgs(GLib.Object sender, object [] args)
|
||||
{
|
||||
this.sender = sender;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public object this[int index] {
|
||||
get { return Args[index]; }
|
||||
}
|
||||
|
||||
public GLib.Object Sender {
|
||||
get { return sender; }
|
||||
}
|
||||
|
||||
public object [] Args {
|
||||
get { return args; }
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
handler(gobject, new DynamicSignalArgs(gobject, args));
|
||||
}
|
||||
}
|
||||
|
||||
[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);
|
||||
|
||||
[DllImport("gstreamersharpglue-0.10")]
|
||||
private static extern IntPtr g_value_type(IntPtr value);
|
||||
|
||||
[DllImport("libgobject-2.0-0.dll")]
|
||||
private static extern IntPtr g_value_peek_pointer(IntPtr value);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
//
|
||||
// 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");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
//
|
||||
// Authors
|
||||
// Khaled Mohammed < Khaled.Mohammed@gmail.com >
|
||||
//
|
||||
// (C) 2006 Novell
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Gst {
|
||||
public abstract class DynamicSignalMarshalHandler {
|
||||
public abstract Delegate Func();
|
||||
}
|
||||
}
|
|
@ -43,48 +43,12 @@
|
|||
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();
|
||||
|
||||
Type [] paramTypes = new Type[pi.Length];
|
||||
for(int i=0; i < paramTypes.Length; i++) {
|
||||
paramTypes[i] = pi[i].ParameterType;
|
||||
public void Connect(string signal, GLib.DynamicSignalHandler handler)
|
||||
{
|
||||
GLib.DynamicSignal.Connect(this, signal, handler);
|
||||
}
|
||||
|
||||
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;
|
||||
Delegate d = sig.Handler as Delegate;
|
||||
System.Reflection.ParameterInfo [] pi = d.Method.GetParameters();
|
||||
|
||||
Type [] paramTypes = new Type[pi.Length];
|
||||
for(int i=0; i<pi.Length; i++)
|
||||
paramTypes[i] = pi[i].ParameterType;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
d.DynamicInvoke(newargs);
|
||||
public void Disconnect(string signal, GLib.DynamicSignalHandler handler)
|
||||
{
|
||||
GLib.DynamicSignal.Disconnect(this, signal, handler);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,12 +37,11 @@ clean-local:
|
|||
rm -rf generated
|
||||
|
||||
sources = \
|
||||
DynamicSignal.cs \
|
||||
Application.cs \
|
||||
Version.cs \
|
||||
AssemblyInfo.cs \
|
||||
CommonTags.cs \
|
||||
DynamicSignalMarshalHandler.cs \
|
||||
DynamicSignalHandlerGenerator.cs \
|
||||
plugins-base/PlayBin.cs \
|
||||
plugins-base/DecodeBin.cs
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
lib_LTLIBRARIES = libgstreamersharpglue-0.10.la
|
||||
|
||||
libgstreamersharpglue_0_10_la_SOURCES = \
|
||||
dynamicsignal.c \
|
||||
clock.c \
|
||||
message.c \
|
||||
miniobject.c \
|
||||
|
|
191
gstreamer-sharp/glue/dynamicsignal.c
Normal file
191
gstreamer-sharp/glue/dynamicsignal.c
Normal file
|
@ -0,0 +1,191 @@
|
|||
//
|
||||
// dynamicsignal.c: new method of registering GObject signal
|
||||
// handlers that uses a default signal handler to read
|
||||
// callback argument stack and convert to an array of
|
||||
// GValues before running the "generic" signal handler
|
||||
//
|
||||
// Authors:
|
||||
// Aaron Bockover (abockover@novell.com)
|
||||
//
|
||||
// (C) 2006 Novell, Inc.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
typedef void (* DynamicSignalHandler)(GObject *sender, guint argc,
|
||||
GValue *argv, gpointer userdata);
|
||||
|
||||
typedef struct {
|
||||
GObject *object;
|
||||
gpointer userdata;
|
||||
DynamicSignalHandler callback;
|
||||
|
||||
guint id;
|
||||
|
||||
guint g_signal_id;
|
||||
gulong handler_id;
|
||||
GSignalQuery signal_details;
|
||||
} DynamicSignalEntry;
|
||||
|
||||
static GList *dynamic_signal_table = NULL;
|
||||
static guint dynamic_signal_last_id = 1;
|
||||
|
||||
static DynamicSignalEntry *
|
||||
find_entry(GObject *object, guint signal_id)
|
||||
{
|
||||
GList *current = dynamic_signal_table;
|
||||
|
||||
while(current != NULL) {
|
||||
DynamicSignalEntry *entry = (DynamicSignalEntry *)current->data;
|
||||
if(entry->object == object && entry->g_signal_id == signal_id) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DynamicSignalEntry *
|
||||
find_entry_by_name(GObject *object, const gchar *signal_name, guint *signal_id_out)
|
||||
{
|
||||
guint signal_id;
|
||||
|
||||
signal_id = g_signal_lookup(signal_name, G_OBJECT_TYPE(object));
|
||||
if(signal_id_out != NULL) {
|
||||
*signal_id_out = signal_id;
|
||||
}
|
||||
|
||||
if(signal_id <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return find_entry(object, signal_id);
|
||||
}
|
||||
|
||||
static void
|
||||
free_entry(DynamicSignalEntry *entry)
|
||||
{
|
||||
memset(entry, 0, sizeof(DynamicSignalEntry));
|
||||
g_free(entry);
|
||||
}
|
||||
|
||||
static void
|
||||
dynamic_signal_handler(DynamicSignalEntry *entry, ...)
|
||||
{
|
||||
va_list argp;
|
||||
GValue *args = NULL;
|
||||
guint i, n;
|
||||
|
||||
if(entry == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
n = entry->signal_details.n_params;
|
||||
|
||||
if(n <= 0) {
|
||||
entry->callback(entry->object, 0, NULL, entry->userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
args = g_new0(GValue, n);
|
||||
va_start(argp, entry);
|
||||
|
||||
for(i = 0; i < n; i++) {
|
||||
GType type = entry->signal_details.param_types[i];
|
||||
GValue *value = &args[i];
|
||||
gchar *collect_error = NULL;
|
||||
|
||||
if(!G_TYPE_IS_CLASSED(type) && G_TYPE_IS_VALUE_TYPE(type) &&
|
||||
!G_TYPE_IS_FUNDAMENTAL(type) && G_TYPE_IS_DERIVED(type) &&
|
||||
G_TYPE_HAS_VALUE_TABLE(type)) {
|
||||
g_value_init(value, type);
|
||||
value->data[0].v_pointer = va_arg(argp, gpointer);
|
||||
} else {
|
||||
g_value_init(value, type);
|
||||
G_VALUE_COLLECT(value, argp, 0, &collect_error);
|
||||
}
|
||||
|
||||
if(collect_error != NULL) {
|
||||
g_warning("Could not collect value: %s", collect_error);
|
||||
g_free(collect_error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(argp);
|
||||
entry->callback(entry->object, n, args, entry->userdata);
|
||||
}
|
||||
|
||||
DynamicSignalEntry *
|
||||
g_dynamic_signal_find_registration(GObject *object, const gchar *signal_name)
|
||||
{
|
||||
return find_entry_by_name(object, signal_name, NULL);
|
||||
}
|
||||
|
||||
guint
|
||||
g_dynamic_signal_connect(GObject *object, const gchar *signal_name,
|
||||
DynamicSignalHandler callback, gboolean after, gpointer userdata)
|
||||
{
|
||||
DynamicSignalEntry *entry;
|
||||
guint signal_id;
|
||||
|
||||
entry = find_entry_by_name(object, signal_name, &signal_id);
|
||||
|
||||
if(entry != NULL) {
|
||||
return entry->id;
|
||||
}
|
||||
|
||||
entry = g_new0(DynamicSignalEntry, 1);
|
||||
entry->id = dynamic_signal_last_id++;
|
||||
entry->object = object;
|
||||
entry->g_signal_id = signal_id;
|
||||
entry->callback = callback;
|
||||
entry->userdata = userdata;
|
||||
g_signal_query(signal_id, &(entry->signal_details));
|
||||
|
||||
dynamic_signal_table = g_list_prepend(dynamic_signal_table, entry);
|
||||
|
||||
entry->handler_id = g_signal_connect_data(object, signal_name,
|
||||
G_CALLBACK(dynamic_signal_handler), entry, NULL,
|
||||
G_CONNECT_SWAPPED | (after ? G_CONNECT_AFTER : 0));
|
||||
|
||||
return entry->id;
|
||||
}
|
||||
|
||||
void
|
||||
g_dynamic_signal_disconnect(GObject *object, const gchar *signal_name)
|
||||
{
|
||||
DynamicSignalEntry *entry = find_entry_by_name(object, signal_name, NULL);
|
||||
|
||||
if(entry == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_signal_handler_disconnect(object, entry->handler_id);
|
||||
|
||||
dynamic_signal_table = g_list_remove(dynamic_signal_table, entry);
|
||||
free_entry(entry);
|
||||
|
||||
entry = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
g_dynamic_signal_update_entry_userdata(DynamicSignalEntry *entry, gpointer userdata)
|
||||
{
|
||||
if(entry != NULL) {
|
||||
entry->userdata = userdata;
|
||||
}
|
||||
}
|
||||
|
||||
GType g_value_type(GValue *value)
|
||||
{
|
||||
return G_VALUE_TYPE(value);
|
||||
}
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
<configuration>
|
||||
<dllmap dll="libglib-2.0-0.dll" target="libglib-2.0@LIB_PREFIX@.0@LIB_SUFFIX@"/>
|
||||
<dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0@LIB_PREFIX@.0@LIB_SUFFIX@"/>
|
||||
<dllmap dll="gstreamer-0.8" target="libgstreamer-0.8@LIB_PREFIX@.1@LIB_SUFFIX@"/>
|
||||
<dllmap dll="gstplay-0.8" target="libgstplay-0.8@LIB_PREFIX@.0@LIB_SUFFIX@"/>
|
||||
<dllmap dll="gstgconf-0.8" target="libgstgconf-0.8@LIB_PREFIX@.0@LIB_SUFFIX@"/>
|
||||
<dllmap dll="libglib-2.0-0.dll" target="libglib-2.0@LIB_PREFIX@.0@LIB_SUFFIX@"/>
|
||||
<dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0@LIB_PREFIX@.0@LIB_SUFFIX@"/>
|
||||
</configuration>
|
||||
|
|
|
@ -1,121 +1,104 @@
|
|||
using System;
|
||||
using Gst;
|
||||
using GLib;
|
||||
using System.Reflection;
|
||||
|
||||
public class HelloWorld {
|
||||
public class HelloWorld
|
||||
{
|
||||
private MainLoop loop;
|
||||
private Element pipeline, source, parser, decoder, conv, identity, sink;
|
||||
|
||||
public static void Main(string [] args)
|
||||
{
|
||||
new HelloWorld(args);
|
||||
}
|
||||
|
||||
MainLoop loop;
|
||||
Element pipeline, source, parser, decoder, conv, identity, sink;
|
||||
|
||||
bool BusCall(Bus bus, Message message) {
|
||||
|
||||
switch(message.Type) {
|
||||
case MessageType.Error:
|
||||
string err = String.Empty;
|
||||
message.ParseError(out err);
|
||||
Console.WriteLine ("Gstreamer error: {0}", err);
|
||||
loop.Quit();
|
||||
break;
|
||||
case MessageType.Eos:
|
||||
Console.WriteLine("End-of-stream");
|
||||
loop.Quit();
|
||||
break;
|
||||
default:
|
||||
//Console.WriteLine("Entered BusCall:\t" + message.Type);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public HelloWorld(string [] args)
|
||||
{
|
||||
Application.Init();
|
||||
|
||||
public static void Main(string [] args) {
|
||||
new HelloWorld(args);
|
||||
}
|
||||
loop = new MainLoop();
|
||||
|
||||
public HelloWorld(string [] args) {
|
||||
if((pipeline = new Pipeline("audio-player")) == null) {
|
||||
Console.WriteLine("Could not create audio player pipeline");
|
||||
}
|
||||
|
||||
if((source = ElementFactory.Make("filesrc", "file-source")) == null) {
|
||||
Console.WriteLine("Could not create file-source");
|
||||
}
|
||||
|
||||
parser = ElementFactory.Make("oggdemux", "ogg-parser");
|
||||
decoder = ElementFactory.Make("vorbisdec", "vorbis-decoder");
|
||||
conv = ElementFactory.Make("audioconvert", "converter");
|
||||
identity = ElementFactory.Make("identity", "identitye");
|
||||
sink = ElementFactory.Make("alsasink", "alsa-output");
|
||||
|
||||
source.SetProperty("location", args[0]);
|
||||
|
||||
Bin bin = (Bin) pipeline;
|
||||
bin.Bus.AddWatch(new BusFunc(BusCall));
|
||||
|
||||
// Initializes Gstreamer library
|
||||
Application.Init();
|
||||
bin.AddMany(source, parser, decoder, conv, identity, sink);
|
||||
|
||||
loop = new MainLoop();
|
||||
if(!source.Link(parser)) {
|
||||
Console.WriteLine("link failed between source and parser");
|
||||
}
|
||||
|
||||
if(!decoder.Link(conv)) {
|
||||
Console.WriteLine("link failed between decoder and converter");
|
||||
}
|
||||
|
||||
if(!conv.Link(identity)) {
|
||||
Console.WriteLine("link failed between converter and identity");
|
||||
}
|
||||
|
||||
if(!identity.Link(sink)) {
|
||||
Console.Error.WriteLine("link failed between identity and sink");
|
||||
}
|
||||
|
||||
parser.PadAdded += new PadAddedHandler(OnPadAdded);
|
||||
identity.Connect("handoff", OnHandoff);
|
||||
|
||||
// create elements
|
||||
if((pipeline = new Pipeline("audio-player")) == null)
|
||||
{
|
||||
Console.WriteLine("Could not create audio player pipeline");
|
||||
}
|
||||
|
||||
if((source = ElementFactory.Make("filesrc", "file-source")) == null)
|
||||
{
|
||||
Console.WriteLine("Could not create file-source");
|
||||
}
|
||||
|
||||
parser = ElementFactory.Make("oggdemux", "ogg-parser");
|
||||
decoder = ElementFactory.Make("vorbisdec", "vorbis-decoder");
|
||||
conv = ElementFactory.Make("audioconvert", "converter");
|
||||
identity = ElementFactory.Make("identity", "identitye");
|
||||
sink = ElementFactory.Make("alsasink", "alsa-output");
|
||||
|
||||
// set source to read the filename from command line argdument
|
||||
source.SetProperty("location", args[0]);
|
||||
|
||||
Bin bin = (Bin) pipeline;
|
||||
bin.Bus.AddWatch(new BusFunc(BusCall));
|
||||
pipeline.SetState(State.Playing);
|
||||
|
||||
bin.Add(source);
|
||||
bin.Add(parser);
|
||||
bin.Add(decoder);
|
||||
bin.Add(conv);
|
||||
bin.Add(identity);
|
||||
bin.Add(sink);
|
||||
Console.WriteLine("Playing [" + args[0] + "]");
|
||||
|
||||
loop.Run();
|
||||
|
||||
if(!source.Link(parser))
|
||||
Console.WriteLine("link failed");
|
||||
if(!decoder.Link(conv))
|
||||
Console.WriteLine("link failed between decoder and converter");
|
||||
if(!conv.Link(identity))
|
||||
Console.WriteLine("link failed between converter and identity");
|
||||
if(!identity.Link(sink))
|
||||
Console.Error.WriteLine("link failed between identity and sink");
|
||||
pipeline.SetState(State.Null);
|
||||
pipeline.Dispose();
|
||||
}
|
||||
|
||||
parser.PadAdded += new PadAddedHandler(OnPadAdded);
|
||||
private bool BusCall(Bus bus, Message message)
|
||||
{
|
||||
switch(message.Type) {
|
||||
case MessageType.Error:
|
||||
string err = String.Empty;
|
||||
message.ParseError(out err);
|
||||
Console.WriteLine ("Gstreamer error: {0}", err);
|
||||
loop.Quit();
|
||||
break;
|
||||
case MessageType.Eos:
|
||||
Console.WriteLine("End-of-stream");
|
||||
loop.Quit();
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Entered BusCall:\t{0}", message.Type);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.WriteLine("Adding custom event");
|
||||
|
||||
|
||||
identity.AddCustomEvent("handoff", new MyEventHandler(handoff));
|
||||
|
||||
pipeline.SetState(State.Playing);
|
||||
Console.WriteLine("Playing [" + args[0] + "]");
|
||||
|
||||
|
||||
loop.Run();
|
||||
|
||||
pipeline.SetState(State.Null);
|
||||
|
||||
pipeline.Dispose();
|
||||
}
|
||||
|
||||
delegate void MyEventHandler(object sender, Gst.Buffer buf);
|
||||
|
||||
ulong count = 0;
|
||||
|
||||
|
||||
void handoff(object i, Gst.Buffer buf) {
|
||||
Console.WriteLine(buf.Duration + "\t" + buf.Timestamp);
|
||||
/*
|
||||
ulong newcount = buf.Timestamp / buf.Duration * 20;
|
||||
if(newcount > count)
|
||||
{
|
||||
Console.Write("*");
|
||||
count = newcount;
|
||||
}
|
||||
*/
|
||||
}
|
||||
void OnPadAdded(object sender, PadAddedArgs e) {
|
||||
Console.WriteLine("Entered OnPadAdded");
|
||||
Pad sinkpad = decoder.GetPad("sink");
|
||||
e.Pad.Link(sinkpad);
|
||||
}
|
||||
private void OnHandoff(object o, DynamicSignalArgs args)
|
||||
{
|
||||
Gst.Buffer buffer = args[0] as Gst.Buffer;
|
||||
Console.WriteLine(buffer.Duration + "\t" + buffer.Timestamp);
|
||||
}
|
||||
|
||||
void OnPadAdded(object o, PadAddedArgs args)
|
||||
{
|
||||
Console.WriteLine("Entered OnPadAdded");
|
||||
Pad sinkpad = decoder.GetPad("sink");
|
||||
args.Pad.Link(sinkpad);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue