removed clang-format and clang_complete files from the repo
[dosdemo] / src / glut / audio.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #if defined(__WATCOMC__) || defined(_WIN32) || defined(__DJGPP__)
6 #include <malloc.h>
7 #else
8 #include <alloca.h>
9 #endif
10 #include "mikmod.h"
11 #include "audio.h"
12 #include "cfgopt.h"
13
14 #ifdef _WIN32
15 #include <windows.h>
16 #else
17 #include <pthread.h>
18 #include <unistd.h>
19 #endif
20
21 #define SET_MUS_VOL(vol) \
22         do { \
23                 int mv = (vol) * vol_master >> 9; \
24                 Player_SetVolume(mv ? mv + 1 : 0); \
25         } while(0)
26
27 static struct au_module *curmod;
28 static int vol_master, vol_mus, vol_sfx;
29
30 #ifdef _WIN32
31 static DWORD WINAPI upd_thread(void *cls);
32 #else
33 static void *update(void *cls);
34 #endif
35
36 int au_init(void)
37 {
38         curmod = 0;
39         vol_master = vol_mus = vol_sfx = 255;
40
41         if(!opt.music) return 0;
42
43 #if defined(__linux__)
44         MikMod_RegisterDriver(&drv_alsa);
45 #elif defined(__FreeBSD__)
46         MikMod_RegisterDriver(&drv_oss);
47 #elif defined(__sgi__)
48         MikMod_RegisterDriver(&drv_sgi);
49 #elif defined(_WIN32)
50         MikMod_RegisterDriver(&drv_ds);
51 #else
52         MikMod_RegisterDriver(&drv_nos);
53 #endif
54
55         MikMod_RegisterLoader(&load_it);
56         MikMod_RegisterLoader(&load_mod);
57         MikMod_RegisterLoader(&load_s3m);
58         MikMod_RegisterLoader(&load_xm);
59
60         if(MikMod_Init("")) {
61                 fprintf(stderr, "failed ot initialize mikmod: %s\n", MikMod_strerror(MikMod_errno));
62                 return -1;
63         }
64         MikMod_InitThreads();
65
66         {
67 #ifdef _WIN32
68                 HANDLE thr;
69                 if((thr = CreateThread(0, 0, upd_thread, 0, 0, 0))) {
70                         CloseHandle(thr);
71                 }
72 #else
73                 pthread_t upd_thread;
74                 if(pthread_create(&upd_thread, 0, update, 0) == 0) {
75                         pthread_detach(upd_thread);
76                 }
77 #endif
78         }
79         return 0;
80 }
81
82 void au_shutdown(void)
83 {
84         if(opt.music) {
85                 curmod = 0;
86                 MikMod_Exit();
87         }
88 }
89
90 struct au_module *au_load_module(const char *fname)
91 {
92         struct au_module *mod;
93         MODULE *mikmod;
94         char *name = 0, *end;
95
96         if(!(mod = malloc(sizeof *mod))) {
97                 fprintf(stderr, "au_load_module: failed to allocate module\n");
98                 return 0;
99         }
100
101         if(!(mikmod = Player_Load(fname, 128, 0))) {
102                 fprintf(stderr, "au_load_module: failed to load module: %s: %s\n",
103                                 fname, MikMod_strerror(MikMod_errno));
104                 free(mod);
105                 return 0;
106         }
107         mod->impl = mikmod;
108
109         if(mikmod->songname && *mikmod->songname) {
110                 name = alloca(strlen(mikmod->songname) + 1);
111                 strcpy(name, mikmod->songname);
112
113                 end = name + strlen(name) - 1;
114                 while(end >= name && isspace(*end)) {
115                         *end-- = 0;
116                 }
117                 if(!*name) name = 0;
118         }
119
120         if(!name) {
121                 /* fallback to using the filename */
122                 if((name = strrchr(fname, '/')) || (name = strrchr(fname, '\\'))) {
123                         name++;
124                 } else {
125                         name = (char*)fname;
126                 }
127         }
128
129         if(!(mod->name = malloc(strlen(name) + 1))) {
130                 fprintf(stderr, "au_load_module: mod->name malloc failed\n");
131                 Player_Free(mod->impl);
132                 free(mod);
133                 return 0;
134         }
135         strcpy(mod->name, name);
136
137         printf("loaded module \"%s\" (%s)\n", name, fname);
138         return mod;
139 }
140
141 void au_free_module(struct au_module *mod)
142 {
143         if(!mod) return;
144
145         if(mod == curmod) {
146                 au_stop_module(curmod);
147         }
148         Player_Free(mod->impl);
149         free(mod->name);
150         free(mod);
151 }
152
153 int au_play_module(struct au_module *mod)
154 {
155         if(curmod) {
156                 if(curmod == mod) return 0;
157                 au_stop_module(curmod);
158         }
159
160         Player_Start(mod->impl);
161         SET_MUS_VOL(vol_mus);
162         curmod = mod;
163         return 0;
164 }
165
166 void au_update(void)
167 {
168         if(!curmod) return;
169
170         if(!Player_Active()) {
171                 Player_Stop();
172                 curmod = 0;
173         }
174 }
175
176 #ifdef _WIN32
177 static DWORD WINAPI upd_thread(void *cls)
178 #else
179 static void *update(void *cls)
180 #endif
181 {
182         for(;;) {
183                 if(Player_Active()) {
184                         MikMod_Update();
185                 }
186 #ifdef _WIN32
187                 Sleep(10);
188 #else
189                 usleep(10000);
190 #endif
191         }
192         return 0;
193 }
194
195 int au_stop_module(struct au_module *mod)
196 {
197         if(mod && curmod != mod) return -1;
198         if(!curmod) return -1;
199
200         Player_Stop();
201         curmod = 0;
202         return 0;
203 }
204
205 int au_module_state(struct au_module *mod)
206 {
207         if(mod) {
208                 return curmod == mod ? AU_PLAYING : AU_STOPPED;
209         }
210         return curmod ? AU_PLAYING : AU_STOPPED;
211 }
212
213 int au_volume(int vol)
214 {
215         AU_VOLADJ(vol_master, vol);
216         if(vol != vol_master) {
217                 vol_master = vol;
218
219                 au_sfx_volume(vol_sfx);
220                 au_music_volume(vol_mus);
221         }
222         return vol_master;
223 }
224
225 int au_sfx_volume(int vol)
226 {
227         AU_VOLADJ(vol_sfx, vol);
228         vol_sfx = vol;
229         /* TODO */
230         return vol_sfx;
231 }
232
233 int au_music_volume(int vol)
234 {
235         AU_VOLADJ(vol_mus, vol);
236         vol_mus = vol;
237
238         if(curmod) {
239                 SET_MUS_VOL(vol);
240         }
241         return vol_mus;
242 }