]> git.draconx.ca Git - upkg.git/blob - src/engine/music.gob
Stop using gnulib's flexmember module.
[upkg.git] / src / engine / music.gob
1 %alltop{
2 /*
3  * upkg: tool for manipulating Unreal Tournament packages.
4  * Copyright © 2009-2012, 2022 Nick Bowler
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 %}
20
21 %ctop{
22 #include <config.h>
23 %}
24
25 %{
26 #include <stdio.h>
27 #include <string.h>
28 #include <uobject/loadable.h>
29 #include <uobject/exportable.h>
30 #include <engine/music-module.h>
31 #include <upkg.h>
32 %}
33
34 %h{
35 #include <uobject/uobject.h>
36 %}
37
38 class Engine:Music from U:Object (dynamic)
39         (interface U:Object:Exportable)
40         (interface U:Object:Loadable)
41 {
42         private struct music_mod *mod = NULL;
43         private unsigned loaded = 0;
44
45         interface U:Object:Loadable
46         private int load(U:Object *uo)
47         {
48                 struct upkg_file *f = uo->pkg_file;
49                 Self *self = SELF(uo);
50
51                 if (!self->_priv->loaded) {
52                         g_return_val_if_fail(f != NULL, -1);
53
54                         if (upkg_export_seek(f, 0, SEEK_SET) != 0)
55                                 return -1;
56
57                         self->_priv->mod = music_mod_open(f);
58                         if (!self->_priv->mod)
59                                 return -1;
60                 }
61
62                 self->_priv->loaded++;
63                 return 0;
64         }
65
66         interface U:Object:Loadable
67         private void unload(U:Object *uo)
68         {
69                 Self *self = SELF(uo);
70
71                 g_return_if_fail(self->_priv->loaded > 0);
72
73                 if (--self->_priv->loaded == 0)
74                         music_mod_close(self->_priv->mod);
75         }
76
77         interface U:Object:Exportable
78         private int export(U:Object *uo, FILE *f)
79         {
80                 Self *self = SELF(uo);
81                 int rc;
82
83                 if (self_load(uo) != 0)
84                         return -1;
85
86                 rc = music_mod_dump(self->_priv->mod, f);
87
88                 self_unload(uo);
89                 return rc;
90         }
91
92         interface U:Object:Exportable
93         private int export_name(U:Object *uo, char *buf, size_t n)
94         {
95                 Self *self = SELF(uo);
96                 const char *type;
97                 int rc;
98
99                 if (self_load(uo) != 0) {
100                         if (n > 0)
101                                 buf[0] = '\0';
102                         return 0;
103                 }
104
105                 type = music_mod_type(self->_priv->mod);
106                 rc = snprintf(buf, n, "%s.%s", uo->pkg_file->name, type);
107
108                 self_unload(uo);
109                 return rc;
110         }
111
112         override (U:Object) int deserialize(U:Object *uo)
113         {
114                 struct upkg_file *f = uo->pkg_file;
115                 size_t rc, pos = 0, buflen;
116                 unsigned char buf[32];
117                 long size;
118
119                 PARENT_HANDLER(uo);
120
121                 buflen = upkg_export_read(f, buf, sizeof buf);
122
123                 /* Unknown field #1 */
124                 if (buflen - pos < 1)
125                         return -1;
126                 pos += 1;
127
128                 if (f->pkg->version > 61) {
129                         /* Unknown field #2 */
130                         if (buflen - pos < 4)
131                                 return -1;
132                         pos += 4;
133                 }
134
135                 rc = upkg_decode_index(&size, buf+pos, buflen-pos);
136                 if (rc == 0 || size < 0 || size > f->len - pos)
137                         return -1;
138                 pos += rc;
139
140                 f->base += pos;
141                 f->len   = size;
142                 upkg_export_seek(f, 0, SEEK_SET);
143
144                 return 0;
145         }
146 }