grim/guifications3
Clone
Summary
Browse
Changes
Graph
moved gflib-gtk to the new cmake module
cmake
2010-12-15, Gary Kramlich
b6418db658c1
moved gflib-gtk to the new cmake module
/*
* Guifications - The end-all, be-all notification framework
* Copyright (C) 2003-2009 Gary Kramlich <grim@reaperworld.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
#
include
<config.h>
#endif
/* HAVE_CONFIG_H */
#include
<gflib/gf_native_plugin.h>
#include
<stdlib.h>
#include
<gmodule.h>
#include
<gflib/gf_intl.h>
#include
<gflib/gf_log.h>
#define GF_NATIVE_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), GF_TYPE_NATIVE_PLUGIN, GfNativePluginPriv))
/******************************************************************************
* Structs
*****************************************************************************/
typedef
struct
_GfNativePluginPriv
GfNativePluginPriv
;
typedef
struct
_GfNativePluginTypeInfo
GfNativePluginTypeInfo
;
typedef
struct
_GfNativePluginInterfaceInfo
GfNativePluginInterfaceInfo
;
struct
_GfNativePluginPriv
{
GModule
*
module
;
guint
use_count
;
GSList
*
type_infos
;
GSList
*
interface_infos
;
};
struct
_GfNativePluginTypeInfo
{
gboolean
loaded
;
GType
type
;
GType
parent
;
GTypeInfo
info
;
};
struct
_GfNativePluginInterfaceInfo
{
gboolean
loaded
;
GType
instance_type
;
GType
interface_type
;
GInterfaceInfo
info
;
};
/******************************************************************************
* Enums
*****************************************************************************/
enum
{
PROP_ZERO
,
PROP_MODULE
,
PROP_LAST
,
};
/******************************************************************************
* Functions
*****************************************************************************/
typedef
gboolean
(
*
GfNativePluginLoadFunc
)(
GfNativePlugin
*
);
typedef
gboolean
(
*
GfNativePluginUnloadFunc
)(
GfNativePlugin
*
);
/******************************************************************************
* Globals
*****************************************************************************/
static
GObjectClass
*
parent_class
=
NULL
;
/******************************************************************************
* Helpers
*****************************************************************************/
static
GfNativePluginTypeInfo
*
gf_native_plugin_find_type_info
(
GfNativePlugin
*
plugin
,
GType
type
)
{
GfNativePluginPriv
*
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
plugin
);
GSList
*
l
=
NULL
;
for
(
l
=
priv
->
type_infos
;
l
;
l
=
l
->
next
)
{
GfNativePluginTypeInfo
*
info
=
(
GfNativePluginTypeInfo
*
)(
l
->
data
);
if
(
info
->
type
==
type
)
return
info
;
}
return
NULL
;
}
static
GfNativePluginInterfaceInfo
*
gf_native_plugin_find_interface_info
(
GfNativePlugin
*
plugin
,
GType
instance_type
,
GType
interface_type
)
{
GfNativePluginPriv
*
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
plugin
);
GSList
*
l
=
NULL
;
for
(
l
=
priv
->
interface_infos
;
l
;
l
=
l
->
next
)
{
GfNativePluginInterfaceInfo
*
info
=
(
GfNativePluginInterfaceInfo
*
)(
l
->
data
);
if
(
info
->
instance_type
==
instance_type
&&
info
->
interface_type
==
interface_type
)
{
return
info
;
}
}
return
NULL
;
}
/******************************************************************************
* Interface Stuff
*****************************************************************************/
static
void
gf_native_plugin_priv_use
(
GTypePlugin
*
plugin
)
{
GfNativePlugin
*
native
=
GF_NATIVE_PLUGIN
(
plugin
);
if
(
!
gf_native_plugin_use
(
native
))
{
GfPluginInfo
*
info
=
gf_plugin_get_info
(
GF_PLUGIN
(
native
));
const
gchar
*
name
=
(
info
)
?
info
->
name
:
"(unknown)"
;
gf_log_critical
(
"GfNativePlugin"
,
"Fatal error - Could not reload previously loaded "
"plugin '%s'
\n
"
,
name
);
}
}
static
void
gf_native_plugin_complete_type_info
(
GTypePlugin
*
plugin
,
GType
type
,
GTypeInfo
*
info
,
GTypeValueTable
*
value_table
)
{
GfNativePlugin
*
native
=
GF_NATIVE_PLUGIN
(
plugin
);
GfNativePluginTypeInfo
*
native_info
=
gf_native_plugin_find_type_info
(
native
,
type
);
*
info
=
native_info
->
info
;
if
(
native_info
->
info
.
value_table
)
*
value_table
=
*
native_info
->
info
.
value_table
;
}
static
void
gf_native_plugin_complete_interface_info
(
GTypePlugin
*
plugin
,
GType
instance_type
,
GType
interface_type
,
GInterfaceInfo
*
info
)
{
GfNativePlugin
*
native
=
GF_NATIVE_PLUGIN
(
plugin
);
GfNativePluginInterfaceInfo
*
iface_info
=
gf_native_plugin_find_interface_info
(
native
,
instance_type
,
interface_type
);
*
info
=
iface_info
->
info
;
}
static
void
gf_native_plugin_iface_init
(
GTypePluginClass
*
iface
)
{
iface
->
use_plugin
=
gf_native_plugin_priv_use
;
iface
->
unuse_plugin
=
(
void
(
*
)(
GTypePlugin
*
))
gf_native_plugin_unuse
;
iface
->
complete_type_info
=
gf_native_plugin_complete_type_info
;
iface
->
complete_interface_info
=
gf_native_plugin_complete_interface_info
;
}
/******************************************************************************
* Object Stuff
*****************************************************************************/
static
void
gf_native_plugin_get_property
(
GObject
*
obj
,
guint
param_id
,
GValue
*
value
,
GParamSpec
*
psec
)
{
GfNativePluginPriv
*
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
obj
);
switch
(
param_id
)
{
case
PROP_MODULE
:
g_value_set_pointer
(
value
,
priv
->
module
);
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
psec
);
break
;
}
}
static
void
gf_native_plugin_set_property
(
GObject
*
obj
,
guint
param_id
,
const
GValue
*
value
,
GParamSpec
*
psec
)
{
GfNativePluginPriv
*
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
obj
);
switch
(
param_id
)
{
case
PROP_MODULE
:
priv
->
module
=
g_value_get_pointer
(
value
);
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
psec
);
break
;
}
}
static
void
gf_native_plugin_finalize
(
GObject
*
obj
)
{
GfNativePluginPriv
*
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
obj
);
g_slist_free
(
priv
->
type_infos
);
g_slist_free
(
priv
->
interface_infos
);
G_OBJECT_CLASS
(
parent_class
)
->
finalize
(
obj
);
}
static
void
gf_native_plugin_class_init
(
GfNativePluginClass
*
klass
)
{
GObjectClass
*
obj_class
=
G_OBJECT_CLASS
(
klass
);
parent_class
=
g_type_class_peek_parent
(
klass
);
g_type_class_add_private
(
klass
,
sizeof
(
GfNativePluginPriv
));
obj_class
->
finalize
=
gf_native_plugin_finalize
;
obj_class
->
get_property
=
gf_native_plugin_get_property
;
obj_class
->
set_property
=
gf_native_plugin_set_property
;
g_object_class_install_property
(
obj_class
,
PROP_MODULE
,
g_param_spec_pointer
(
"module"
,
P_
(
"The GModule"
),
P_
(
"The GModule for this plugin."
),
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY
));
}
/******************************************************************************
* API
*****************************************************************************/
GType
gf_native_plugin_get_type
(
void
)
{
static
GType
type
=
0
;
if
(
type
==
0
)
{
static
const
GTypeInfo
info
=
{
sizeof
(
GfNativePluginClass
),
NULL
,
NULL
,
(
GClassInitFunc
)
gf_native_plugin_class_init
,
NULL
,
NULL
,
sizeof
(
GfNativePlugin
),
0
,
NULL
,
};
static
const
GInterfaceInfo
iface_info
=
{
(
GInterfaceInitFunc
)
gf_native_plugin_iface_init
,
NULL
,
NULL
};
type
=
g_type_register_static
(
GF_TYPE_PLUGIN
,
"GfNativePlugin"
,
&
info
,
0
);
g_type_add_interface_static
(
type
,
G_TYPE_TYPE_PLUGIN
,
&
iface_info
);
}
return
type
;
}
/**
* gf_native_plugin_use:
* @plugin: a #GfNativePlugin
*
* Calls the @use_plugin function from the #GfNativePluginClass of @plugin.
* There should be no need to use this function outside of the GObject type
* system itself.
*
* Return Value: TRUE if successful, FALSE otherwise.
*/
gboolean
gf_native_plugin_use
(
GfNativePlugin
*
plugin
)
{
GfNativePluginPriv
*
priv
=
NULL
;
g_return_val_if_fail
(
GF_IS_NATIVE_PLUGIN
(
plugin
),
FALSE
);
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
plugin
);
priv
->
use_count
++
;
if
(
priv
->
use_count
==
1
)
{
GfNativePluginLoadFunc
load
=
NULL
;
GSList
*
l
=
NULL
;
gpointer
func
=
NULL
;
if
(
!
g_module_symbol
(
priv
->
module
,
"gf_native_plugin_load"
,
&
func
))
{
priv
->
use_count
--
;
return
FALSE
;
}
load
=
(
GfNativePluginLoadFunc
)
func
;
if
(
!
(
load
&&
load
(
plugin
)))
{
priv
->
use_count
--
;
return
FALSE
;
}
for
(
l
=
priv
->
type_infos
;
l
;
l
=
l
->
next
)
{
GfNativePluginTypeInfo
*
info
=
(
GfNativePluginTypeInfo
*
)(
l
->
data
);
if
(
!
info
->
loaded
)
{
GfPluginInfo
*
plugin_info
=
gf_plugin_get_info
(
GF_PLUGIN
(
plugin
));
const
gchar
*
name
=
(
plugin_info
)
?
plugin_info
->
name
:
"(unknown)"
;
gf_log_warning
(
"GfNativePlugin"
,
"plugin '%s' failed to register type '%s'
\n
"
,
name
,
g_type_name
(
info
->
type
));
return
FALSE
;
}
}
}
return
TRUE
;
}
/**
* gf_native_plugin_unuse:
* @plugin: a #GfNativePlugin
*
* Calls the @unuse_plugin function from the #GfNativePluginClass of @plugin.
* There should be no need to use this function outside of the GObject type
* system itself.
*
* Return Value: TRUE on success, FALSE otherwise.
*/
gboolean
gf_native_plugin_unuse
(
GfNativePlugin
*
plugin
)
{
GfNativePluginPriv
*
priv
=
NULL
;
g_return_val_if_fail
(
GF_IS_NATIVE_PLUGIN
(
plugin
),
FALSE
);
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
plugin
);
g_return_val_if_fail
(
priv
->
use_count
>
0
,
FALSE
);
priv
->
use_count
--
;
if
(
priv
->
use_count
==
0
)
{
GfNativePluginUnloadFunc
unload
=
NULL
;
GSList
*
l
=
NULL
;
gpointer
func
=
NULL
;
if
(
!
g_module_symbol
(
priv
->
module
,
"gf_native_plugin_unload"
,
&
func
))
{
priv
->
use_count
++
;
return
FALSE
;
}
unload
=
(
GfNativePluginUnloadFunc
)
func
;
if
(
!
(
unload
&&
unload
(
plugin
)))
{
priv
->
use_count
++
;
return
FALSE
;
}
for
(
l
=
priv
->
type_infos
;
l
;
l
=
l
->
next
)
{
GfNativePluginTypeInfo
*
info
=
(
GfNativePluginTypeInfo
*
)(
l
->
data
);
info
->
loaded
=
FALSE
;
return
FALSE
;
}
}
return
TRUE
;
}
/**
* gf_native_plugin_register_type:
* @plugin: a #GfNativePlugin
* @parent: The type of the parent class
* @name: name for the type
* @info: type information structure
* @flags: flags field providing details about the type
*
* Looks up or registers a type that is implemented via @plugin.
*
* Return Value: the new or existing type ID
*/
GType
gf_native_plugin_register_type
(
GfNativePlugin
*
plugin
,
GType
parent
,
const
gchar
*
name
,
const
GTypeInfo
*
info
,
GTypeFlags
flags
)
{
GfNativePluginPriv
*
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
plugin
);
GfNativePluginTypeInfo
*
type_info
=
NULL
;
GType
type
=
G_TYPE_INVALID
;
g_return_val_if_fail
(
GF_IS_NATIVE_PLUGIN
(
plugin
),
G_TYPE_INVALID
);
g_return_val_if_fail
(
name
,
G_TYPE_INVALID
);
g_return_val_if_fail
(
info
,
G_TYPE_INVALID
);
type
=
g_type_from_name
(
name
);
if
(
type
!=
G_TYPE_INVALID
)
{
/* this type is already loaded, let's make sure it's the same plugin
* loading it again.
*/
GTypePlugin
*
old
=
g_type_get_plugin
(
type
);
if
(
old
!=
G_TYPE_PLUGIN
(
plugin
))
{
gf_log_warning
(
"GfNativePlugin"
,
"Two different plugins tried to register '%s'
\n
"
,
name
);
return
G_TYPE_INVALID
;
}
/* The same plugin is reloading the type */
type_info
=
gf_native_plugin_find_type_info
(
plugin
,
type
);
if
(
type_info
->
parent
!=
parent
)
{
/* eek, them bastards tried to reparent this type! */
const
gchar
*
parent_name
=
g_type_name
(
parent
);
gf_log_warning
(
"GfNativePlugin"
,
"Type '%s' was recreated with a different parent "
"type.
\n
(was '%s', now '%s')
\n
"
,
name
,
g_type_name
(
type_info
->
parent
),
(
parent_name
)
?
parent_name
:
"(unknown)"
);
return
G_TYPE_INVALID
;
}
/* we need to free the old value table if the old type had one */
if
(
type_info
->
info
.
value_table
)
g_free
((
GTypeValueTable
*
)
type_info
->
info
.
value_table
);
}
else
{
/* the type hasn't been loaded before, so now we need to add it */
type_info
=
g_new
(
GfNativePluginTypeInfo
,
1
);
type_info
->
parent
=
parent
;
type_info
->
type
=
g_type_register_dynamic
(
parent
,
name
,
G_TYPE_PLUGIN
(
plugin
),
flags
);
priv
->
type_infos
=
g_slist_prepend
(
priv
->
type_infos
,
type_info
);
}
/* ok, now finish up */
type_info
->
loaded
=
TRUE
;
type_info
->
info
=
*
info
;
if
(
info
->
value_table
)
{
type_info
->
info
.
value_table
=
g_memdup
(
info
->
value_table
,
sizeof
(
GTypeValueTable
));
}
return
type_info
->
type
;
}
/**
* gf_native_plugin_add_interface:
* @plugin: a #GfNativePlugin
* @instance_type: type to which to add the interface
* @interface_type: interface type to add
* @interface_info: type information structure
*
* Registers an additional interface for @instance_type.
*/
void
gf_native_plugin_add_interface
(
GfNativePlugin
*
plugin
,
GType
instance_type
,
GType
interface_type
,
const
GInterfaceInfo
*
interface_info
)
{
GfNativePluginPriv
*
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
plugin
);
GfNativePluginInterfaceInfo
*
iface_info
=
NULL
;
g_return_if_fail
(
GF_IS_NATIVE_PLUGIN
(
plugin
));
g_return_if_fail
(
interface_info
);
if
(
g_type_is_a
(
instance_type
,
interface_type
))
{
GTypePlugin
*
old
=
g_type_interface_get_plugin
(
instance_type
,
interface_type
);
if
(
!
old
)
{
gf_log_warning
(
"GfNativePlugin"
,
"Interface '%s' for '%s' was previously registered "
"statically or for a parent type."
,
g_type_name
(
interface_type
),
g_type_name
(
instance_type
));
return
;
}
else
if
(
old
!=
G_TYPE_PLUGIN
(
plugin
))
{
gf_log_warning
(
"GfNativePlugin"
,
"Two different plugins tried to register interface "
"'%s' for '%s'."
,
g_type_name
(
interface_type
),
g_type_name
(
instance_type
));
return
;
}
iface_info
=
gf_native_plugin_find_interface_info
(
plugin
,
instance_type
,
interface_type
);
g_return_if_fail
(
iface_info
);
}
else
{
iface_info
=
g_new0
(
GfNativePluginInterfaceInfo
,
1
);
iface_info
->
instance_type
=
instance_type
;
iface_info
->
interface_type
=
interface_type
;
g_type_add_interface_dynamic
(
instance_type
,
interface_type
,
G_TYPE_PLUGIN
(
plugin
));
priv
->
interface_infos
=
g_slist_prepend
(
priv
->
interface_infos
,
iface_info
);
}
iface_info
->
loaded
=
TRUE
;
iface_info
->
info
=
*
interface_info
;
}
/**
* gf_native_plugin_register_enum:
* @plugin: a #GfNativePlugin
* @name: name for the type
* @values: an array of #GEnumValue structs for the possible enumeration
* values. The array is terminated by a struct with all members
* being 0.
*
* Looks up or registers an enumeration that is implemented with @plugin.
*
* Return Value: the new or existing type ID
*/
GType
gf_native_plugin_register_enum
(
GfNativePlugin
*
plugin
,
const
gchar
*
name
,
const
GEnumValue
*
values
)
{
GTypeInfo
enum_info
=
{
0
,
};
g_return_val_if_fail
(
GF_IS_NATIVE_PLUGIN
(
plugin
),
G_TYPE_INVALID
);
g_return_val_if_fail
(
name
,
G_TYPE_INVALID
);
g_return_val_if_fail
(
values
,
G_TYPE_INVALID
);
g_enum_complete_type_info
(
G_TYPE_ENUM
,
&
enum_info
,
values
);
return
gf_native_plugin_register_type
(
plugin
,
G_TYPE_ENUM
,
name
,
&
enum_info
,
0
);
}
/**
* gf_native_plugin_register_flags:
* @plugin: a #GfNativePlugin
* @name: name for the type
* @values: an array of GFlagsValue structs for the possible flags values.
* The array is terminated by a struct with all members being 0.
*
* Looks up or registers a flags type that is implemented with @plugin.
*
* Return Value: the new or existing type ID
*/
GType
gf_native_plugin_register_flags
(
GfNativePlugin
*
plugin
,
const
gchar
*
name
,
const
GFlagsValue
*
values
)
{
GTypeInfo
flags_info
=
{
0
,
};
g_return_val_if_fail
(
GF_IS_NATIVE_PLUGIN
(
plugin
),
G_TYPE_INVALID
);
g_return_val_if_fail
(
name
,
G_TYPE_INVALID
);
g_return_val_if_fail
(
values
,
G_TYPE_INVALID
);
g_flags_complete_type_info
(
G_TYPE_FLAGS
,
&
flags_info
,
values
);
return
gf_native_plugin_register_type
(
plugin
,
G_TYPE_FLAGS
,
name
,
&
flags_info
,
0
);
}
/**
* gf_native_plugin_get_module:
* @plugin: a #GfNativePlugin
*
* Gets the #GModule that was open for @plugin.
*
* Return Value: The #GModule for @plugin.
*/
GModule
*
gf_native_plugin_get_module
(
GfNativePlugin
*
plugin
)
{
GfNativePluginPriv
*
priv
=
NULL
;
g_return_val_if_fail
(
GF_IS_NATIVE_PLUGIN
(
plugin
),
NULL
);
priv
=
GF_NATIVE_PLUGIN_GET_PRIVATE
(
plugin
);
return
priv
->
module
;
}