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