]> git.draconx.ca Git - upkg.git/blobdiff - src/engine/music.c
Implement dynamic loading of modules.
[upkg.git] / src / engine / music.c
diff --git a/src/engine/music.c b/src/engine/music.c
new file mode 100644 (file)
index 0000000..0c0cdf8
--- /dev/null
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <string.h>
+#include <glib-object.h>
+
+#include "serializable.h"
+#include "exportable.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 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 (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->name);
+}
+
+static void exportable_init(UPkgExportable *e)
+{
+       e->export      = export;
+       e->export_name = export_name;
+}
+
+static int deserialize(GObject *o, struct upkg_file *f)
+{
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
+       EngineMusic *m = ENGINE_MUSIC(o);
+       long size;
+
+       size_t rc;
+
+       priv->nbuf = upkg_export_read(f, priv->buf, sizeof priv->buf);
+       priv->base = 0;
+
+       /* Random field #1 */
+       if (priv->nbuf - priv->base < 2)
+               return -1;
+       // unpack_16_le(priv->buf+0);
+       priv->base += 2;
+
+       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;
+}
+
+static void serializable_init(UPkgSerializable *s)
+{
+       s->deserialize = deserialize;
+}
+
+static void engine_music_init(EngineMusic *m)
+{
+}
+
+static void engine_music_class_init(EngineMusicClass *class)
+{
+       g_type_class_add_private(class, sizeof (struct music_priv));
+}
+
+static void engine_music_class_finalize(EngineMusicClass *class)
+{
+}
+
+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)
+);
+
+void music_register(GTypeModule *m)
+{
+       engine_music_register_type(m);
+}