]> git.draconx.ca Git - upkg.git/blob - src/engine/music.c
Implement dynamic loading of modules.
[upkg.git] / src / engine / music.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <glib-object.h>
4
5 #include "serializable.h"
6 #include "exportable.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 int export(GObject *o, FILE *f)
24 {
25         struct music_priv *priv = MUSIC_GET_PRIV(o);
26         size_t left = priv->len, rc;
27
28         unsigned char buf[1024];
29
30         if (upkg_export_seek(priv->f, priv->base, SEEK_SET) != 0)
31                 return -1;
32
33         while (left > 0) {
34                 rc = upkg_export_read(priv->f, buf, MIN(left, sizeof buf));
35                 if (rc == 0)
36                         return -1;
37                 if (fwrite(buf, 1, rc, f) != rc)
38                         return -1;
39                 left -= rc;
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
49         return snprintf(buf, n, "%s", priv->f->name);
50 }
51
52 static void exportable_init(UPkgExportable *e)
53 {
54         e->export      = export;
55         e->export_name = export_name;
56 }
57
58 static int deserialize(GObject *o, struct upkg_file *f)
59 {
60         struct music_priv *priv = MUSIC_GET_PRIV(o);
61         EngineMusic *m = ENGINE_MUSIC(o);
62         long size;
63
64         size_t rc;
65
66         priv->nbuf = upkg_export_read(f, priv->buf, sizeof priv->buf);
67         priv->base = 0;
68
69         /* Random field #1 */
70         if (priv->nbuf - priv->base < 2)
71                 return -1;
72         // unpack_16_le(priv->buf+0);
73         priv->base += 2;
74
75         if (f->pkg->version > 61) {
76                 /* Random field #2 */
77                 if (priv->nbuf - priv->base < 4)
78                         return -1;
79                 // unpack_32_le(priv->buf+2);
80                 priv->base += 4;
81         }
82
83         rc = upkg_decode_index(&size, priv->buf+priv->base, priv->nbuf-priv->base);
84         if (rc == 0 || size < 0)
85                 return -1;
86
87         priv->base += rc;
88         priv->len   = size;
89
90         priv->nbuf -= priv->base;
91         memmove(priv->buf, priv->buf+priv->base, priv->nbuf);
92
93         priv->f = f;
94         return 0;
95 }
96
97 static void serializable_init(UPkgSerializable *s)
98 {
99         s->deserialize = deserialize;
100 }
101
102 static void engine_music_init(EngineMusic *m)
103 {
104 }
105
106 static void engine_music_class_init(EngineMusicClass *class)
107 {
108         g_type_class_add_private(class, sizeof (struct music_priv));
109 }
110
111 static void engine_music_class_finalize(EngineMusicClass *class)
112 {
113 }
114
115 G_DEFINE_DYNAMIC_TYPE_EXTENDED(EngineMusic, engine_music, G_TYPE_OBJECT, 0,
116         G_IMPLEMENT_INTERFACE(UPKG_TYPE_SERIALIZABLE, serializable_init)
117         G_IMPLEMENT_INTERFACE(UPKG_TYPE_EXPORTABLE, exportable_init)
118 );
119
120 void music_register(GTypeModule *m)
121 {
122         engine_music_register_type(m);
123 }