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:
Aaron Bockover 2006-07-12 22:47:30 +00:00
parent 448405d86a
commit 0c76171b89
11 changed files with 466 additions and 282 deletions

View file

@ -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:

View file

@ -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>

View 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);
}
}

View file

@ -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");
}
}
}

View file

@ -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();
}
}

View file

@ -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 void Disconnect(string signal, GLib.DynamicSignalHandler handler)
{
GLib.DynamicSignal.Disconnect(this, signal, handler);
}
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);
}

View file

@ -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

View file

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

View 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);
}

View file

@ -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@"/>
</configuration>

View file

@ -1,15 +1,75 @@
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;
MainLoop loop;
Element pipeline, source, parser, decoder, conv, identity, sink;
public static void Main(string [] args)
{
new HelloWorld(args);
}
bool BusCall(Bus bus, Message message) {
public HelloWorld(string [] args)
{
Application.Init();
loop = new MainLoop();
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));
bin.AddMany(source, parser, decoder, conv, identity, sink);
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);
pipeline.SetState(State.Playing);
Console.WriteLine("Playing [" + args[0] + "]");
loop.Run();
pipeline.SetState(State.Null);
pipeline.Dispose();
}
private bool BusCall(Bus bus, Message message)
{
switch(message.Type) {
case MessageType.Error:
string err = String.Empty;
@ -22,100 +82,23 @@ public class HelloWorld {
loop.Quit();
break;
default:
//Console.WriteLine("Entered BusCall:\t" + message.Type);
Console.WriteLine("Entered BusCall:\t{0}", message.Type);
break;
}
return true;
}
public static void Main(string [] args) {
new HelloWorld(args);
}
public HelloWorld(string [] args) {
// Initializes Gstreamer library
Application.Init();
loop = new MainLoop();
// create elements
if((pipeline = new Pipeline("audio-player")) == null)
private void OnHandoff(object o, DynamicSignalArgs args)
{
Console.WriteLine("Could not create audio player pipeline");
Gst.Buffer buffer = args[0] as Gst.Buffer;
Console.WriteLine(buffer.Duration + "\t" + buffer.Timestamp);
}
if((source = ElementFactory.Make("filesrc", "file-source")) == null)
void OnPadAdded(object o, PadAddedArgs args)
{
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));
bin.Add(source);
bin.Add(parser);
bin.Add(decoder);
bin.Add(conv);
bin.Add(identity);
bin.Add(sink);
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");
parser.PadAdded += new PadAddedHandler(OnPadAdded);
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);
args.Pad.Link(sinkpad);
}
}