#include <string.h>
#include <glib-object.h>
-#include "serializable.h"
#include "exportable.h"
+#include "loadable.h"
+#include "uobject.h"
#include "music.h"
#include "upkg.h"
G_TYPE_INSTANCE_GET_PRIVATE(o, ENGINE_MUSIC_TYPE, struct music_priv)
struct music_priv {
- unsigned type;
-
struct upkg_file *f;
- size_t base, len;
-
- unsigned char buf[2048];
- unsigned long nbuf;
+ unsigned loaded;
};
-static int export(GObject *o, FILE *f)
+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);
- size_t left = priv->len, rc;
- unsigned char buf[1024];
+ if (!priv->loaded) {
+ g_return_val_if_fail(priv->f != NULL, -1);
- if (!priv->f)
- return -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);
+ unsigned char buf[1024];
- if (upkg_export_seek(priv->f, priv->base, SEEK_SET) != 0)
+ if (!priv->f || upkg_export_seek(priv->f, 0, SEEK_SET) != 0)
return -1;
- while (left > 0) {
- rc = upkg_export_read(priv->f, buf, MIN(left, sizeof buf));
- if (rc == 0)
+ while (!priv->f->eof) {
+ size_t rc = upkg_export_read(priv->f, buf, sizeof buf);
+ if (rc == 0) {
+ if (priv->f->eof) break;
return -1;
+ }
+
if (fwrite(buf, 1, rc, f) != rc)
return -1;
- left -= rc;
}
return 0;
return snprintf(buf, n, "%s", priv->f ? priv->f->name : "");
}
-static void exportable_init(UPkgExportable *e)
+static void exportable_init(UObjectExportable *e)
{
e->export = export;
e->export_name = export_name;
}
-static int deserialize(GObject *o, struct upkg_file *f)
+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);
EngineMusic *m = ENGINE_MUSIC(o);
+ size_t rc, pos = 0, buflen;
+ unsigned char buf[32];
long size;
- size_t rc;
+ U_OBJECT_CLASS(engine_music_parent_class)->deserialize(o, f);
- priv->nbuf = upkg_export_read(f, priv->buf, sizeof priv->buf);
- priv->base = 0;
+ buflen = upkg_export_read(f, buf, sizeof buf);
/* Random field #1 */
- if (priv->nbuf - priv->base < 2)
+ if (buflen - pos < 1)
return -1;
- // unpack_16_le(priv->buf+0);
- priv->base += 2;
+ pos += 1;
if (f->pkg->version > 61) {
/* Random field #2 */
- if (priv->nbuf - priv->base < 4)
+ if (buflen - pos < 4)
return -1;
- // unpack_32_le(priv->buf+2);
- priv->base += 4;
+ pos += 4;
}
- rc = upkg_decode_index(&size, priv->buf+priv->base, priv->nbuf-priv->base);
+ rc = upkg_decode_index(&size, buf+pos, buflen-pos);
if (rc == 0 || size < 0)
return -1;
+ pos += rc;
- priv->base += rc;
- priv->len = size;
-
- priv->nbuf -= priv->base;
- memmove(priv->buf, priv->buf+priv->base, priv->nbuf);
+ f->base += pos;
+ f->len = size;
+ upkg_export_seek(f, 0, SEEK_SET);
priv->f = f;
+
return 0;
}
-static void serializable_init(UPkgSerializable *s)
+void music_register(GTypeModule *m)
{
- s->deserialize = deserialize;
+ engine_music_register_type(m);
}
static void engine_music_init(EngineMusic *m)
{
+ struct music_priv *priv = MUSIC_GET_PRIV(m);
+ *priv = (struct music_priv){0};
}
-static void engine_music_class_init(EngineMusicClass *class)
+static void engine_music_finalize(GObject *o)
{
- g_type_class_add_private(class, sizeof (struct music_priv));
+ struct music_priv *priv = MUSIC_GET_PRIV(o);
+
+ if (priv->loaded >= 1) {
+ priv->loaded = 1;
+ unload(o);
+ }
}
-static void engine_music_class_finalize(EngineMusicClass *class)
+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));
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(EngineMusic, engine_music, G_TYPE_OBJECT, 0,
- G_IMPLEMENT_INTERFACE(UPKG_TYPE_SERIALIZABLE, serializable_init)
- G_IMPLEMENT_INTERFACE(UPKG_TYPE_EXPORTABLE, exportable_init)
-);
+ uo->deserialize = deserialize;
+ go->finalize = engine_music_finalize;
+}
-void music_register(GTypeModule *m)
+static void engine_music_class_finalize(EngineMusicClass *class)
{
- engine_music_register_type(m);
}