]> git.draconx.ca Git - upkg.git/blob - src/engine/music-modplug.c
Improve GOB rebuild rules for VPATH builds.
[upkg.git] / src / engine / music-modplug.c
1 /*
2  *  upkg: tool for manipulating Unreal Tournament packages.
3  *  Copyright © 2009-2011, 2019 Nick Bowler
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <libmodplug/modplug.h>
22 #include "modplug-types.h"
23
24 #include "music-module.h"
25 #include "upkg.h"
26
27 struct music_mod {
28         ModPlugFile *f;
29         size_t len, alloc;
30         unsigned char buf[];
31 };
32
33 #define BUF_INIT_SIZE 65536
34
35 int music_mod_init(void)
36 {
37         ModPlug_Settings settings = {
38                 .mFlags          = MODPLUG_ENABLE_OVERSAMPLING,
39                 .mChannels       = 2,
40                 .mFrequency      = 44100,
41                 .mResamplingMode = MODPLUG_RESAMPLE_SPLINE,
42                 .mLoopCount      = -1,
43         };
44
45         ModPlug_SetSettings(&settings);
46         return 0;
47 }
48
49 void music_mod_exit(void)
50 {
51 }
52
53 static struct music_mod *readfile(struct upkg_file *f)
54 {
55         struct music_mod *m = malloc(sizeof *m + BUF_INIT_SIZE);
56         if (!m) return NULL;
57         *m = (struct music_mod) {
58                 .alloc = BUF_INIT_SIZE
59         };
60
61         while (1) {
62                 struct music_mod *tmp;
63                 size_t sz = m->alloc - m->len;
64                 
65                 m->len += upkg_export_read(f, m->buf + m->len, sz);
66                 if (m->alloc != m->len) {
67                         if (f->eof) {
68                                 tmp = realloc(m, sizeof *m + m->len);
69                                 return tmp ? tmp : m;
70                         }
71
72                         break;
73                 }
74
75                 tmp = realloc(m, sizeof *m + 2*m->alloc);
76                 if (!tmp)
77                         break;
78                 m = tmp;
79                 m->alloc *= 2;
80         }
81
82         free(m);
83         return NULL;
84 }
85
86 struct music_mod *music_mod_open(struct upkg_file *f)
87 {
88         struct music_mod *m = readfile(f);
89         if (!m) return NULL;
90
91         m->f = ModPlug_Load(m->buf, m->len);
92         if (!m->f) {
93                 free(m);
94                 return NULL;
95         }
96
97         return m;
98 }
99
100 int music_mod_dump(struct music_mod *m, FILE *of)
101 {
102         if (fwrite(m->buf, m->len, 1, of) != 1)
103                 return -1;
104         return 0;
105 }
106
107 void music_mod_close(struct music_mod *m)
108 {
109         ModPlug_Unload(m->f);
110         free(m);
111 }
112
113 const char *music_mod_type(struct music_mod *m)
114 {
115         int type = ModPlug_GetModuleType(m->f);
116
117         if (type & MOD_TYPE_MOD)
118                 return "mod";
119         if (type & MOD_TYPE_S3M)
120                 return "s3m";
121         if (type & MOD_TYPE_XM)
122                 return "xm";
123         if (type & MOD_TYPE_IT)
124                 return "it";
125         return "unknown";
126 }