2009-05-20 15:29:36 +00:00
// MiniObject.cs - GstMiniObject class wrapper implementation
//
// Authors: Mike Kestner <mkestner@speakeasy.net>
// Sebastian Dröge <sebastian.droege@collabora.co.uk>
//
// Copyright (c) 2001-2003 Mike Kestner
// Copyright (c) 2004-2005 Novell, Inc.
// Copyright (c) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the Lesser GNU General
// Public License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// Based on Object.cs from Gtk# 2.8.3
// TODO: For managed types, install finalizer in ThresholdType
// and only destroy the managed instance if the native instance
// gets finalized => move managed instance to managed_tb_destroyed
// and unref, if finalizer is called remove it completely.
// For non-managed types handle as is.
namespace Gst {
using System ;
using System.Collections ;
using System.ComponentModel ;
using System.Reflection ;
using System.Runtime.InteropServices ;
using System.Text ;
2009-08-05 14:57:20 +00:00
using Gst.GLib ;
2009-05-20 15:29:36 +00:00
public class MiniObject : IWrapper , IDisposable {
[StructLayout (LayoutKind.Sequential) ]
struct GTypeClass {
public IntPtr gtype ;
}
[StructLayout (LayoutKind.Sequential) ]
struct GstMiniObjectClass {
GTypeClass parent ;
IntPtr copy ;
IntPtr finalize ;
IntPtr reserved ;
}
[StructLayout (LayoutKind.Sequential) ]
struct GTypeInstance {
public IntPtr g_class ;
}
[StructLayout (LayoutKind.Sequential) ]
struct GstMiniObject {
GTypeInstance parent ;
public int refcount ;
public Gst . MiniObjectFlags flags ;
IntPtr reserved ;
}
IntPtr handle ;
bool disposed = false ;
static Hashtable Objects = new Hashtable ( ) ;
~ MiniObject ( ) {
Dispose ( ) ;
}
2009-05-25 10:09:52 +00:00
[DllImport ("libgstreamer-0.10.dll") ]
2009-05-20 15:29:36 +00:00
static extern void gst_mini_object_unref ( IntPtr raw ) ;
public virtual void Dispose ( ) {
if ( disposed )
return ;
disposed = true ;
2009-05-22 08:56:24 +00:00
lock ( typeof ( MiniObject ) ) {
if ( handle ! = IntPtr . Zero ) {
Objects . Remove ( handle ) ;
try {
gst_mini_object_unref ( handle ) ;
} catch ( Exception e ) {
Console . WriteLine ( "Exception while disposing a " + this + " in Gtk#" ) ;
throw e ;
2009-05-20 15:29:36 +00:00
}
2009-05-22 08:56:24 +00:00
handle = IntPtr . Zero ;
2009-05-20 15:29:36 +00:00
}
}
GC . SuppressFinalize ( this ) ;
}
2009-05-25 10:09:52 +00:00
[DllImport ("libgstreamer-0.10.dll") ]
2009-05-20 15:29:36 +00:00
static extern IntPtr gst_mini_object_ref ( IntPtr raw ) ;
public static MiniObject GetObject ( IntPtr o , bool owned_ref ) {
if ( o = = IntPtr . Zero )
return null ;
MiniObject obj = null ;
2009-05-22 08:56:24 +00:00
lock ( typeof ( MiniObject ) ) {
WeakReference weak_ref = Objects [ o ] as WeakReference ;
2009-05-20 15:29:36 +00:00
2009-05-22 08:56:24 +00:00
if ( weak_ref ! = null & & weak_ref . IsAlive )
obj = weak_ref . Target as MiniObject ;
2009-05-20 15:29:36 +00:00
2009-05-22 08:56:24 +00:00
if ( obj = = null )
obj = Objects [ o ] as MiniObject ;
}
2009-05-20 15:29:36 +00:00
if ( obj ! = null & & obj . handle = = o ) {
if ( owned_ref )
gst_mini_object_unref ( obj . handle ) ;
obj . disposed = false ;
return obj ;
}
obj = CreateObject ( o ) ;
if ( obj = = null )
return null ;
if ( ! owned_ref )
gst_mini_object_ref ( obj . Handle ) ;
Objects [ o ] = new WeakReference ( obj ) ;
return obj ;
}
static BindingFlags flags = BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance | BindingFlags . CreateInstance ;
private static MiniObject CreateObject ( IntPtr raw ) {
if ( raw = = IntPtr . Zero )
return null ;
Type type = GetTypeOrParent ( raw ) ;
if ( type = = null )
return null ;
MiniObject obj ;
try {
obj = Activator . CreateInstance ( type , flags , null , new object [ ] { raw } , null ) as Gst . MiniObject ;
} catch ( MissingMethodException ) {
2009-08-05 14:57:20 +00:00
throw new Gst . GLib . MissingIntPtrCtorException ( "Gst.MiniObject subclass " + type + " must provide a protected or public IntPtr ctor to support wrapping of native object handles." ) ;
2009-05-20 15:29:36 +00:00
}
return obj ;
}
[DllImport ("gstreamersharpglue-0.10.dll") ]
static extern IntPtr gstsharp_g_type_from_instance ( IntPtr inst ) ;
static Type GetTypeOrParent ( IntPtr obj ) {
IntPtr typeid = gstsharp_g_type_from_instance ( obj ) ;
if ( typeid = = GType . Invalid . Val )
return null ;
Type result = GType . LookupType ( typeid ) ;
while ( result = = null ) {
typeid = g_type_parent ( typeid ) ;
if ( typeid = = IntPtr . Zero )
return null ;
result = GType . LookupType ( typeid ) ;
}
return result ;
}
[DllImport ("libgobject-2.0-0.dll") ]
static extern IntPtr g_type_parent ( IntPtr typ ) ;
public static MiniObject GetObject ( IntPtr o ) {
return GetObject ( o , false ) ;
}
private static void ConnectDefaultHandlers ( GType gtype , System . Type t ) {
foreach ( MethodInfo minfo in t . GetMethods ( BindingFlags . Instance | BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . DeclaredOnly ) ) {
MethodInfo baseinfo = minfo . GetBaseDefinition ( ) ;
if ( baseinfo = = minfo )
continue ;
foreach ( object attr in baseinfo . GetCustomAttributes ( typeof ( DefaultSignalHandlerAttribute ) , false ) ) {
DefaultSignalHandlerAttribute sigattr = attr as DefaultSignalHandlerAttribute ;
MethodInfo connector = sigattr . Type . GetMethod ( sigattr . ConnectionMethod , BindingFlags . Static | BindingFlags . NonPublic ) ;
object [ ] parms = new object [ 1 ] ;
parms [ 0 ] = gtype ;
connector . Invoke ( null , parms ) ;
break ;
}
}
}
private static void InvokeClassInitializers ( GType gtype , System . Type t ) {
object [ ] parms = { gtype , t } ;
BindingFlags flags = BindingFlags . Static | BindingFlags . NonPublic ;
foreach ( TypeInitializerAttribute tia in t . GetCustomAttributes ( typeof ( TypeInitializerAttribute ) , true ) ) {
MethodInfo m = tia . Type . GetMethod ( tia . MethodName , flags ) ;
if ( m ! = null )
m . Invoke ( null , parms ) ;
}
}
static Hashtable class_structs ;
2009-08-05 14:57:20 +00:00
static GstMiniObjectClass GetClassStruct ( Gst . GLib . GType gtype , bool use_cache ) {
2009-05-20 15:29:36 +00:00
if ( class_structs = = null )
class_structs = new Hashtable ( ) ;
if ( use_cache & & class_structs . Contains ( gtype ) )
return ( GstMiniObjectClass ) class_structs [ gtype ] ;
else {
2009-09-03 09:07:43 +00:00
IntPtr class_ptr = gtype . GetClassPtr ( ) ;
2009-05-20 15:29:36 +00:00
GstMiniObjectClass class_struct = ( GstMiniObjectClass ) Marshal . PtrToStructure ( class_ptr , typeof ( GstMiniObjectClass ) ) ;
if ( use_cache )
class_structs . Add ( gtype , class_struct ) ;
return class_struct ;
}
}
2009-08-05 14:57:20 +00:00
static void OverrideClassStruct ( Gst . GLib . GType gtype , GstMiniObjectClass class_struct ) {
2009-09-03 09:07:43 +00:00
IntPtr class_ptr = gtype . GetClassPtr ( ) ;
2009-05-20 15:29:36 +00:00
Marshal . StructureToPtr ( class_struct , class_ptr , false ) ;
}
static int type_uid ;
static string BuildEscapedName ( System . Type t ) {
string qn = t . FullName ;
// Just a random guess
StringBuilder sb = new StringBuilder ( 20 + qn . Length ) ;
sb . Append ( "__gtksharp_" ) ;
sb . Append ( type_uid + + ) ;
sb . Append ( "_" ) ;
foreach ( char c in qn ) {
if ( ( c > = '0' & & c < = '9' ) | | ( c > = 'a' & & c < = 'z' ) | | ( c > = 'A' & & c < = 'Z' ) )
sb . Append ( c ) ;
else if ( c = = '.' )
sb . Append ( '_' ) ;
else if ( ( uint ) c < = byte . MaxValue ) {
sb . Append ( '+' ) ;
sb . Append ( ( ( byte ) c ) . ToString ( "x2" ) ) ;
} else {
sb . Append ( '-' ) ;
sb . Append ( ( ( uint ) c ) . ToString ( "x4" ) ) ;
}
}
return sb . ToString ( ) ;
}
[StructLayout (LayoutKind.Sequential) ]
struct GTypeInfo {
public ushort class_size ;
IntPtr base_init ;
IntPtr base_finalize ;
IntPtr class_init ;
IntPtr class_finalize ;
IntPtr class_data ;
public ushort instance_size ;
ushort n_preallocs ;
IntPtr instance_init ;
IntPtr value_table ;
}
[StructLayout (LayoutKind.Sequential) ]
struct GTypeQuery {
public IntPtr type ;
public IntPtr type_name ;
public uint class_size ;
public uint instance_size ;
}
[DllImport ("libgobject-2.0-0.dll") ]
static extern void g_type_query ( IntPtr type , out GTypeQuery query ) ;
[DllImport ("libgobject-2.0-0.dll") ]
static extern IntPtr g_type_register_static ( IntPtr parent , IntPtr name , ref GTypeInfo info , int flags ) ;
private static GType RegisterGType ( System . Type t ) {
GType parent_gtype = LookupGType ( t . BaseType ) ;
string name = BuildEscapedName ( t ) ;
2009-08-05 14:57:20 +00:00
IntPtr native_name = Gst . GLib . Marshaller . StringToPtrGStrdup ( name ) ;
2009-05-20 15:29:36 +00:00
GTypeQuery query ;
g_type_query ( parent_gtype . Val , out query ) ;
GTypeInfo info = new GTypeInfo ( ) ;
info . class_size = ( ushort ) query . class_size ;
info . instance_size = ( ushort ) query . instance_size ;
GType gtype = new GType ( g_type_register_static ( parent_gtype . Val , native_name , ref info , 0 ) ) ;
2009-08-05 14:57:20 +00:00
Gst . GLib . Marshaller . Free ( native_name ) ;
2009-05-20 15:29:36 +00:00
2009-08-05 14:57:20 +00:00
Gst . GLib . GType . Register ( gtype , t ) ;
2009-05-20 15:29:36 +00:00
ConnectDefaultHandlers ( gtype , t ) ;
InvokeClassInitializers ( gtype , t ) ;
return gtype ;
}
[DllImport ("glibsharpglue-2") ]
static extern IntPtr gtksharp_register_type ( IntPtr name , IntPtr parent_type ) ;
protected GType LookupGType ( ) {
if ( Handle ! = IntPtr . Zero ) {
GTypeInstance obj = ( GTypeInstance ) Marshal . PtrToStructure ( Handle , typeof ( GTypeInstance ) ) ;
GTypeClass klass = ( GTypeClass ) Marshal . PtrToStructure ( obj . g_class , typeof ( GTypeClass ) ) ;
2009-08-05 14:57:20 +00:00
return new Gst . GLib . GType ( klass . gtype ) ;
2009-05-20 15:29:36 +00:00
} else {
return LookupGType ( GetType ( ) ) ;
}
}
protected internal static GType LookupGType ( System . Type t ) {
2009-05-22 08:56:24 +00:00
GType gtype = ( GType ) t ;
if ( gtype . ToString ( ) ! = "GtkSharpValue" )
return gtype ;
2009-05-20 15:29:36 +00:00
return RegisterGType ( t ) ;
}
protected MiniObject ( IntPtr raw ) {
Raw = raw ;
}
protected MiniObject ( ) {
CreateNativeObject ( ) ;
}
2009-05-25 10:09:52 +00:00
[DllImport ("libgstreamer-0.10.dll") ]
2009-05-20 15:29:36 +00:00
static extern IntPtr gst_mini_object_new ( IntPtr gtype ) ;
protected virtual void CreateNativeObject ( ) {
Raw = gst_mini_object_new ( LookupGType ( ) . Val ) ;
Objects [ handle ] = this ;
}
protected virtual IntPtr Raw {
get {
return handle ;
}
set {
if ( handle ! = IntPtr . Zero )
Objects . Remove ( handle ) ;
handle = value ;
if ( value = = IntPtr . Zero )
return ;
Objects [ value ] = new WeakReference ( this ) ;
}
}
2009-05-25 10:09:52 +00:00
[DllImport ("libgstreamer-0.10.dll") ]
2009-05-20 15:29:36 +00:00
static extern IntPtr gst_mini_object_get_type ( ) ;
2009-08-05 14:57:20 +00:00
public static Gst . GLib . GType GType {
2009-05-20 15:29:36 +00:00
get {
IntPtr raw_ret = gst_mini_object_get_type ( ) ;
2009-08-05 14:57:20 +00:00
Gst . GLib . GType ret = new Gst . GLib . GType ( raw_ret ) ;
2009-05-20 15:29:36 +00:00
return ret ;
}
}
protected string TypeName {
get {
return NativeType . ToString ( ) ;
}
}
2009-08-05 14:57:20 +00:00
internal Gst . GLib . GType NativeType {
2009-05-20 15:29:36 +00:00
get {
return LookupGType ( ) ;
}
}
public IntPtr Handle {
get {
return handle ;
}
}
public IntPtr OwnedHandle {
get {
return gst_mini_object_ref ( handle ) ;
}
}
public override int GetHashCode ( ) {
return Handle . GetHashCode ( ) ;
}
[DllImport ("libgobject-2.0-0.dll") ]
static extern bool g_type_check_instance_is_a ( IntPtr obj , IntPtr gtype ) ;
internal static bool IsMiniObject ( IntPtr obj ) {
return g_type_check_instance_is_a ( obj , MiniObject . GType . Val ) ;
}
internal int Refcount {
get {
GstMiniObject inst_struct = ( GstMiniObject ) Marshal . PtrToStructure ( Handle , typeof ( GstMiniObject ) ) ;
return inst_struct . refcount ;
}
}
public Gst . MiniObjectFlags Flags {
get {
GstMiniObject inst_struct = ( GstMiniObject ) Marshal . PtrToStructure ( Handle , typeof ( GstMiniObject ) ) ;
return inst_struct . flags ;
}
set {
GstMiniObject inst_struct = ( GstMiniObject ) Marshal . PtrToStructure ( Handle , typeof ( GstMiniObject ) ) ;
inst_struct . flags = value ;
}
}
2009-05-25 10:09:52 +00:00
[DllImport ("libgstreamer-0.10.dll") ]
2009-05-20 15:29:36 +00:00
static extern bool gst_mini_object_is_writable ( IntPtr raw ) ;
public bool IsWritable {
get {
bool raw_ret = gst_mini_object_is_writable ( Handle ) ;
bool ret = raw_ret ;
return ret ;
}
}
2009-05-25 10:09:52 +00:00
[DllImport ("libgstreamer-0.10.dll") ]
2009-08-05 14:57:20 +00:00
private static extern IntPtr gst_value_dup_mini_object ( ref Gst . GLib . Value v ) ;
2009-05-20 15:29:36 +00:00
2009-08-05 14:57:20 +00:00
public MiniObject ( Gst . GLib . Value val ) : base ( ) {
2009-05-20 15:29:36 +00:00
Raw = gst_value_dup_mini_object ( ref val ) ;
}
2009-05-25 10:09:52 +00:00
[DllImport ("libgstreamer-0.10.dll") ]
2009-08-05 14:57:20 +00:00
private static extern void gst_value_set_mini_object ( ref Gst . GLib . Value v , IntPtr o ) ;
2009-05-20 15:29:36 +00:00
2009-08-05 14:57:20 +00:00
public static explicit operator Gst . GLib . Value ( MiniObject o ) {
Gst . GLib . Value val = new Gst . GLib . Value ( o . LookupGType ( ) ) ;
2009-05-20 15:29:36 +00:00
gst_value_set_mini_object ( ref val , o . Handle ) ;
return val ;
}
2009-08-05 14:57:20 +00:00
public void SetGValue ( ref Gst . GLib . Value val ) {
2009-05-20 15:29:36 +00:00
gst_value_set_mini_object ( ref val , Handle ) ;
}
/* FIXME: This is not optimal */
public void MakeWritable ( ) {
if ( IsWritable )
return ;
IntPtr old = Handle ;
IntPtr copy = gst_mini_object_copy ( Handle ) ;
Raw = copy ;
gst_mini_object_unref ( old ) ;
}
2009-05-25 10:09:52 +00:00
[DllImport ("libgstreamer-0.10.dll") ]
2009-05-20 15:29:36 +00:00
static extern IntPtr gst_mini_object_copy ( IntPtr raw ) ;
public Gst . MiniObject Copy ( ) {
IntPtr raw_ret = gst_mini_object_copy ( Handle ) ;
return GetObject ( raw_ret , true ) ;
}
}
}