]> git.draconx.ca Git - upkg.git/blob - src/engine/music.c
Simplify music I/O.
[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         struct upkg_file *f;
15 };
16
17 static void exportable_init(UObjectExportable *);
18
19 G_DEFINE_DYNAMIC_TYPE_EXTENDED(EngineMusic, engine_music, U_OBJECT_TYPE, 0,
20         G_IMPLEMENT_INTERFACE(U_OBJECT_TYPE_EXPORTABLE, exportable_init)
21 );
22
23 static int export(GObject *o, FILE *f)
24 {
25         struct music_priv *priv = MUSIC_GET_PRIV(o);
26         unsigned char buf[1024];
27
28         if (!priv->f || upkg_export_seek(priv->f, 0, SEEK_SET) != 0)
29                 return -1;
30
31         while (!priv->f->eof) {
32                 size_t rc = upkg_export_read(priv->f, buf, sizeof buf);
33                 if (rc == 0) {
34                         if (priv->f->eof) break;
35                         return -1;
36                 }
37
38                 if (fwrite(buf, 1, rc, f) != rc)
39                         return -1;
40         }
41
42         return 0;
43 }
44
45 static int export_name(GObject *o, char *buf, size_t n)
46 {
47         struct music_priv *priv = MUSIC_GET_PRIV(o);
48         return snprintf(buf, n, "%s", priv->f ? priv->f->name : "");
49 }
50
51 static void exportable_init(UObjectExportable *e)
52 {
53         e->export      = export;
54         e->export_name = export_name;
55 }
56
57 static int deserialize(UObject *o, struct upkg_file *f)
58 {
59         struct music_priv *priv = MUSIC_GET_PRIV(o);
60         EngineMusic *m = ENGINE_MUSIC(o);
61         size_t rc, pos = 0, buflen;
62         unsigned char buf[32];
63         long size;
64
65         U_OBJECT_CLASS(engine_music_parent_class)->deserialize(o, f);
66
67         buflen = upkg_export_read(f, buf, sizeof buf);
68
69         /* Random field #1 */
70         if (buflen - pos < 1)
71                 return -1;
72         pos += 1;
73
74         if (f->pkg->version > 61) {
75                 /* Random field #2 */
76                 if (buflen - pos < 4)
77                         return -1;
78                 pos += 4;
79         }
80
81         rc = upkg_decode_index(&size, buf+pos, buflen-pos);
82         if (rc == 0 || size < 0)
83                 return -1;
84         pos += rc;
85
86         f->base += pos;
87         f->len   = size;
88         upkg_export_seek(f, 0, SEEK_SET);
89
90         priv->f = f;
91
92         return 0;
93 }
94
95 void music_register(GTypeModule *m)
96 {
97         engine_music_register_type(m);
98 }
99
100 static void engine_music_init(EngineMusic *m)
101 {
102 }
103
104 static void engine_music_class_init(EngineMusicClass *class)
105 {
106         UObjectClass *uo = U_OBJECT_CLASS(class);
107
108         g_type_class_add_private(class, sizeof (struct music_priv));
109
110         uo->deserialize = deserialize;
111 }
112
113 static void engine_music_class_finalize(EngineMusicClass *class)
114 {
115 }