Add an SDL sound backend and use it instead of spawning an external
authorDeanna Phillips <deanna@sdf.lonestar.org>
Sun, 10 Feb 2008 23:32:08 +0000 (18:32 -0500)
committerDeanna Phillips <deanna@sdf.lonestar.org>
Sun, 10 Feb 2008 23:32:08 +0000 (18:32 -0500)
player.  SDL and SDL_mixer are now required.  You may get them from:

http://www.libsdl.org
http://www.libsdl.org/projects/SDL_mixer/

If you have problems building, try uncommenting the extra SDLLIBS and
SDLINCLUDES variables in src/sim/makefile.

res/micropolis.tcl
src/sim/makefile
src/sim/s_msg.c
src/sim/w_sound.c
src/sim/w_sprite.c
src/sim/w_tk.c

index 6c6c03a..01f8749 100644 (file)
@@ -938,21 +938,11 @@ proc UISetChannelVolume {win chan vol} {
 
 
 proc EchoPlaySound {soundspec} {
-  # Temporary workaround to tell Python Sugar app to play sound.
-  global Sound ResourceDir
-  if {$Sound} {
-    #echo PlaySound [lindex $soundspec 0]
-    signal ignore SIGCHLD
-    exec "${ResourceDir}/sounds/player" "${ResourceDir}/sounds/[string tolower [lindex $soundspec 0]].wav" &
-  }
 }
 
 
 proc UIMakeSoundOn {win chan sound {opts ""}} {
-  # Send message to Python to play sound.
-  EchoPlaySound $sound
-
-  #UIDoSoundOn $win "play $sound -replay -channel $chan $opts"
+  playsound $chan $sound $opts
 }
 
 
@@ -964,11 +954,6 @@ proc UIStartSoundOn {win chan sound {opts ""}} {
 }
 
 
-proc UIStopSoundOn {win chan sound {opts ""}} {
-  UIDoSoundOn $win "stop $sound"
-}
-
-
 proc UIMakeSound {chan sound {opts ""}} {
   # Send message to Python to play sound.
   EchoPlaySound $sound
@@ -985,11 +970,6 @@ proc UIStartSound {chan sound {opts ""}} {
 }
 
 
-proc UIStopSound {chan sound {opts ""}} {
-  UIDoSound "sound stop $sound"
-}
-
-
 proc SetupSoundServer {win} {
   AddSoundServer $win
 }
@@ -2537,7 +2517,7 @@ proc EditorToolUp {w x y} {
 
   case [$w ToolState] in \
     7 { # bulldozer
-     UIStopSoundOn $w edit 1
+      stopdozer
     } \
     10 { # chalk
       StopChalk $w
index 13c22c5..9705d6e 100644 (file)
@@ -5,6 +5,12 @@ TCLXHOME = ../tclx
 TCLLIBRARY = /usr/local/lib/tcl
 TKLIBRARY = /usr/local/lib/tk
 
+SDLINCLUDE =
+SDLLIBS = -lSDL -lSDL_mixer
+#SDLINCLUDE += $$(pkg-config -cflags sdl)
+#SDLLIBS += $$(pkg-config -libs sdl)
+
 CC = gcc
 
 OPTFLAGS = -O3
@@ -26,7 +32,8 @@ INCLUDES = \
        -I$(XINCLUDE) \
        -I$(TCLHOME) \
        -I$(TCLXHOME)/src \
-       -I$(TKHOME)
+       -I$(TKHOME) \
+       $(SDLINCLUDE)
 
 CPPFLAGS = $(INCLUDES)
 
@@ -35,7 +42,8 @@ LIBS =        $(TCLXHOME)/libtk.a \
        -lm \
         -lX11 \
         -lXext \
-       -lXpm
+       -lXpm \
+       $(SDLLIBS)
 
 SRCS = \
        sim.c \
index 330f125..d820607 100644 (file)
@@ -340,7 +340,7 @@ doMessage(void)
       MakeSound("city", "Siren");
       break;
     case  21:
-      MakeSound("city", "Monster -speed [MonsterSpeed]");
+      MakeSound("city", "Monster");
       break;
     case 30:
       MakeSound("city", "Explosion-Low");
index b9b323c..2602183 100644 (file)
@@ -1,3 +1,7 @@
+/* 
+ * Portions Copyright (c) 2008 Deanna Phillips <deanna@sdf.lonestar.org>
+ */
+
 /* w_sound.c
  *
  * Micropolis, Unix Version.  This game was released for the Unix platform
  * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
  * NOT APPLY TO YOU.
  */
+#include <SDL/SDL.h>
+#include <SDL/SDL_mixer.h>
 #include "sim.h"
 
 
+#define SIM_NSOUNDS    47
+#define SIM_NCHANNELS  32
+#define DOZER_CHANNEL  0
+#define DOZER_SOUND    "rumble.wav"
+
+struct sound {
+  char *id;
+  char *file;
+  Mix_Chunk *wave;
+};
+
+struct sound sounds[SIM_NSOUNDS] = {
+  { "A",               "a.wav",                NULL },
+  { "Aaah",            "aaah.wav",             NULL },
+  { "Airport",         "airport.wav",          NULL },
+  { "Beep",            "beep.wav",             NULL },
+  { "Boing",           "boing.wav",            NULL },
+  { "Bop",             "bop.wav",              NULL },
+  { "Build",           "build.wav",            NULL },
+  { "Bulldozer",       "bulldozer.wav",        NULL },
+  { "Chalk",           "chalk.wav",            NULL },
+  { "Coal",            "coal.wav",             NULL },
+  { "Com",             "com.wav",              NULL },
+  { "Computer",                "computer.wav",         NULL },
+  { "Cuckoo",          "cuckoo.wav",           NULL },
+  { "E",               "e.wav",                NULL },
+  { "Eraser",          "eraser.wav",           NULL },
+  { "Explosion-High",  "explosion-high.wav",   NULL },
+  { "Explosion-Low",   "explosion-low.wav",    NULL },
+  { "Fire",            "fire.wav",             NULL },
+  { "HeavyTraffic",    "heavytraffic.wav",     NULL },
+  { "HonkHonk-High",   "honkhonk-high.wav",    NULL },
+  { "HonkHonk-Low",    "honkhonk-low.wav",     NULL },
+  { "HonkHonk-Med",    "honkhonk-med.wav",     NULL },
+  { "Ignition",                "ignition.wav",         NULL },
+  { "Ind",             "ind.wav",              NULL },
+  { "Monster",         "monster.wav",          NULL },
+  { "Nuclear",         "nuclear.wav",          NULL },
+  { "O",               "o.wav",                NULL },
+  { "Oop",             "oop.wav",              NULL },
+  { "Park",            "park.wav",             NULL },
+  { "Player",          "player.wav",           NULL },
+  { "Police",          "police.wav",           NULL },
+  { "QuackQuack",      "quackquack.wav",       NULL },
+  { "Query",           "query.wav",            NULL },
+  { "Rail",            "rail.wav",             NULL },
+  { "Res",             "res.wav",              NULL },
+  { "Road",            "road.wav",             NULL },
+  { "Rumble",          "rumble.wav",           NULL },
+  { "Seaport",         "seaport.wav",          NULL },
+  { "Siren",           "siren.wav",            NULL },
+  { "Skid",            "skid.wav",             NULL },
+  { "Sorry",           "sorry.wav",            NULL },
+  { "Stadium",         "stadium.wav",          NULL },
+  { "UhUh",            "uhuh.wav",             NULL },
+  { "Whip",            "whip.wav",             NULL },
+  { "Wire",            "wire.wav",             NULL },
+  { "Woosh",           "woosh.wav",            NULL },
+  { "Zone",            "zone.wav",             NULL }
+};
+
 /* Sound routines */
 
 
 int SoundInitialized = 0;
-short Dozing;
+Mix_Chunk *rumble;
 
 
 InitializeSound()
 {
-  char cmd[256];
+  int reserved_chans;
+  char buf[256];
 
-  SoundInitialized = 1;
+  if (SDL_Init(SDL_INIT_AUDIO) == -1) {
+    fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());
+    return;
+  }
 
-  if (!UserSoundOn) return;
+  if (Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 1, 1024) == -1) {
+    fprintf(stderr, "Mix_OpenAudio: %s\n", Mix_GetError());
+    return;
+  }
+
+  reserved_chans = Mix_ReserveChannels(1);
 
-  Eval("UIInitializeSound");
+  if (reserved_chans != 1) {
+    fprintf(stderr, "Mix_ReserveChannels: %s\n", Mix_GetError());
+    return;
+  }
+
+  if (Mix_AllocateChannels(SIM_NCHANNELS) == -1) {
+    fprintf(stderr, "Mix_AllocateChannels: %s\n", Mix_GetError());
+    return;
+  }
+
+  snprintf(buf, sizeof(buf), "%s/sounds/%s", ResourceDir, DOZER_SOUND);
+  rumble = Mix_LoadWAV(buf);
+
+  if (rumble == NULL) {
+    printf("Mix_LoadWAV: %s\n", Mix_GetError());
+    return;
+  }
+
+  SoundInitialized = 1;
 }
 
 
 ShutDownSound()
 {
-  if (SoundInitialized) {
-    SoundInitialized = 0;
-    Eval("UIShutDownSound");
+  int i;
+  SoundInitialized = 0;
+
+  for (i = 0; i < SIM_NSOUNDS; i++) {
+    if (sounds[i].wave) {
+      Mix_FreeChunk(sounds[i].wave);
+      sounds[i].wave = NULL;
+    }
+  }
+  if (rumble) {
+    Mix_FreeChunk(rumble);
+    rumble = NULL;
   }
+  Mix_CloseAudio();
+  SDL_Quit();
 }
 
 
 MakeSound(char *channel, char *id)
 {
   char buf[256];
+  int i;
 
   if (!UserSoundOn) return;
-  if (!SoundInitialized) InitializeSound();
+  if (!SoundInitialized) return;
 
-  sprintf(buf, "UIMakeSound \"%s\" \"%s\"", channel, id);
-  Eval(buf);
-}
+  for (i = 0; i < SIM_NSOUNDS; i++) {
+    if (!strcmp(sounds[i].id, id))
+      break;
+  }
+  
+  if (sounds[i].wave) {
+    if (Mix_PlayChannel(-1, sounds[i].wave, 0) == -1)
+      fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
+    return;
+  }
+
+  snprintf(buf, sizeof(buf), "%s/sounds/%s", ResourceDir,
+          sounds[i].file);
+
+  sounds[i].wave = Mix_LoadWAV(buf);
 
+  if (sounds[i].wave == NULL) {
+    fprintf(stderr, "Mix_LoadWAV: %s\n", Mix_GetError());
+    return;
+  }
+
+  if (Mix_PlayChannel(-1, sounds[i].wave, 0) == -1)
+    fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
+}
 
 MakeSoundOn(SimView *view, char *channel, char *id)
 {
-  char buf[256];
-
   if (!UserSoundOn) return;
-  if (!SoundInitialized) InitializeSound();
+  if (!SoundInitialized) return;
 
-  sprintf(buf, "UIMakeSoundOn %s \"%s\" \"%s\"",
-         Tk_PathName(view->tkwin), channel, id);
-  Eval(buf);
+  MakeSound(channel, id);
 }
 
 
 StartBulldozer(void)
 {
+  size_t size;
+  char buf[256];
+
   if (!UserSoundOn) return;
-  if (!SoundInitialized) InitializeSound();
-  if (!Dozing) {
-    DoStartSound("edit", "1");
-    Dozing = 1;
+  if (!SoundInitialized) return;
+
+  if (Mix_PlayChannel(DOZER_CHANNEL, rumble, 4) == -1) {
+    printf("Mix_PlayChannel: %s\n", Mix_GetError());
+    return;
   }
 }
 
 
 StopBulldozer(void)
 {
-  if ((!UserSoundOn) || (!SoundInitialized)) return;
-  DoStopSound("1");
-  Dozing = 0;
+  if (!UserSoundOn) return;
+  if (!SoundInitialized) return;
+
+  Mix_HaltChannel(DOZER_CHANNEL);
 }
 
 
-/* comefrom: doKeyEvent */
+/* XXX comefrom: doKeyEvent */
 SoundOff(void)
 {
-  if (!SoundInitialized) InitializeSound();
-  Eval("UISoundOff");
-  Dozing = 0;
+  ShutDownSound();
 }
 
 
 DoStartSound(char *channel, char *id)
 {
-  char buf[256];
+  MakeSound(channel, id);
+}
 
-  sprintf(buf, "UIStartSound %s %s", channel, id);
-  Eval(buf);
+DoStopSound(char *id)
+{
+  StopBulldozer();
 }
 
+SoundCmd(CLIENT_ARGS)
+{
+  if (!strcmp(argv[2], "Rumble"))
+    StartBulldozer();
+  else
+    MakeSound(NULL, argv[2]);
+  return 0;
+}
 
-DoStopSound(char *id)
+DozerCmd(CLIENT_ARGS)
 {
-  char buf[256];
+  StopBulldozer();
+  return 0;
+}
 
-  sprintf(buf, "UIStopSound %s", id);
-  Eval(buf);
+sound_command_init()
+{
+  Tcl_CreateCommand(tk_mainInterp, "playsound", SoundCmd,
+                   (ClientData)NULL, (void (*)()) NULL);
+  Tcl_CreateCommand(tk_mainInterp, "stopdozer", DozerCmd,
+                   (ClientData)NULL, (void (*)()) NULL);
 }
index 3f50989..7ecc045 100644 (file)
@@ -849,7 +849,7 @@ DoShipSprite(SimSprite *sprite)
     if ((Rand16() & 3) == 1) {
       if ((ScenarioID == 2) && /* San Francisco */
          (Rand(10) < 5)) {
-       MakeSound("city", "HonkHonk-Low -speed 80");
+       MakeSound("city", "HonkHonk-Low");
       } else {
        MakeSound("city", "HonkHonk-Low");
       }
@@ -985,7 +985,7 @@ DoMonsterSprite(SimSprite *sprite)
          else z = ND2[d];
          d = 4;
          if (!sprite->sound_count) {
-           MakeSound("city", "Monster -speed [MonsterSpeed]"); /* monster */
+           MakeSound("city", "Monster"); /* monster */
            sprite->sound_count = 50 + Rand(100);
          }
        }
index 027654d..08c16f9 100644 (file)
@@ -774,6 +774,7 @@ tk_main()
   graph_command_init();
   date_command_init();
   sprite_command_init();
+  sound_command_init();
 
 #ifdef CAM
   cam_command_init();
Impressum, Datenschutz