]> git.draconx.ca Git - upkg.git/commitdiff
Initial UObject implementation plus a dumb music extractor.
authorNick Bowler <nbowler@draconx.ca>
Mon, 8 Jun 2009 19:46:50 +0000 (15:46 -0400)
committerNick Bowler <nbowler@draconx.ca>
Tue, 9 Jun 2009 02:43:26 +0000 (22:43 -0400)
configure.ac
src/Makefile.am
src/exportable.c [new file with mode: 0644]
src/exportable.h [new file with mode: 0644]
src/music.c [new file with mode: 0644]
src/music.h [new file with mode: 0644]
src/serializable.c [new file with mode: 0644]
src/serializable.h [new file with mode: 0644]
src/upkg.c

index debf262d9d3f17ed199054266d429148981a5fbd..5b8dbf732cd89d423980ef6b94531eb55588bcaf 100644 (file)
@@ -8,6 +8,20 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign])
 
 AC_PROG_CC_C99
 
+AC_ARG_WITH([gobject],
+       [AS_HELP_STRING([--with-gobject],
+               [build tools requiring libgobject [default=yes]]
+       )],
+       [],
+       [with_gobject=yes])
+
+have_gobject=no
+if test x$with_gobject = xyes; then
+AM_PATH_GLIB_2_0(, [have_gobject=yes], [have_gobject=no], [gobject])
+fi
+
+AM_CONDITIONAL([BUILD_UPKG], [test x$have_gobject = xyes])
+
 LT_INIT
 
 AC_CONFIG_FILES([
index 2002c43b2efdb1c50b3fd3ec9d627263f490e600..a631216889c729a90bd7bde089d7cef5b0e1a49c 100644 (file)
@@ -1,9 +1,13 @@
 lib_LTLIBRARIES = libupkg.la
-bin_PROGRAMS = upkg
 
 libupkg_la_SOURCES = libupkg.c pack.c
 include_HEADERS = upkg.h
 noinst_HEADERS = pack.h
 
-upkg_SOURCES = upkg.c
+if BUILD_UPKG
+bin_PROGRAMS = upkg
+upkg_SOURCES = upkg.c exportable.c serializable.c music.c
+upkg_CFLAGS  = $(GLIB_CFLAGS)
+upkg_LDFLAGS = $(GLIB_LIBS)
 upkg_LDADD = libupkg.la
+endif
diff --git a/src/exportable.c b/src/exportable.c
new file mode 100644 (file)
index 0000000..8947fcc
--- /dev/null
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <glib-object.h>
+#include "exportable.h"
+
+GType upkg_exportable_get_type(void)
+{
+       static GType type = 0;
+       if (type == 0) {
+               static const GTypeInfo info = {
+                       sizeof (UPkgExportable),
+                       NULL,
+                       NULL,
+               };
+
+               type = g_type_register_static(G_TYPE_INTERFACE,
+                       "UPkgExportable", &info, 0);
+       }
+       return type;
+}
+
+int upkg_export(GObject *obj, FILE *f)
+{
+       g_return_val_if_fail(UPKG_IS_EXPORTABLE(obj), -1);
+       return UPKG_EXPORTABLE_GET_INTERFACE(obj)->export(obj, f);
+}
+
+int upkg_export_name(GObject *obj, char *buf, size_t n)
+{
+       g_return_val_if_fail(UPKG_IS_EXPORTABLE(obj), -1);
+       return UPKG_EXPORTABLE_GET_INTERFACE(obj)->export_name(obj, buf, n);
+}
diff --git a/src/exportable.h b/src/exportable.h
new file mode 100644 (file)
index 0000000..9fe07e9
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef EXPORTABLE_H_
+#define EXPORTABLE_H_
+
+#include <stdio.h>
+#include <glib-object.h>
+
+#define UPKG_TYPE_EXPORTABLE (upkg_exportable_get_type())
+#define UPKG_EXPORTABLE(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, \
+       UPKG_TYPE_EXPORTABLE, UPkgExportable)
+#define UPKG_IS_EXPORTABLE(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, \
+       UPKG_TYPE_EXPORTABLE)
+#define UPKG_EXPORTABLE_GET_INTERFACE(inst) G_TYPE_INSTANCE_GET_INTERFACE \
+       (inst, UPKG_TYPE_EXPORTABLE, UPkgExportable)
+
+typedef struct UPkgExportable UPkgExportable;
+
+struct UPkgExportable {
+       GTypeInterface parent;
+
+       int (*export)(GObject *obj, FILE *f);
+       int (*export_name)(GObject *obj, char *buf, size_t n);
+};
+
+GType upkg_exportable_get_type(void);
+
+int upkg_export(GObject *obj, FILE *f);
+int upkg_export_name(GObject *obj, char *buf, size_t n);
+
+#endif
diff --git a/src/music.c b/src/music.c
new file mode 100644 (file)
index 0000000..4c64a7b
--- /dev/null
@@ -0,0 +1,117 @@
+#include <stdio.h>
+#include <string.h>
+#include <glib-object.h>
+
+#include "serializable.h"
+#include "exportable.h"
+#include "music.h"
+#include "upkg.h"
+
+#define U_MUSIC_GET_PRIV(o) \
+       G_TYPE_INSTANCE_GET_PRIVATE(o, U_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 serializable_init(UPkgSerializable *s);
+static void exportable_init(UPkgExportable *e);
+
+G_DEFINE_TYPE_WITH_CODE(UMusic, u_music, G_TYPE_OBJECT,
+       G_IMPLEMENT_INTERFACE(UPKG_TYPE_SERIALIZABLE, serializable_init)
+       G_IMPLEMENT_INTERFACE(UPKG_TYPE_EXPORTABLE, exportable_init)
+);
+
+static int export(GObject *o, FILE *f)
+{
+       struct music_priv *priv = U_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 = U_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 = U_MUSIC_GET_PRIV(o);
+       UMusic *m = U_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 u_music_init(UMusic *o)
+{
+}
+
+static void u_music_class_init(UMusicClass *class)
+{
+       g_type_class_add_private(class, sizeof (struct music_priv));
+}
diff --git a/src/music.h b/src/music.h
new file mode 100644 (file)
index 0000000..d3f685c
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef MUSIC_H_
+#define MUSIC_H_
+
+#include <glib-object.h>
+
+#define U_MUSIC_TYPE (u_music_get_type())
+#define U_MUSIC(obj) \
+       G_TYPE_CHECK_INSTANCE_CAST(obj, U_MUSIC_TYPE, UMusic)
+#define U_MUSIC_CLASS(class) \
+       G_TYPE_CHECK_CLASS_CAST(class, U_MUSIC_TYPE, UMusicClass)
+#define IS_U_MUSIC(obj) \
+       G_TYPE_CHECK_INSTANCE_TYPE(obj, U_MUSIC_TYPE)
+#define IS_U_MUSIC_CLASS(class) \
+       G_TYPE_CHECK_CLASS_TYPE(class, U_MUSIC_TYPE, UMusicClass)
+
+typedef struct UMusic      UMusic;
+typedef struct UMusicClass UMusicClass;
+
+enum {
+       U_MUSIC_UNKNOWN,
+       U_MUSIC_IT,
+       U_MUSIC_S3M,
+       U_MUSIC_XM,
+};
+
+struct UMusic {
+       GObject parent;
+};
+
+struct UMusicClass {
+       GObjectClass parent;
+};
+
+GType u_music_get_type(void);
+
+static inline GObject *u_music_new(void)
+{
+       return g_object_new(u_music_get_type(), NULL);
+}
+
+#endif
diff --git a/src/serializable.c b/src/serializable.c
new file mode 100644 (file)
index 0000000..fdc2cc5
--- /dev/null
@@ -0,0 +1,25 @@
+#include <glib-object.h>
+#include "serializable.h"
+#include "upkg.h"
+
+GType upkg_serializable_get_type(void)
+{
+       static GType type = 0;
+       if (type == 0) {
+               static const GTypeInfo info = {
+                       sizeof (UPkgSerializable),
+                       NULL,
+                       NULL,
+               };
+
+               type = g_type_register_static(G_TYPE_INTERFACE,
+                       "UPkgSerializable", &info, 0);
+       }
+       return type;
+}
+
+int upkg_deserialize(GObject *obj, struct upkg_file *f)
+{
+       g_return_val_if_fail(UPKG_IS_SERIALIZABLE(obj), -1);
+       return UPKG_SERIALIZABLE_GET_INTERFACE(obj)->deserialize(obj, f);
+}
diff --git a/src/serializable.h b/src/serializable.h
new file mode 100644 (file)
index 0000000..5d83d57
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef SERIALIZABLE_H_
+#define SERIALIZABLE_H_
+
+#include <glib-object.h>
+#include "upkg.h"
+
+#define UPKG_TYPE_SERIALIZABLE (upkg_serializable_get_type())
+#define UPKG_SERIALIZABLE(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, \
+       UPKG_TYPE_SERIALIZABLE, UPkgSerializable)
+#define UPKG_IS_SERIALIZABLE(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, \
+       UPKG_TYPE_SERIALIZABLE)
+#define UPKG_SERIALIZABLE_GET_INTERFACE(inst) G_TYPE_INSTANCE_GET_INTERFACE \
+       (inst, UPKG_TYPE_SERIALIZABLE, UPkgSerializable)
+
+typedef struct UPkgSerializable UPkgSerializable;
+
+struct UPkgSerializable {
+       GTypeInterface parent;
+
+       int (*deserialize)(GObject *obj, struct upkg_file *f);
+};
+
+GType upkg_serializable_get_type(void);
+int upkg_deserialize(GObject *obj, struct upkg_file *f);
+
+#endif
index 20b7336155a1077840d171889aff71b859e68e6d..bcbee2fbcd291b5522ea551942e81c5ec07ed729 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <glib-object.h>
+
 #include "upkg.h"
+#include "serializable.h"
+#include "exportable.h"
+#include "music.h"
 
 void print_upkg_flags(const char *prefix, unsigned long flags)
 {
@@ -52,6 +57,8 @@ int main(int argc, char **argv)
 {
        struct upkg *pkg;
 
+       g_type_init();
+
        if (argc < 2) {
                fprintf(stderr, "usage: upkg file\n");
                return EXIT_FAILURE;
@@ -79,6 +86,18 @@ int main(int argc, char **argv)
        printf("Exports: %lu\n", pkg->export_count);
        printf("Imports: %lu\n", pkg->import_count);
 
+       GObject *music = u_music_new();
+       struct upkg_file *f = upkg_export_open(pkg, 0);
+       upkg_deserialize(music, f);
+
+       char name[256];
+       upkg_export_name(music, name, sizeof name);
+       FILE *fp = fopen(name, "wb");
+       if (!fp) return EXIT_FAILURE;
+       upkg_export(music, fp);
+       fclose(fp);
+       printf("Wrote %s\n", name);
+
        upkg_close(pkg);
        return 0;
 }