]> git.draconx.ca Git - upkg.git/blobdiff - src/engine/music.gob
music: Migrate to GOB2.
[upkg.git] / src / engine / music.gob
diff --git a/src/engine/music.gob b/src/engine/music.gob
new file mode 100644 (file)
index 0000000..920e23c
--- /dev/null
@@ -0,0 +1,143 @@
+%alltop{
+/*
+ *  upkg: tool for manipulating Unreal Tournament packages.
+ *  Copyright © 2009-2011 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 <uobject/loadable.h>
+#include <uobject/exportable.h>
+#include <engine/music-module.h>
+#include <upkg.h>
+%}
+
+%h{
+#include <uobject/uobject.h>
+%}
+
+class Engine:Music from U:Object (dynamic)
+       (interface U:Object:Exportable)
+       (interface U:Object:Loadable)
+{
+       private struct music_mod *mod = NULL;
+       private unsigned loaded = 0;
+
+       interface U:Object:Loadable
+       private int load(G:Object *go)
+       {
+               struct upkg_file *f = U_OBJECT(go)->pkg_file;
+               Self *self = SELF(go);
+
+               if (!self->_priv->loaded) {
+                       g_return_val_if_fail(f != NULL, -1);
+
+                       if (upkg_export_seek(f, 0, SEEK_SET) != 0)
+                               return -1;
+
+                       self->_priv->mod = music_mod_open(f);
+                       if (!self->_priv->mod)
+                               return -1;
+               }
+
+               self->_priv->loaded++;
+               return 0;
+       }
+
+       interface U:Object:Loadable
+       private void unload(G:Object *go)
+       {
+               Self *self = SELF(go);
+
+               g_return_if_fail(self->_priv->loaded > 0);
+
+               if (--self->_priv->loaded == 0)
+                       music_mod_close(self->_priv->mod);
+       }
+
+       interface U:Object:Exportable
+       private int export(G:Object *go, FILE *f)
+       {
+               Self *self = SELF(go);
+               int rc;
+
+               if (self_load(go) != 0)
+                       return -1;
+
+               rc = music_mod_dump(self->_priv->mod, f);
+
+               self_unload(go);
+               return rc;
+       }
+
+       interface U:Object:Exportable
+       private int export_name(G:Object *go, char *buf, size_t n)
+       {
+               Self *self = SELF(go);
+               const char *type;
+               int rc;
+
+               if (self_load(go) != 0) {
+                       if (n > 0)
+                               buf[0] = '\0';
+                       return 0;
+               }
+
+               type = music_mod_type(self->_priv->mod);
+               rc = snprintf(buf, n, "%s.%s", U_OBJECT(go)->pkg_file->name, type);
+
+               self_unload(go);
+               return rc;
+       }
+
+       override (U:Object) int deserialize(U:Object *uo)
+       {
+               struct upkg_file *f = uo->pkg_file;
+               Self *self = SELF(uo);
+               size_t rc, pos, buflen;
+               unsigned char buf[32];
+               long size;
+
+               PARENT_HANDLER(uo);
+
+               buflen = upkg_export_read(f, buf, sizeof buf);
+
+               /* Unknown field #1 */
+               if (buflen - pos < 1)
+                       return -1;
+               pos += 1;
+
+               if (uo->pkg->version > 61) {
+                       /* Unknown field #2 */
+                       if (buflen - pos < 4)
+                               return -1;
+                       pos += 4;
+               }
+
+               rc = upkg_decode_index(&size, buf+pos, buflen-pos);
+               if (rc == 0 || size < 0)
+                       return -1;
+               pos += rc;
+
+               f->base += pos;
+               f->len   = size;
+               upkg_export_seek(f, 0, SEEK_SET);
+
+               return 0;
+       }
+}