]> git.draconx.ca Git - upkg.git/blob - src/engine/music.c
Reorganize object hierarchy to root at "UObject".
[upkg.git] / src / engine / music.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <glib-object.h>
4
5 #include "exportable.h"
6 #include "uobject.h"
7 #include "music.h"
8 #include "upkg.h"
9
10 #define MUSIC_GET_PRIV(o) \
11         G_TYPE_INSTANCE_GET_PRIVATE(o, ENGINE_MUSIC_TYPE, struct music_priv)
12
13 struct music_priv {
14         unsigned type;
15
16         struct upkg_file *f;
17         size_t base, len;
18
19         unsigned char buf[2048];
20         unsigned long nbuf;
21 };
22
23 static void exportable_init(UObjectExportable *);
24
25 G_DEFINE_DYNAMIC_TYPE_EXTENDED(EngineMusic, engine_music, U_OBJECT_TYPE, 0,
26         G_IMPLEMENT_INTERFACE(U_OBJECT_TYPE_EXPORTABLE, exportable_init)
27 );
28
29 static int export(GObject *o, FILE *f)
30 {
31         struct music_priv *priv = MUSIC_GET_PRIV(o);
32         size_t left = priv->len, rc;
33
34         unsigned char buf[1024];
35
36         if (!priv->f)
37                 return -1;
38
39         if (upkg_export_seek(priv->f, priv->base, SEEK_SET) != 0)
40                 return -1;
41
42         while (left > 0) {
43                 rc = upkg_export_read(priv->f, buf, MIN(left, sizeof buf));
44                 if (rc == 0)
45                         return -1;
46                 if (fwrite(buf, 1, rc, f) != rc)
47                         return -1;
48                 left -= rc;
49         }
50
51         return 0;
52 }
53
54 static int export_name(GObject *o, char *buf, size_t n)
55 {
56         struct music_priv *priv = MUSIC_GET_PRIV(o);
57         return snprintf(buf, n, "%s", priv->f ? priv->f->name : "");
58 }
59
60 static void exportable_init(UObjectExportable *e)
61 {
62         e->export      = export;
63         e->export_name = export_name;
64 }
65
66 static int deserialize(UObject *o, struct upkg_file *f)
67 {
68         struct music_priv *priv = MUSIC_GET_PRIV(o);
69         EngineMusic *m = ENGINE_MUSIC(o);
70         long size;
71
72         size_t rc;
73
74         U_OBJECT_CLASS(engine_music_parent_class)->deserialize(o, f);
75
76         priv->nbuf = upkg_export_read(f, priv->buf, sizeof priv->buf);
77         priv->base = 0;
78
79         /* Random field #1 */
80         if (priv->nbuf - priv->base < 1)
81                 return -1;
82         // unpack_16_le(priv->buf+0);
83         priv->base += 1;
84
85         if (f->pkg->version > 61) {
86                 /* Random field #2 */
87                 if (priv->nbuf - priv->base < 4)
88                         return -1;
89                 // unpack_32_le(priv->buf+2);
90                 priv->base += 4;
91         }
92
93         rc = upkg_decode_index(&size, priv->buf+priv->base, priv->nbuf-priv->base);
94         if (rc == 0 || size < 0)
95                 return -1;
96
97         priv->base += rc;
98         priv->len   = size;
99
100         priv->nbuf -= priv->base;
101         memmove(priv->buf, priv->buf+priv->base, priv->nbuf);
102
103         priv->f = f;
104         return 0;
105 }
106
107 void music_register(GTypeModule *m)
108 {
109         engine_music_register_type(m);
110 }
111
112 static void engine_music_init(EngineMusic *m)
113 {
114 }
115
116 static void engine_music_class_init(EngineMusicClass *class)
117 {
118         UObjectClass *uo = U_OBJECT_CLASS(class);
119
120         g_type_class_add_private(class, sizeof (struct music_priv));
121
122         uo->deserialize = deserialize;
123 }
124
125 static void engine_music_class_finalize(EngineMusicClass *class)
126 {
127 }