URI: 
       tsound.c - vaccinewars - be a doctor and try to vaccinate the world
  HTML git clone git://src.adamsgaard.dk/vaccinewars
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tsound.c (6512B)
       ---
            1 /************************************************************************
            2  * sound.c        dopewars sound system                                 *
            3  * Copyright (C)  1998-2021  Ben Webb                                   *
            4  *                Email: benwebb@users.sf.net                           *
            5  *                WWW: https://dopewars.sourceforge.io/                 *
            6  *                                                                      *
            7  * This program is free software; you can redistribute it and/or        *
            8  * modify it under the terms of the GNU General Public License          *
            9  * as published by the Free Software Foundation; either version 2       *
           10  * of the License, or (at your option) any later version.               *
           11  *                                                                      *
           12  * This program is distributed in the hope that it will be useful,      *
           13  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
           14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
           15  * GNU General Public License for more details.                         *
           16  *                                                                      *
           17  * You should have received a copy of the GNU General Public License    *
           18  * along with this program; if not, write to the Free Software          *
           19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,               *
           20  *                   MA  02111-1307, USA.                               *
           21  ************************************************************************/
           22 
           23 #ifdef HAVE_CONFIG_H
           24 #include <config.h>
           25 #endif
           26 
           27 #include <glib.h>
           28 #include <string.h>
           29 
           30 #ifdef PLUGINS
           31 #include <sys/types.h>
           32 #include <dirent.h>
           33 #include <dlfcn.h>
           34 #else
           35 #include "plugins/sound_sdl.h"
           36 #include "plugins/sound_esd.h"
           37 #include "plugins/sound_winmm.h"
           38 #ifdef HAVE_COCOA
           39 SoundDriver *sound_cocoa_init(void);
           40 #endif
           41 #endif
           42 
           43 #include "dopewars.h"
           44 #include "log.h"
           45 #include "nls.h"
           46 #include "sound.h"
           47 
           48 #define NOPLUGIN "none"
           49 
           50 static SoundDriver *driver = NULL;
           51 static GSList *driverlist = NULL;
           52 typedef SoundDriver *(*InitFunc)(void);
           53 static gboolean sound_enabled = TRUE;
           54 
           55 gchar *GetPluginList(void)
           56 {
           57   GSList *listpt;
           58   GString *plugins;
           59   gchar *retstr;
           60 
           61   plugins = g_string_new("\""NOPLUGIN"\"");
           62   for (listpt = driverlist; listpt; listpt = g_slist_next(listpt)) {
           63     SoundDriver *drivpt = (SoundDriver *)listpt->data;
           64 
           65     if (drivpt && drivpt->name) {
           66       g_string_append_printf(plugins, ", \"%s\"", drivpt->name);
           67     }
           68   }
           69   retstr = plugins->str;
           70   g_string_free(plugins, FALSE);
           71   return retstr;
           72 }
           73 
           74 static void AddPlugin(InitFunc ifunc, void *module)
           75 {
           76   SoundDriver *newdriver = (*ifunc)();
           77 
           78   if (newdriver) {
           79     dopelog(5, 0, "%s sound plugin init OK", newdriver->name);
           80     newdriver->module = module;
           81     driverlist = g_slist_append(driverlist, newdriver);
           82   }
           83 }
           84 
           85 #ifdef PLUGINS
           86 static void OpenModule(const gchar *modname, const gchar *fullname)
           87 {
           88   InitFunc ifunc;
           89   gint len = strlen(modname);
           90   void *soundmodule;
           91 
           92   if (len > 6 && strncmp(modname, "lib", 3) == 0
           93       && strcmp(modname + len - 3, ".so") == 0) {
           94     GString *funcname;
           95 
           96     soundmodule = dlopen(fullname, RTLD_NOW);
           97     if (!soundmodule) {
           98       /* FIXME: using dlerror() here causes a segfault later in the program */
           99       dopelog(3, 0, "dlopen of %s failed: %s", fullname, dlerror());
          100       return;
          101     }
          102 
          103     funcname = g_string_new(modname);
          104     g_string_truncate(funcname, len - 3);
          105     g_string_erase(funcname, 0, 3);
          106     g_string_append(funcname, "_init");
          107     ifunc = dlsym(soundmodule, funcname->str);
          108     if (ifunc) {
          109       AddPlugin(ifunc, soundmodule);
          110     } else {
          111       dopelog(3, 0, "dlsym (%s) failed: %s", funcname->str, dlerror());
          112       dlclose(soundmodule);
          113     }
          114     g_string_free(funcname, TRUE);
          115   }
          116 }
          117 
          118 static void ScanPluginDir(const gchar *dirname)
          119 {
          120   DIR *dir;
          121 
          122   dir = opendir(dirname);
          123   if (dir) {
          124     struct dirent *fileinfo;
          125     GString *modname;
          126 
          127     modname = g_string_new("");
          128     do {
          129       fileinfo = readdir(dir);
          130       if (fileinfo) {
          131         g_string_assign(modname, dirname);
          132         g_string_append_c(modname, G_DIR_SEPARATOR);
          133         g_string_append(modname, fileinfo->d_name);
          134         OpenModule(fileinfo->d_name, modname->str);
          135       }
          136     } while (fileinfo);
          137     g_string_free(modname, TRUE);
          138     closedir(dir);
          139   } else {
          140     dopelog(5, 0, "Cannot open dir %s", dirname);
          141   }
          142 }
          143 #endif
          144 
          145 void SoundInit(void)
          146 {
          147 #ifdef PLUGINS
          148   ScanPluginDir(PLUGINDIR);
          149   ScanPluginDir("src/plugins/.libs");
          150   ScanPluginDir("plugins/.libs");
          151 #else
          152 #ifdef HAVE_ESD
          153   AddPlugin(sound_esd_init, NULL);
          154 #endif
          155 #ifdef HAVE_SDL_MIXER
          156   AddPlugin(sound_sdl_init, NULL);
          157 #endif
          158 #ifdef HAVE_WINMM
          159   AddPlugin(sound_winmm_init, NULL);
          160 #endif
          161 #ifdef HAVE_COCOA
          162   AddPlugin(sound_cocoa_init, NULL);
          163 #endif
          164 #endif
          165   driver = NULL;
          166 }
          167 
          168 static SoundDriver *GetPlugin(gchar *drivername)
          169 {
          170   GSList *listpt;
          171 
          172   for (listpt = driverlist; listpt; listpt = g_slist_next(listpt)) {
          173     SoundDriver *drivpt = (SoundDriver *)listpt->data;
          174 
          175     if (drivpt && drivpt->name
          176         && (!drivername || strcmp(drivpt->name, drivername) == 0)) {
          177       return drivpt;
          178     }
          179   }
          180   return NULL;
          181 }
          182 
          183 void SoundOpen(gchar *drivername)
          184 {
          185   if (!drivername || strcmp(drivername, NOPLUGIN) != 0) {
          186     driver = GetPlugin(drivername);
          187     if (driver) {
          188       if (driver->open) {
          189         dopelog(3, 0, "Using plugin %s", driver->name);
          190         driver->open();
          191       }
          192     } else if (drivername) {
          193       gchar *plugins, *err;
          194 
          195       plugins = GetPluginList();
          196       err = g_strdup_printf(_("Invalid plugin \"%s\" selected.\n"
          197                               "(%s available; now using \"%s\".)"),
          198                             drivername, plugins, NOPLUGIN);
          199       g_log(NULL, G_LOG_LEVEL_CRITICAL, "%s", err);
          200       g_free(plugins);
          201       g_free(err);
          202     }
          203   }
          204   sound_enabled = TRUE;
          205 }
          206 
          207 void SoundClose(void)
          208 {
          209 #ifdef PLUGINS
          210   GSList *listpt;
          211   SoundDriver *listdriv;
          212 #endif
          213 
          214   if (driver && driver->close) {
          215     driver->close();
          216     driver = NULL;
          217   }
          218 #ifdef PLUGINS
          219   for (listpt = driverlist; listpt; listpt = g_slist_next(listpt)) {
          220     listdriv = (SoundDriver *)listpt->data;
          221     if (listdriv && listdriv->module) {
          222       dlclose(listdriv->module);
          223     }
          224   }
          225 #endif
          226   g_slist_free(driverlist);
          227   driverlist = NULL;
          228 }
          229 
          230 void SoundPlay(const gchar *snd)
          231 {
          232   if (sound_enabled && driver && driver->play && snd && snd[0]) {
          233     driver->play(snd);
          234   }
          235 }
          236 
          237 void SoundEnable(gboolean enable)
          238 {
          239   sound_enabled = enable;
          240 }
          241 
          242 gboolean IsSoundEnabled(void)
          243 {
          244   return sound_enabled;
          245 }