]> git.draconx.ca Git - upkg.git/blob - src/music.c
Initial UObject implementation plus a dumb music extractor.
[upkg.git] / src / 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 U_MUSIC_GET_PRIV(o) \
11         G_TYPE_INSTANCE_GET_PRIVATE(o, U_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 serializable_init(UPkgSerializable *s);
24 static void exportable_init(UPkgExportable *e);
25
26 G_DEFINE_TYPE_WITH_CODE(UMusic, u_music, G_TYPE_OBJECT,
27         G_IMPLEMENT_INTERFACE(UPKG_TYPE_SERIALIZABLE, serializable_init)
28         G_IMPLEMENT_INTERFACE(UPKG_TYPE_EXPORTABLE, exportable_init)
29 );
30
31 static int export(GObject *o, FILE *f)
32 {
33         struct music_priv *priv = U_MUSIC_GET_PRIV(o);
34         size_t left = priv->len, rc;
35
36         unsigned char buf[1024];
37
38         if (upkg_export_seek(priv->f, priv->base, SEEK_SET) != 0)
39                 return -1;
40
41         while (left > 0) {
42                 rc = upkg_export_read(priv->f, buf, MIN(left, sizeof buf));
43                 if (rc == 0)
44                         return -1;
45                 if (fwrite(buf, 1, rc, f) != rc)
46                         return -1;
47                 left -= rc;
48         }
49
50         return 0;
51 }
52
53 static int export_name(GObject *o, char *buf, size_t n)
54 {
55         struct music_priv *priv = U_MUSIC_GET_PRIV(o);
56
57         return snprintf(buf, n, "%s", priv->f->name);
58 }
59
60 static void exportable_init(UPkgExportable *e)
61 {
62         e->export      = export;
63         e->export_name = export_name;
64 }
65
66 static int deserialize(GObject *o, struct upkg_file *f)
67 {
68         struct music_priv *priv = U_MUSIC_GET_PRIV(o);
69         UMusic *m = U_MUSIC(o);
70         long size;
71
72         size_t rc;
73
74         priv->nbuf = upkg_export_read(f, priv->buf, sizeof priv->buf);
75         priv->base = 0;
76
77         /* Random field #1 */
78         if (priv->nbuf - priv->base < 2)
79                 return -1;
80         // unpack_16_le(priv->buf+0);
81         priv->base += 2;
82
83         if (f->pkg->version > 61) {
84                 /* Random field #2 */
85                 if (priv->nbuf - priv->base < 4)
86                         return -1;
87                 // unpack_32_le(priv->buf+2);
88                 priv->base += 4;
89         }
90
91         rc = upkg_decode_index(&size, priv->buf+priv->base, priv->nbuf-priv->base);
92         if (rc == 0 || size < 0)
93                 return -1;
94
95         priv->base += rc;
96         priv->len   = size;
97
98         priv->nbuf -= priv->base;
99         memmove(priv->buf, priv->buf+priv->base, priv->nbuf);
100
101         priv->f = f;
102         return 0;
103 }
104
105 static void serializable_init(UPkgSerializable *s)
106 {
107         s->deserialize = deserialize;
108 }
109
110 static void u_music_init(UMusic *o)
111 {
112 }
113
114 static void u_music_class_init(UMusicClass *class)
115 {
116         g_type_class_add_private(class, sizeof (struct music_priv));
117 }