From 9178376c287b7afaad69aa9abc1ad30f9f822765 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Wed, 4 Sep 2013 15:19:04 +0100
Subject: [PATCH] [Change] Split engine sounds and GUI sounds for player. [Fix]
 Some issues in sound.c [Add] More documentation.

---
 src/input.c  |  86 ++++++++++++++------
 src/pilot.c  |   6 ++
 src/player.c | 223 +++++++++++++++++++++++++++++++++++++++++++--------
 src/player.h |   4 +
 src/sound.c  |   6 +-
 5 files changed, 266 insertions(+), 59 deletions(-)

diff --git a/src/input.c b/src/input.c
index 7edc9b8..57dfb4e 100644
--- a/src/input.c
+++ b/src/input.c
@@ -1,3 +1,9 @@
+/**
+ * @file input.c
+ *
+ * @brief Handle all the keybindings and input.
+ */
+
 #include "lephisto.h"
 #include "log.h"
 #include "player.h"
@@ -8,18 +14,18 @@
 #include "map.h"
 #include "input.h"
 
-#define KEY_PRESS   ( 1.)
-#define KEY_RELEASE (-1.)
+#define KEY_PRESS   ( 1.) /**< Key is pressed. */
+#define KEY_RELEASE (-1.) /**< Key is released. */
 
 /* Keybind structure. */
 typedef struct Keybind_ {
-  char* name;       /* Keybinding name, taken from keybindNames[] */
-  KeybindType type; /* type, defined in player.h. */
-  unsigned int key; /* Key/axis/button event number. */
-  double reverse;   /* 1. if normal, -1 if reversed, only useful for joystick axis. */
+  char* name;       /**< Keybinding name, taken from keybindNames[] */
+  KeybindType type; /**< type, defined in player.h. */
+  unsigned int key; /**< Key/axis/button event number. */
+  double reverse;   /**< 1. if normal, -1 if reversed, only useful for joystick axis. */
 } Keybind;
 
-static Keybind** input_keybinds; /* Contains the players keybindings. */
+static Keybind** input_keybinds; /**< Contains the players keybindings. */
 
 
 /* Name of each keybinding. */
@@ -33,8 +39,8 @@ const char* keybindNames[] = {
   "end" }; /* Must terminate at the end. */
 
 /* Accel hacks. */
-static unsigned int input_accelLast  = 0;   /* Used to see if double tap. */
-unsigned int input_afterburnSensibility = 200;  /* ms between taps to afterburn. */
+static unsigned int input_accelLast  = 0;       /**< Used to see if double tap. */
+unsigned int input_afterburnSensibility = 200;  /**< ms between taps to afterburn. */
 
 /* From player.c */
 extern double player_turn;
@@ -43,7 +49,11 @@ extern unsigned int player_target;
 extern int show_fps;
 
 
-/* Set the default input keys. */
+/**
+ * @fn void input_setDefault(void)
+ *
+ * @brief Set the default input keys.
+ */
 void input_setDefault(void) {
   /* Movement. */
   input_setKeybind("accel",           KEYBIND_KEYBOARD, SDLK_w,           0);
@@ -76,7 +86,11 @@ void input_setDefault(void) {
   input_setKeybind("info",            KEYBIND_KEYBOARD, SDLK_i,           0);
 }
 
-/* Initialization/exit functions (does not assign keys). */
+/**
+ * @fn void input_init(void)
+ *
+ * @brief Initialize the input subsystem (does not set keys).
+ */
 void input_init(void) {
   Keybind* tmp;
   int i;
@@ -94,6 +108,11 @@ void input_init(void) {
   }
 }
 
+/**
+ * @fn void input_exit(void)
+ *
+ * @brief Exit the input subsystem.
+ */
 void input_exit(void) {
   int i;
   for(i = 0; strcmp(keybindNames[i], "end"); i++)
@@ -101,7 +120,15 @@ void input_exit(void) {
   free(input_keybinds);
 }
 
-/* Binds key of type [type] to action keybind. */
+/**
+ * @fn void input_setKeybind(char* keybind, KeybindType type, int key, int reverse)
+ *
+ * @brief Bind a key of type to action keybind.
+ *    @param keybind The name of the keybind defined above.
+ *    @param type The type of the keybind.
+ *    @param key The key to bind to.
+ *    @param reverse Whether to reverse it or not.
+ */
 void input_setKeybind(char* keybind, KeybindType type, int key, int reverse) {
   int i;
   for(i = 0; strcmp(keybindNames[i], "end"); i++)
@@ -114,7 +141,10 @@ void input_setKeybind(char* keybind, KeybindType type, int key, int reverse) {
   WARN("Unable to set keybind '%s', That command does not exist.", keybind);
 }
 
-/* Get the value of a keybind. */
+/* @fn int input_getKeybind(char* keybind, KeybindType* type, int* reverse)
+ *
+ * @brief Get the value of a keybind.
+ */
 int input_getKeybind(char* keybind, KeybindType* type, int* reverse) {
   int i;
   for(i = 0; strcmp(keybindNames[i], "end"); i++)
@@ -128,14 +158,16 @@ int input_getKeybind(char* keybind, KeybindType* type, int* reverse) {
   return -1;
 }
 
-/* == Run input method. ================================================ */
-/* keynum : Index of the input_keybinds keybind. */
-/* value  : Value of keypress (defined above). */
-/* abs    : Whether or not it's an abs value (For those pesky joysticks. */
-/* ===================================================================== */
+/**
+ * @fn static void input_key(int keynum, double value, int kabs)
+ *
+ * @brief Run the input command.
+ *    @param keynum The index of the keybind.
+ *    @param value The value of the keypress (defined above).
+ *    @param abs Whether or not it's an absolute value (for the joystick).
+ */
 #define KEY(s)   (strcmp(input_keybinds[keynum]->name, s)==0)
 #define INGAME() (!toolkit)
-/* We won't be having any more funny stuff from VLack.. */
 #define NOHYP() \
   (player && !pilot_isFlag(player, PILOT_HYP_PREP) && \
   !pilot_isFlag(player, PILOT_HYP_BEGIN) && \
@@ -200,13 +232,13 @@ static void input_key(int keynum, double value, int kabs) {
   }
   /* Targetting. */
   else if(INGAME() && KEY("target")) {
-    if(value == KEY_PRESS) player_target = pilot_getNextID(player_target);
+    if(value == KEY_PRESS) player_targetNext();
   }
   else if(INGAME() && KEY("target_nearest")) {
-    if(value == KEY_PRESS) player_target = pilot_getNearestPilot(player);
+    if(value == KEY_PRESS) player_targetNearest();
   }
   else if(INGAME() && KEY("target_hostile")) {
-    if(value == KEY_PRESS) player_target = pilot_getNearestHostile();
+    if(value == KEY_PRESS) player_targetHostile();
   }
   /* Face the target. */
   else if(KEY("face")) {
@@ -349,9 +381,15 @@ static void input_keyup(SDLKey key) {
     }
 }
 
-/* Global input. */
 
-/* Just seperates the event types. */
+/**
+ * @fn void input_handle(SDL_Event* event)
+ *
+ * @brief Handle global input.
+ *
+ * Basically seperates the event types.
+ *    @param event Incoming SDL_Event.
+ */
 void input_handle(SDL_Event* event) {
   /* Pause the game if it is unfocused. */
   if(event->type == SDL_ACTIVEEVENT) {
diff --git a/src/pilot.c b/src/pilot.c
index a27dd5a..a229d3b 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -1,3 +1,9 @@
+/**
+ * @file pilot.c
+ *
+ * @brief Handles the pilot stuff.
+ */
+
 #include <string.h>
 #include <math.h>
 #include <stdlib.h>
diff --git a/src/player.c b/src/player.c
index 7214d31..cf74034 100644
--- a/src/player.c
+++ b/src/player.c
@@ -43,8 +43,9 @@
 #define TARGET_WIDTH  128             /**< Width of target graphics. */
 #define TARGET_HEIGHT 96              /**< Height of target graphics. */
 
-#define PLAYER_RESERVED_CHANNELS 4    /**< Number of channels to reserve for player sounds. */
-#define PLAYER_CHANNEL           0    /**< Player channel. */
+#define PLAYER_RESERVED_CHANNELS 6    /**< Number of channels to reserve for player sounds. */
+#define PLAYER_ENGINE_CHANNEL    9    /**< Player channel for engine noises. */
+#define PLAYER_GUI_CHANNEL       9    /**< Player channel. */
 
 /* Player stuff. */
 Pilot* player = NULL;                   /**< The player. */
@@ -156,8 +157,7 @@ static void player_newMake(void);
 static void player_newShipMake(char* name);
 /* Sound. */
 static void player_initSound(void);
-static void player_playSound(int sound, int once);
-static void player_stopSound(void);
+/*static void player_stopSound(void) */
 /* Gui. */
 static void rect_parse(const xmlNodePtr parent,
                        double* x, double* y, double* w, double* h);
@@ -479,7 +479,8 @@ static void player_initSound(void) {
   if(player_soundReserved) return;
 
   sound_reserve(PLAYER_RESERVED_CHANNELS);
-  sound_createGroup(PLAYER_CHANNEL, 0, PLAYER_RESERVED_CHANNELS);
+  sound_createGroup(PLAYER_ENGINE_CHANNEL, 0, 1); /* Channel for engine noises. */
+  sound_createGroup(PLAYER_GUI_CHANNEL, 1, PLAYER_RESERVED_CHANNELS-1);
   player_soundReserved = 1;
 }
 
@@ -490,18 +491,20 @@ static void player_initSound(void) {
  *    @param sound ID of the sound to play.
  *    @param once Play only once?
  */
-static void player_playSound(int sound, int once) {
-  sound_playGroup(PLAYER_CHANNEL, sound, once);
+void player_playSound(int sound, int once) {
+  sound_playGroup(PLAYER_GUI_CHANNEL, sound, once);
 }
 
+#if 0
 /**
  * @fn static void player_stopSound(void)
  *
  * @brief Stop playing player sounds.
  */
 static void player_stopSound(void) {
-  sound_stopGroup(PLAYER_CHANNEL);
+  sound_stopGroup(PLAYER_GUI_CHANNEL);
 }
+#endif
 
 /**
  * @fn void player_message(const char* fmt, ...)
@@ -1010,7 +1013,12 @@ static void gui_renderBar(const glColour* c, const Rect* r, const double w) {
   glEnd();
 }
 
-/* Init GUI. */
+/**
+ * @fn int gui_init(void)
+ *
+ * @brief Initialize the GUI system.
+ *    @return 0 on success.
+ */
 int gui_init(void) {
   /* Set graphics to NULL. */
   gui.gfx_frame = NULL;
@@ -1024,10 +1032,21 @@ int gui_init(void) {
   gui.msg.y = 30;
   msg_stack = calloc(msg_max, sizeof(Msg));
 
+  if(msg_stack == NULL) {
+    ERR("Out of memory!");
+    return -1;
+  }
+
   return 0;
 }
 
-/* Attempts to load the actual gui. */
+/**
+ * @fn int gui_load(const char* name)
+ *
+ * @brief Attempt to load the actual GUI.
+ *    @brief name Name of the GUI to load.
+ *    @brief 0 on success.
+ */
 int gui_load(const char* name) {
   uint32_t bufsize;
   char* buf = pack_readfile(DATA, GUI_DATA, &bufsize);
@@ -1265,7 +1284,11 @@ static int gui_parse(const xmlNodePtr parent, const char* name) {
 }
 #undef RELATIVIZE
 
-/* Free the GUI. */
+/**
+ * @fn void gui_free(void)
+ *
+ * @brief Free the GUI.
+ */
 void gui_free(void) {
   if(gui.gfx_frame)     gl_freeTexture(gui.gfx_frame);
   if(gui.gfx_targetPilot)  gl_freeTexture(gui.gfx_targetPilot);
@@ -1274,8 +1297,12 @@ void gui_free(void) {
   free(msg_stack);
 }
 
-/* Used in pilot.c */
-/* Basically uses keyboard input instead of AI input. */
+/**
+ * @fn void player_think(Pilot* pplayer)
+ *
+ * @brief Basically uses keyboard input instead of AI input. Used in pilot.c.
+ *    @param pplayer Player to think.
+ */
 void player_think(Pilot* pplayer) {
   /* Last I checked, the dead didn't think.. */
   if(pilot_isFlag(pplayer, PILOT_DEAD)) {
@@ -1330,7 +1357,16 @@ void player_think(Pilot* pplayer) {
 
 }
 
-/* Modify the radar resolution. */
+/*
+ * For use in keybindings.
+ */
+/**
+ * @fn void player_setRadarRel(int mod)
+ *
+ * @brief Modify the radar resolution.
+ *    @param mod Number of intervals to jump (up or down).
+ */
+
 void player_setRadarRel(int mod) {
   gui.radar.res += mod * RADAR_RES_INTERVAL;
   if(gui.radar.res > RADAR_RES_MAX) gui.radar.res = RADAR_RES_MAX;
@@ -1339,7 +1375,11 @@ void player_setRadarRel(int mod) {
   player_message("Radar set to %dx.", (int)gui.radar.res);
 }
 
-/* Get the next secondary weapon. */
+/**
+ * @fn void player_secondaryNext(void)
+ *
+ * @brief Get the next secondary weapon.
+ */
 void player_secondaryNext(void) {
   int i = 0;
 
@@ -1364,7 +1404,11 @@ void player_secondaryNext(void) {
   pilot_setAmmo(player);
 }
 
-/* Cycle through planet targets. */
+/**
+ * @fn void player_targetPlanet(void)
+ *
+ * @brief Cycle through planet targets.
+ */
 void player_targetPlanet(void) {
   hyperspace_target = -1;
   player_rmFlag(PLAYER_LANDACK);
@@ -1382,7 +1426,11 @@ void player_targetPlanet(void) {
     planet_target = -1;
 }
 
-/* Attempt to land or target closest planet if no land target. */
+/**
+ * fn void player_land(void)
+ *
+ * @brief Try to land or target closest planet if no land target.
+ */
 void player_land(void) {
   int i;
   int tp;
@@ -1450,6 +1498,11 @@ void player_land(void) {
   }
 }
 
+/**
+ * @fn void player_targetHyperspace(void)
+ *
+ * @brief Get a hyperspace target.
+ */
 void player_targetHyperspace(void) {
   planet_target = -1; /* Remove planet target. */
   player_rmFlag(PLAYER_LANDACK); /* Get rid of landing permission. */
@@ -1460,15 +1513,20 @@ void player_targetHyperspace(void) {
     hyperspace_target = -1;
 }
 
-/* Actually attempt to jump into hyperspace. */
+/**
+ * @fn void player_jump(void)
+ *
+ * @brief Actually attempt to jump in hyperspace.
+ */
 void player_jump(void) {
+  int i;
   if((hyperspace_target == -1) ||
      pilot_isFlag(player, PILOT_HYP_PREP) ||
      pilot_isFlag(player, PILOT_HYP_BEGIN) ||
      pilot_isFlag(player, PILOT_HYPERSPACE))
     return;
 
-  int i = space_hyperspace(player);
+  i = space_hyperspace(player);
 
   if(i == -1)
     player_message("You are too close to gravity centers to initiate hyperspace.");
@@ -1480,7 +1538,11 @@ void player_jump(void) {
     player_message("Preparing for hyperspace.");
 }
 
-/* Player actually broke hyperspace (Let's enter a new system). */
+/**
+ * @fn void player_brokeHyperspace(void)
+ *
+ * @brief Player actually broke hyperspace (entering new system).
+ */
 void player_brokeHyperspace(void) {
   unsigned int tl, th;
 
@@ -1514,7 +1576,12 @@ void player_brokeHyperspace(void) {
   player_message("BANG!");
 }
 
-/* Make the player face her hyperspace target. */
+/**
+ * @fn double player_faceHyperspace(void)
+ *
+ * @brief Make player face her hyperspace target.
+ *    @return direction to face.
+ */
 double player_faceHyperspace(void) {
   double a;
   a = ANGLE(systems_stack[cur_system->jumps[hyperspace_target]].pos.x -
@@ -1525,40 +1592,109 @@ double player_faceHyperspace(void) {
   return pilot_face(player, a);
 }
 
-/* Activate afterburner. */
+/**
+ * @fn void player_afterburn(void)
+ *
+ * @brief Activate the afterburner.
+ */
 void player_afterburn(void) {
   /* TODO: Fancy effects. */
   if((player != NULL) && (player->afterburner != NULL)) {
     player_setFlag(PLAYER_AFTERBURNER);
     pilot_setFlag(player, PILOT_AFTERBURNER);
     spfx_shake(player->afterburner->outfit->u.afb.rumble * SHAKE_MAX);
-    player_playSound(player->afterburner->outfit->u.afb.sound, 0);
+    sound_stopGroup(PLAYER_ENGINE_CHANNEL);
+    sound_playGroup(PLAYER_ENGINE_CHANNEL,
+        player->afterburner->outfit->u.afb.sound, 0);
   }
 }
 
+/**
+ * @fn void player_afterburnOver(void)
+ *
+ * @brief Deactivate the afterburner.
+ */
 void player_afterburnOver(void) {
   if((player != NULL) && (player->afterburner != NULL)) {
     player_rmFlag(PLAYER_AFTERBURNER);
     pilot_rmFlag(player, PILOT_AFTERBURNER);
-    player_stopSound();
+    sound_stopGroup(PLAYER_ENGINE_CHANNEL);
   }
 }
 
-/* Start accelerating. */
+/**
+ * @fn void player_accel(double acc)
+ *
+ * @brief Start accelerating.
+ *    @param acc How much thrust should be applied of maximum (0 - 1).
+ */
 void player_accel(double acc) {
   if(player != NULL) {
     player_acc = acc;
-    player_playSound(player->ship->sound, 0);
+    sound_stopGroup(PLAYER_ENGINE_CHANNEL);
+    sound_playGroup(PLAYER_ENGINE_CHANNEL,
+        player->ship->sound, 0);
   }
 }
 
+/**
+ * @fn void player_accelOver(void)
+ *
+ * @brief Done accelerating.
+ */
 void player_accelOver(void) {
   player_acc = 0;
-  player_stopSound();
+  sound_stopGroup(PLAYER_ENGINE_CHANNEL);
 }
 
-/* Take a screenshot. */
-static int screenshot_cur = 0;
+/**
+ * @fn void player_targetHostile(void)
+ *
+ * @brief Target the nearest hostile enemy to the player.
+ */
+void player_targetHostile(void) {
+  unsigned int tp;
+  int i;
+  double d, td;
+
+  tp = PLAYER_ID;
+  d = 0;
+  for(i = 0; i < pilot_nstack; i++)
+    if(pilot_isFlag(pilot_stack[i], PILOT_HOSTILE) ||
+        areEnemies(FACTION_PLAYER, pilot_stack[i]->faction)) {
+      td = vect_dist(&pilot_stack[i]->solid->pos, &player->solid->pos);
+      if(!pilot_isDisabled(pilot_stack[i]) && ((tp == PLAYER_ID) || (td < d))) {
+        d = td;
+        tp = pilot_stack[i]->id;
+      }
+    }
+  player_target = tp;
+}
+
+/**
+ * @fn void player_targetNext(void)
+ *
+ * @brief Cycles to next target.
+ */
+void player_targetNext(void) {
+  player_target = pilot_getNextID(player_target);
+}
+
+/**
+ * @fn player_targetNearest(void)
+ *
+ * @brief Player targets nearest pilot.
+ */
+void player_targetNearest(void) {
+  player_target = pilot_getNearestPilot(player);
+}
+
+/**
+ * @fn void player_screenshot(void)
+ *
+ * @brief Take a screenshot.
+ */
+static int screenshot_cur = 0;  /**< Current screenshot at. */
 void player_screenshot(void) {
   FILE* fp;
   int done;
@@ -1594,13 +1730,21 @@ void player_screenshot(void) {
   gl_screenshot(filename);
 }
 
-/* Player go pwned. */
+/**
+ * @fn void player_dead(void)
+ *
+ * @brief Player got killed.
+ */
 void player_dead(void) {
   gui_xoff = 0.;
   gui_yoff = 0.;
 }
 
-/* Player blew up in a nice fireball. */
+/**
+ * @fn void player_destroyed(void)
+ *
+ * @brief Player blew up in a nice fireball.
+ */
 void player_destroyed(void) {
   if(player_isFlag(PLAYER_DESTROYED)) return;
 
@@ -1610,8 +1754,14 @@ void player_destroyed(void) {
   player_timer = SDL_GetTicks() + 5000;
 }
 
-/* Return a buffer with all the ships names, or none if there */
-/* aren't any. */
+/**
+ * @fn char** player_ships(int* nships)
+ *
+ * @brief Return a buffer with all the players ship names
+ *        or "None" if there are no ships.
+ *    @param nships Stores the number of ships.
+ *    @return Freshly allocated array with allocated ship names.
+ */
 char** player_ships(int* nships) {
   int i;
   char** shipnames;
@@ -1630,7 +1780,12 @@ char** player_ships(int* nships) {
   return shipnames;
 }
 
-/* Return the amount of ships player has in storage. */
+/**
+ * @fn int player_nships(void)
+ *
+ * @brief Get the ammount of ships player has in storage.
+ *    @return The number of ships the player has.
+ */
 int player_nships(void) {
   return player_nstack;
 }
diff --git a/src/player.h b/src/player.h
index ae96a39..e43ba45 100644
--- a/src/player.h
+++ b/src/player.h
@@ -48,6 +48,7 @@ void player_message(const char* fmt, ...);
 void player_clear(void);
 void player_warp(const double x, const double y);
 const char* player_rating(void);
+void player_playSound(int sound, int once);
 /* Cargo. */
 int player_outfitOwned(const char* outfitname);
 int player_cargoOwned(const char* commodityname);
@@ -66,6 +67,9 @@ void player_missionFinished(int id);
 int player_missionAlreadyDone(int id);
 
 /* Keybind actions. */
+void player_targetHostile(void);
+void player_targetNext(void);
+void player_targetNearest(void);
 void player_setRadarRel(int mod);
 void player_secondaryNext(void);
 void player_targetPlanet(void);
diff --git a/src/sound.c b/src/sound.c
index 0b00c3f..171c487 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -381,6 +381,10 @@ int sound_playGroup(int group, int sound, int once) {
   if(sound_disabled) return 0;
 
   channel = Mix_GroupAvailable(group);
+  if(channel == -1) {
+    WARN("Group '%d' has no free channels!", group);
+    return -1;
+  }
 
   ret = Mix_PlayChannel(channel, sound_list[sound].buffer,
       (once == 0) ? -1 : 0);
@@ -403,6 +407,6 @@ int sound_playGroup(int group, int sound, int once) {
 void sound_stopGroup(int group) {
   if(sound_disabled) return;
 
-  Mix_FadeOutGroup(group, 100);
+  Mix_HaltGroup(group);
 }