From f38da7322b26799e384c90ee87fe6d0e0817eea3 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Wed, 4 Jun 2014 14:09:58 +0100
Subject: [PATCH] [Change] Better handling of music.

---
 snd/music.lua    | 164 ++++++++++++++++++++++++++++++++++++-----------
 src/llua_space.c |  16 +++++
 src/music.c      |  28 ++++++--
 src/music.h      |   1 +
 src/player.c     |   2 +
 src/space.c      |   4 ++
 6 files changed, 170 insertions(+), 45 deletions(-)

diff --git a/snd/music.lua b/snd/music.lua
index 5eaaadb..b87e634 100644
--- a/snd/music.lua
+++ b/snd/music.lua
@@ -9,57 +9,30 @@
 ]]--
 last = "idle"
 function choose(str)
+  -- Means to only change song if needed.
+  if str == nil then
+    str = "ambient"
+  end
+
   if str == "load" then
-    music.load("machina")
-    music.play()
+    choose_load()
 
   elseif str == "land" then
-    planet = space.getPlanet()
-    class = planet:class()
-
-    if class == "M" then
-      mus = "agriculture"
-    elseif name == "Anecu" then -- TODO: We need a way to differenciate aquatics.
-      mus = "ocean"
-    elseif class == "P" then
-      mus = "snow"
-    else
-      if planet:services() > 0 then
-        mus = "cosmostation"
-      else
-        mus = "agriculture"
-      end
-    end
-
-    music.load(mus)
-    music.play()
+    choose_land()
 
   elseif str == "takeoff" then
-    takeoff = { "liftoff", "launch2", "launch3chatstart" }
-    music.load(takeoff[rnd.int(1, #takeoff)])
-    music.play()
+    choose_takeoff()
 
   elseif str == "ambient" then
-    sys = space.getSystem()
-    factions = sys:faction()
-
-    if factions["Collective"] then
-      ambient = { "collective1" }
-    else
-      ambient = { "ambient1", "ambient2", "mission",
-                  "peace1", "peace2", "peace4", "peace6" }
-    end
-    music.load(ambient[rnd.int(1, #ambient)])
-    music.play()
+    choose_ambient()
 
   elseif str == "combat" then
-    music.load("galacticbattle")
-    music.play()
+    choose_battle()
 
   elseif str == "idle" and last ~= "idle" then
     -- We'll play the same as last unless it was takeoff.
     if last == "takeoff" then
-      choose("ambient")
+      choose_ambient()
     else
       choose(last)
     end
@@ -70,3 +43,118 @@ function choose(str)
   end
 end
 
+-- Loading songs.
+function choose_load()
+  music.load("machina")
+  music.play()
+end
+
+-- Landing songs.
+function choose_land()
+  planet = space.getPlanet()
+  class = planet:class()
+
+  if class == "M" then
+    mus = "agriculture"
+  elseif name == "Anecu" then -- TODO: We need a way to differenciate aquatics.
+    mus = "ocean"
+  elseif class == "P" then
+    mus = "snow"
+  else
+    if planet:services() > 0 then
+      mus = "cosmostation"
+    else
+      mus = "agriculture"
+    end
+  end
+
+  music.load(mus)
+  music.play()
+end
+
+-- Takeoff songs.
+function choose_takeoff()
+  -- No need to restart.
+  if last == "takeoff" and music.isPlaying() then
+    return
+  end
+  takeoff = { "liftoff", "launch2", "launch3chatstart" }
+  music.load(takeoff[rnd.int(1, #takeoff)])
+  music.play()
+end
+
+-- Save old data.
+last_sysFaction   = nil
+last_sysNebuDens  = nil
+last_sysNebuVol   = nil
+-- Choose ambient songs.
+function choose_ambient()
+  force = true
+
+  -- Check to see if we want to update.
+  if music.isPlaying() then
+    if last == "takeoff" then
+      return
+    elseif last == "ambient" then
+      force = false
+    end
+  end
+
+  -- Get information about the current system.
+  sys = space.getSystem()
+  factions = sys:faction()
+  nebu_dens, nebu_vol = sys:nebulae()
+
+  -- Check to see if changing faction zone.
+  if not factions[last_sysFaction] then
+    -- Table must not be empty.
+    --if next(factions) ~= nil then
+      force = true
+    --end
+
+    if force then
+      -- Give first value to last faction.
+      for k, v in pairs(factions) do
+        last_sysFaction = k
+        break
+      end
+    end
+  end
+
+  -- Check to see if entering nebulae.
+  nebu = nebu_dens > 0
+  if nebu ~= last_sysNebuDens then
+    force = true
+    last_sysNebuDens = nebu
+  end
+
+  -- Must be forced.
+  if force then
+    -- Stop playing first and have this trigger again.
+    if music.isPlaying() then
+      music.stop()
+      return
+    end
+
+    -- Choose the music, bias by faction first.
+    if factions["Collective"] then
+      ambient = { "collective1" }
+    elseif nebu and rnd.int(0,1) == 0 then
+      ambient = { "ambient1" }
+    else
+      ambient = { "ambient2", "mission",
+          "peace1", "peace2", "peace4", "peace6" }
+    end
+
+    -- Load music and play.
+    music.load(ambient[rnd.int(1, #ambient)])
+    music.play()
+  end
+end
+
+-- Battle songs.
+function choose_battle()
+  music.load("galacticbattle")
+  music.play()
+end
+
diff --git a/src/llua_space.c b/src/llua_space.c
index 7bdabf3..372cb43 100644
--- a/src/llua_space.c
+++ b/src/llua_space.c
@@ -45,12 +45,14 @@ static const luaL_reg planet_methods[] = {
 static int systemL_eq(lua_State* L);
 static int systemL_name(lua_State* L);
 static int systemL_faction(lua_State* L);
+static int systemL_nebulae(lua_State* L);
 static int systemL_jumpdistance(lua_State* L);
 static const luaL_reg system_methods[] = {
   { "__eq",       systemL_eq            },
   { "__tostring", systemL_name          },
   { "name",       systemL_name          },
   { "faction",    systemL_faction       },
+  { "nebulae",    systemL_nebulae       },
   { "jumpDist",   systemL_jumpdistance  },
   { 0, 0 }
 };
@@ -618,6 +620,20 @@ static int systemL_faction(lua_State* L) {
   return 1;
 }
 
+/**
+ * @ingroup META_SYSTEM
+ */
+static int systemL_nebulae(lua_State* L) {
+  LuaSystem* sys;
+  sys = lua_tosystem(L, 1);
+
+  /* Push the density and volatility. */
+  lua_pushnumber(L, sys->s->nebu_density);
+  lua_pushnumber(L, sys->s->nebu_volatility);
+
+  return 2;
+}
+
 /**
  * @ingroup META_SYSTEM
  *
diff --git a/src/music.c b/src/music.c
index 045117a..19a0cb5 100644
--- a/src/music.c
+++ b/src/music.c
@@ -44,11 +44,13 @@ static int music_runLua(char* situation);
 static int musicL_load(lua_State* L);
 static int musicL_play(lua_State* L);
 static int musicL_stop(lua_State* L);
+static int musicL_isPlaying(lua_State* L);
 static const luaL_reg music_methods[] = {
-  { "load",   musicL_load },
-  { "play",   musicL_play },
-  { "stop",   musicL_stop },
-  {0, 0}
+  { "load",       musicL_load       },
+  { "play",       musicL_play       },
+  { "stop",       musicL_stop       },
+  { "isPlaying",  musicL_isPlaying  },
+  {0, 0 }
 }; /**< Music specific methods. */
 
 /* What is available? */
@@ -267,8 +269,6 @@ void music_play(void) {
 }
 
 /**
- * @fn void music_stop(void)
- *
  * @brief Stop the loaded music.
  */
 void music_stop(void) {
@@ -276,7 +276,7 @@ void music_stop(void) {
 
   if(music_music == NULL) return;
 
-  if(Mix_FadeOutMusic(500) < 0)
+  if(Mix_FadeOutMusic(2000) < 0)
     WARN("SDL_Mixer: %s", Mix_GetError());
 }
 
@@ -302,6 +302,15 @@ void music_resume(void) {
   Mix_ResumeMusic();
 }
 
+/**
+ * @brief Check to see if the music is playing.
+ */
+int music_isPlaying(void) {
+  if(music_disabled) return 0; /* Always playing when music is off. */
+
+  return Mix_PlayingMusic();
+}
+
 /**
  * @brief Sets the music to a position in seconds.
  *    @param sec Position to go to in seconds.
@@ -440,3 +449,8 @@ static int musicL_stop(lua_State* L) {
   return 0;
 }
 
+static int musicL_isPlaying(lua_State* L) {
+  lua_pushboolean(L, music_isPlaying());
+  return 1;
+}
+
diff --git a/src/music.h b/src/music.h
index 0f5f18a..65dff1e 100644
--- a/src/music.h
+++ b/src/music.h
@@ -19,6 +19,7 @@ void music_stop(void);
 void music_pause(void);
 void music_resume(void);
 void music_setPos(double sec);
+int  music_isPlaying(void);
 
 /* Lua control. */
 int lua_loadMusic(lua_State* L, int read_only);
diff --git a/src/player.c b/src/player.c
index 3c38423..50f6eb4 100644
--- a/src/player.c
+++ b/src/player.c
@@ -34,6 +34,7 @@
 #include "intro.h"
 #include "perlin.h"
 #include "ai.h"
+#include "music.h"
 #include "player.h"
 
 #define XML_GUI_ID    "GUIs"    /**< XML section identifier for GUI document. */
@@ -2737,6 +2738,7 @@ static int player_parse(xmlNodePtr parent) {
   gl_bindCamera(&player->solid->pos);
 
   /* Initialize the system. */
+  music_choose("takeoff");
   space_init(planet_getSystem(planet));
   map_clear(); /* Sets the map up. */
 
diff --git a/src/space.c b/src/space.c
index 7a7e9fc..0f12bb1 100644
--- a/src/space.c
+++ b/src/space.c
@@ -15,6 +15,7 @@
 #include "spfx.h"
 #include "ltime.h"
 #include "nebulae.h"
+#include "music.h"
 #include "space.h"
 
 #define XML_PLANET_ID       "Planets"
@@ -633,6 +634,9 @@ void space_init(const char* sysname) {
   if(cur_system->interference == 0.)
     interference_alpha = 0.;
 
+  /* See if we should get a new music song. */
+  music_choose(NULL);
+
   /* Reset player enemies. */
   player_enemies = 0;