#include #include #include #include "exportable.h" #include "uobject.h" #include "music.h" #include "upkg.h" #define MUSIC_GET_PRIV(o) \ 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; }; static void exportable_init(UObjectExportable *); G_DEFINE_DYNAMIC_TYPE_EXTENDED(EngineMusic, engine_music, U_OBJECT_TYPE, 0, G_IMPLEMENT_INTERFACE(U_OBJECT_TYPE_EXPORTABLE, exportable_init) ); static int export(GObject *o, FILE *f) { struct music_priv *priv = MUSIC_GET_PRIV(o); size_t left = priv->len, rc; unsigned char buf[1024]; if (!priv->f) return -1; if (upkg_export_seek(priv->f, priv->base, SEEK_SET) != 0) return -1; while (left > 0) { rc = upkg_export_read(priv->f, buf, MIN(left, sizeof buf)); if (rc == 0) return -1; if (fwrite(buf, 1, rc, f) != rc) return -1; left -= rc; } return 0; } static int export_name(GObject *o, char *buf, size_t n) { struct music_priv *priv = MUSIC_GET_PRIV(o); return snprintf(buf, n, "%s", priv->f ? priv->f->name : ""); } static void exportable_init(UObjectExportable *e) { e->export = export; e->export_name = export_name; } static int deserialize(UObject *o, struct upkg_file *f) { struct music_priv *priv = MUSIC_GET_PRIV(o); EngineMusic *m = ENGINE_MUSIC(o); 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; /* Random field #1 */ if (priv->nbuf - priv->base < 1) return -1; // unpack_16_le(priv->buf+0); priv->base += 1; if (f->pkg->version > 61) { /* Random field #2 */ if (priv->nbuf - priv->base < 4) return -1; // unpack_32_le(priv->buf+2); priv->base += 4; } rc = upkg_decode_index(&size, priv->buf+priv->base, priv->nbuf-priv->base); if (rc == 0 || size < 0) return -1; priv->base += rc; priv->len = size; priv->nbuf -= priv->base; memmove(priv->buf, priv->buf+priv->base, priv->nbuf); priv->f = f; return 0; } void music_register(GTypeModule *m) { engine_music_register_type(m); } static void engine_music_init(EngineMusic *m) { } static void engine_music_class_init(EngineMusicClass *class) { UObjectClass *uo = U_OBJECT_CLASS(class); g_type_class_add_private(class, sizeof (struct music_priv)); uo->deserialize = deserialize; } static void engine_music_class_finalize(EngineMusicClass *class) { }