libupkg_la_SOURCES = libupkg.c pack.c
include_HEADERS = upkg.h
-noinst_HEADERS = pack.h exportable.h uobject.h module.h avl.h
+noinst_HEADERS = pack.h loadable.h exportable.h uobject.h module.h avl.h
if BUILD_UPKG
include engine/Makefile.inc
bin_PROGRAMS = upkg
-upkg_SOURCES = upkg.c avl.c module.c exportable.c uobject.c
+upkg_SOURCES = upkg.c avl.c module.c loadable.c exportable.c uobject.c
upkg_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib \
$(GLIB_CFLAGS) $(LTDLINCL)
upkg_LDFLAGS = -L$(top_builddir)/lib -export-dynamic
#include <glib-object.h>
#include "exportable.h"
+#include "loadable.h"
#include "uobject.h"
#include "music.h"
#include "upkg.h"
struct music_priv {
struct upkg_file *f;
+ unsigned loaded;
};
static void exportable_init(UObjectExportable *);
+static void loadable_init(UObjectLoadable *);
G_DEFINE_DYNAMIC_TYPE_EXTENDED(EngineMusic, engine_music, U_OBJECT_TYPE, 0,
G_IMPLEMENT_INTERFACE(U_OBJECT_TYPE_EXPORTABLE, exportable_init)
+ G_IMPLEMENT_INTERFACE(U_OBJECT_TYPE_LOADABLE, loadable_init)
);
+static int load(GObject *o)
+{
+ struct music_priv *priv = MUSIC_GET_PRIV(o);
+
+ if (!priv->loaded) {
+ g_return_val_if_fail(priv->f != NULL, -1);
+
+ if (upkg_export_seek(priv->f, 0, SEEK_SET) != 0) {
+ return -1;
+ }
+ }
+
+ priv->loaded++;
+ return 0;
+}
+
+static void unload(GObject *o)
+{
+ struct music_priv *priv = MUSIC_GET_PRIV(o);
+ g_return_if_fail(priv->loaded > 0);
+
+ --priv->loaded;
+}
+
static int export(GObject *o, FILE *f)
{
struct music_priv *priv = MUSIC_GET_PRIV(o);
e->export_name = export_name;
}
+static void loadable_init(UObjectLoadable *l)
+{
+ l->load = load;
+ l->unload = unload;
+}
+
static int deserialize(UObject *o, struct upkg_file *f)
{
struct music_priv *priv = MUSIC_GET_PRIV(o);
static void engine_music_init(EngineMusic *m)
{
+ struct music_priv *priv = MUSIC_GET_PRIV(m);
+ *priv = (struct music_priv){0};
+}
+
+static void engine_music_finalize(GObject *o)
+{
+ struct music_priv *priv = MUSIC_GET_PRIV(o);
+
+ if (priv->loaded >= 1) {
+ priv->loaded = 1;
+ unload(o);
+ }
}
static void engine_music_class_init(EngineMusicClass *class)
{
UObjectClass *uo = U_OBJECT_CLASS(class);
-
+ GObjectClass *go = G_OBJECT_CLASS(class);
g_type_class_add_private(class, sizeof (struct music_priv));
uo->deserialize = deserialize;
+ go->finalize = engine_music_finalize;
}
static void engine_music_class_finalize(EngineMusicClass *class)
--- /dev/null
+#include <stdio.h>
+#include <glib-object.h>
+#include "loadable.h"
+
+GType u_object_loadable_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (UObjectLoadable),
+ NULL,
+ NULL,
+ };
+
+ type = g_type_register_static(G_TYPE_INTERFACE,
+ "UObjectLoadable", &info, 0);
+ }
+ return type;
+}
+
+int u_object_load(GObject *obj)
+{
+ g_return_val_if_fail(U_OBJECT_IS_LOADABLE(obj), -1);
+ return U_OBJECT_LOADABLE_GET_INTERFACE(obj)->load(obj);
+}
+
+void u_object_unload(GObject *obj)
+{
+ g_return_if_fail(U_OBJECT_IS_LOADABLE(obj));
+ U_OBJECT_LOADABLE_GET_INTERFACE(obj)->unload(obj);
+}
--- /dev/null
+#ifndef LOADABLE_H_
+#define LOADABLE_H_
+
+#include <stdio.h>
+#include <glib-object.h>
+
+#define U_OBJECT_TYPE_LOADABLE (u_object_loadable_get_type())
+#define U_OBJECT_LOADABLE(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, \
+ U_OBJECT_TYPE_LOADABLE, UObjectLoadable)
+#define U_OBJECT_IS_LOADABLE(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, \
+ U_OBJECT_TYPE_LOADABLE)
+#define U_OBJECT_LOADABLE_GET_INTERFACE(inst) G_TYPE_INSTANCE_GET_INTERFACE \
+ (inst, U_OBJECT_TYPE_LOADABLE, UObjectLoadable)
+
+typedef struct UObjectLoadable UObjectLoadable;
+
+struct UObjectLoadable {
+ GTypeInterface parent;
+
+ int (*load)(GObject *obj);
+ void (*unload)(GObject *obj);
+};
+
+GType u_object_loadable_get_type(void);
+
+int u_object_load(GObject *obj);
+void u_object_unload(GObject *obj);
+
+#endif
#include "module.h"
#include "uobject.h"
#include "exportable.h"
+#include "loadable.h"
enum {
MODE_INFO,
if (u_object_deserialize(obj, f) != 0) {
goto out;
}
+
+ if (U_OBJECT_IS_LOADABLE(obj) && u_object_load(obj) != 0) {
+ goto out;
+ }
+
u_object_export_name(obj, name, sizeof name);
printf("exporting %s to %s\n", upkg_export_name(pkg, idx), name);
goto out;
}
+ if (U_OBJECT_IS_LOADABLE(obj)) {
+ u_object_unload(obj);
+ }
+
out:
upkg_export_close(f);
return rc;