]> git.draconx.ca Git - upkg.git/blobdiff - src/engine/music.c
music: Remove file member from private struct.
[upkg.git] / src / engine / music.c
index 87a549b7e6d538766a2832ff7248afca41bfe50a..8c17f9ddfa19e8a1d9d6da6b0e3ae4391395a433 100644 (file)
@@ -1,9 +1,29 @@
+/*
+ *  upkg: tool for manipulating Unreal Tournament packages.
+ *  Copyright (C) 2009 Nick Bowler
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 #include <stdio.h>
 #include <string.h>
 #include <glib-object.h>
 
-#include "exportable.h"
-#include "uobject.h"
+#include <uobject/uobject.h>
+#include <uobject/exportable.h>
+#include <uobject/loadable.h>
+#include "music-module.h"
 #include "music.h"
 #include "upkg.h"
 
        G_TYPE_INSTANCE_GET_PRIVATE(o, ENGINE_MUSIC_TYPE, struct music_priv)
 
 struct music_priv {
-       struct upkg_file *f;
+       struct music_mod *mod;
+       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 export(GObject *o, FILE *f)
+static int load(GObject *o)
 {
        struct music_priv *priv = MUSIC_GET_PRIV(o);
-       unsigned char buf[1024];
+       struct upkg_file *f = U_OBJECT(o)->pkg_file;
 
-       if (!priv->f || upkg_export_seek(priv->f, 0, SEEK_SET) != 0)
-               return -1;
+       if (!priv->loaded) {
+               g_return_val_if_fail(f != NULL, -1);
 
-       while (!priv->f->eof) {
-               size_t rc = upkg_export_read(priv->f, buf, sizeof buf);
-               if (rc == 0) {
-                       if (priv->f->eof) break;
+               if (upkg_export_seek(f, 0, SEEK_SET) != 0) {
                        return -1;
                }
 
-               if (fwrite(buf, 1, rc, f) != rc)
+               priv->mod = music_mod_open(f);
+               if (!priv->mod) {
                        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);
+
+       if (--priv->loaded == 0) {
+               music_mod_close(priv->mod);
+       }
+}
+
+static int export(GObject *o, FILE *f)
+{
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
+       int rc;
+
+       if (load(o) != 0)
+               return -1;
+
+       rc = music_mod_dump(priv->mod, f);
+
+       unload(o);
+
+       return rc;
+}
+
 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 : "");
+       const char *type;
+       int rc;
+
+       if (load(o) != 0) {
+               if (n > 0) *buf = 0;
+               return 0;
+       }
+
+       type = music_mod_type(priv->mod);
+       rc = snprintf(buf, n, "%s.%s", U_OBJECT(o)->pkg_file->name, type);
+
+       unload(o);
+
+       return rc;
 }
 
 static void exportable_init(UObjectExportable *e)
@@ -54,15 +115,21 @@ static void exportable_init(UObjectExportable *e)
        e->export_name = export_name;
 }
 
-static int deserialize(UObject *o, struct upkg_file *f)
+static void loadable_init(UObjectLoadable *l)
 {
-       struct music_priv *priv = MUSIC_GET_PRIV(o);
-       EngineMusic *m = ENGINE_MUSIC(o);
+       l->load   = load;
+       l->unload = unload;
+}
+
+static int deserialize(UObject *uo)
+{
+       struct music_priv *priv = MUSIC_GET_PRIV(uo);
+       struct upkg_file *f = uo->pkg_file;
        size_t rc, pos = 0, buflen;
        unsigned char buf[32];
        long size;
 
-       U_OBJECT_CLASS(engine_music_parent_class)->deserialize(o, f);
+       U_OBJECT_CLASS(engine_music_parent_class)->deserialize(uo);
 
        buflen = upkg_export_read(f, buf, sizeof buf);
 
@@ -87,8 +154,6 @@ static int deserialize(UObject *o, struct upkg_file *f)
        f->len   = size;
        upkg_export_seek(f, 0, SEEK_SET);
 
-       priv->f = f;
-
        return 0;
 }
 
@@ -99,17 +164,35 @@ void music_register(GTypeModule *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_finalize(GObject *o)
+{
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
+
+       if (priv->loaded >= 1) {
+               priv->loaded = 1;
+               unload(o);
+       }
+
+       G_OBJECT_CLASS(engine_music_parent_class)->finalize(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;
+
+       music_mod_init();
 }
 
 static void engine_music_class_finalize(EngineMusicClass *class)
 {
+       music_mod_exit();
 }