added the src/glut files
[dosdemo] / src / glut / audio.c
diff --git a/src/glut/audio.c b/src/glut/audio.c
new file mode 100644 (file)
index 0000000..c776d3b
--- /dev/null
@@ -0,0 +1,237 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#if defined(__WATCOMC__) || defined(_WIN32) || defined(__DJGPP__)
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+#include "mikmod.h"
+#include "audio.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#define SET_MUS_VOL(vol) \
+       do { \
+               int mv = (vol) * vol_master >> 9; \
+               Player_SetVolume(mv ? mv + 1 : 0); \
+       } while(0)
+
+static struct au_module *curmod;
+static int vol_master, vol_mus, vol_sfx;
+
+#ifdef _WIN32
+static DWORD WINAPI upd_thread(void *cls);
+#else
+static void *update(void *cls);
+#endif
+
+int au_init(void)
+{
+       curmod = 0;
+       vol_master = vol_mus = vol_sfx = 255;
+
+#if defined(__linux__)
+       MikMod_RegisterDriver(&drv_alsa);
+#elif defined(__FreeBSD__)
+       MikMod_RegisterDriver(&drv_oss);
+#elif defined(__sgi__)
+       MikMod_RegisterDriver(&drv_sgi);
+#elif defined(_WIN32)
+       MikMod_RegisterDriver(&drv_ds);
+#else
+       MikMod_RegisterDriver(&drv_nos);
+#endif
+
+       MikMod_RegisterLoader(&load_it);
+       MikMod_RegisterLoader(&load_mod);
+       MikMod_RegisterLoader(&load_s3m);
+       MikMod_RegisterLoader(&load_xm);
+
+       if(MikMod_Init("")) {
+               fprintf(stderr, "failed ot initialize mikmod: %s\n", MikMod_strerror(MikMod_errno));
+               return -1;
+       }
+       MikMod_InitThreads();
+
+       {
+#ifdef _WIN32
+               HANDLE thr;
+               if((thr = CreateThread(0, 0, update, 0, 0, 0))) {
+                       CloseHandle(thr);
+               }
+#else
+               pthread_t upd_thread;
+               if(pthread_create(&upd_thread, 0, update, 0) == 0) {
+                       pthread_detach(upd_thread);
+               }
+#endif
+       }
+       return 0;
+}
+
+void au_shutdown(void)
+{
+       curmod = 0;
+       MikMod_Exit();
+}
+
+struct au_module *au_load_module(const char *fname)
+{
+       struct au_module *mod;
+       MODULE *mikmod;
+       char *name = 0, *end;
+
+       if(!(mod = malloc(sizeof *mod))) {
+               fprintf(stderr, "au_load_module: failed to allocate module\n");
+               return 0;
+       }
+
+       if(!(mikmod = Player_Load(fname, 128, 0))) {
+               fprintf(stderr, "au_load_module: failed to load module: %s: %s\n",
+                               fname, MikMod_strerror(MikMod_errno));
+               free(mod);
+               return 0;
+       }
+       mod->impl = mikmod;
+
+       if(mikmod->songname && *mikmod->songname) {
+               name = alloca(strlen(mikmod->songname) + 1);
+               strcpy(name, mikmod->songname);
+
+               end = name + strlen(name) - 1;
+               while(end >= name && isspace(*end)) {
+                       *end-- = 0;
+               }
+               if(!*name) name = 0;
+       }
+
+       if(!name) {
+               /* fallback to using the filename */
+               if((name = strrchr(fname, '/')) || (name = strrchr(fname, '\\'))) {
+                       name++;
+               } else {
+                       name = (char*)fname;
+               }
+       }
+
+       if(!(mod->name = malloc(strlen(name) + 1))) {
+               fprintf(stderr, "au_load_module: mod->name malloc failed\n");
+               Player_Free(mod->impl);
+               free(mod);
+               return 0;
+       }
+       strcpy(mod->name, name);
+
+       printf("loaded module \"%s\" (%s)\n", name, fname);
+       return mod;
+}
+
+void au_free_module(struct au_module *mod)
+{
+       if(!mod) return;
+
+       if(mod == curmod) {
+               au_stop_module(curmod);
+       }
+       Player_Free(mod->impl);
+       free(mod->name);
+       free(mod);
+}
+
+int au_play_module(struct au_module *mod)
+{
+       if(curmod) {
+               if(curmod == mod) return 0;
+               au_stop_module(curmod);
+       }
+
+       Player_Start(mod->impl);
+       SET_MUS_VOL(vol_mus);
+       curmod = mod;
+       return 0;
+}
+
+void au_update(void)
+{
+       if(!curmod) return;
+
+       if(!Player_Active()) {
+               Player_Stop();
+               curmod = 0;
+       }
+}
+
+#ifdef _WIN32
+static DWORD WINAPI upd_thread(void *cls);
+#else
+static void *update(void *cls)
+#endif
+{
+       for(;;) {
+               if(Player_Active()) {
+                       MikMod_Update();
+               }
+#ifdef _WIN32
+               Sleep(10);
+#else
+               usleep(10000);
+#endif
+       }
+       return 0;
+}
+
+int au_stop_module(struct au_module *mod)
+{
+       if(mod && curmod != mod) return -1;
+       if(!curmod) return -1;
+
+       Player_Stop();
+       curmod = 0;
+       return 0;
+}
+
+int au_module_state(struct au_module *mod)
+{
+       if(mod) {
+               return curmod == mod ? AU_PLAYING : AU_STOPPED;
+       }
+       return curmod ? AU_PLAYING : AU_STOPPED;
+}
+
+int au_volume(int vol)
+{
+       AU_VOLADJ(vol_master, vol);
+       if(vol != vol_master) {
+               vol_master = vol;
+
+               au_sfx_volume(vol_sfx);
+               au_music_volume(vol_mus);
+       }
+       return vol_master;
+}
+
+int au_sfx_volume(int vol)
+{
+       AU_VOLADJ(vol_sfx, vol);
+       vol_sfx = vol;
+       /* TODO */
+       return vol_sfx;
+}
+
+int au_music_volume(int vol)
+{
+       AU_VOLADJ(vol_mus, vol);
+       vol_mus = vol;
+
+       if(curmod) {
+               SET_MUS_VOL(vol);
+       }
+       return vol_mus;
+}