From ac7781a3b3ac1b96132b5c5ef44652f00330b604 Mon Sep 17 00:00:00 2001
From: Steel Titanium <steeltitanium1@gmail.com>
Date: Sat, 31 Oct 2020 20:15:41 -0500
Subject: [PATCH] Expose more music functions to Lua

---
 src/dehacked.c    |  16 ++++
 src/lua_baselib.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++
 src/lua_hook.h    |   2 +
 src/lua_hooklib.c |  60 +++++++++++++++
 src/s_sound.c     |   7 +-
 5 files changed, 267 insertions(+), 6 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index ca013a25d5..ae22e19d51 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -26,6 +26,7 @@
 #include "dehacked.h"
 #include "st_stuff.h"
 #include "i_system.h"
+#include "i_sound.h" // musictype_t (for lua)
 #include "p_local.h" // for var1 and var2, and some constants
 #include "p_setup.h"
 #include "r_data.h"
@@ -10106,6 +10107,21 @@ struct {
 	{"MA_NOCUTSCENES",MA_NOCUTSCENES},
 	{"MA_INGAME",MA_INGAME},
 
+	// music types
+	{"MU_NONE", MU_NONE},
+	{"MU_CMD", MU_CMD},
+	{"MU_WAV", MU_WAV},
+	{"MU_MOD", MU_MOD},
+	{"MU_MID", MU_MID},
+	{"MU_OGG", MU_OGG},
+	{"MU_MP3", MU_MP3},
+	{"MU_MP3_MAD_UNUSED", MU_MP3_MAD_UNUSED},
+	{"MU_FLAC", MU_FLAC},
+	{"MU_MODPLUG_UNUSED", MU_MODPLUG_UNUSED},
+	{"MU_GME", MU_GME},
+	{"MU_MOD_EX", MU_MOD_EX},
+	{"MU_MID_EX", MU_MID_EX},
+
 	{NULL,0}
 };
 
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 132ebc1a8b..6cb3a07196 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -3006,6 +3006,185 @@ static int lib_sStartMusicCaption(lua_State *L)
 	return 0;
 }
 
+static int lib_sMusicType(lua_State *L)
+{
+	player_t *player = NULL;
+	NOHUD
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (!player || P_IsLocalPlayer(player))
+		lua_pushinteger(L, S_MusicType());
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
+static int lib_sMusicPlaying(lua_State *L)
+{
+	player_t *player = NULL;
+	NOHUD
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (!player || P_IsLocalPlayer(player))
+		lua_pushboolean(L, S_MusicPlaying());
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
+static int lib_sMusicPaused(lua_State *L)
+{
+	player_t *player = NULL;
+	NOHUD
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (!player || P_IsLocalPlayer(player))
+		lua_pushboolean(L, S_MusicPaused());
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
+static int lib_sMusicName(lua_State *L)
+{
+	player_t *player = NULL;
+	NOHUD
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (!player || P_IsLocalPlayer(player))
+		lua_pushstring(L, S_MusicName());
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
+static int lib_sMusicExists(lua_State *L)
+{
+	boolean checkMIDI = lua_opttrueboolean(L, 2);
+	boolean checkDigi = lua_opttrueboolean(L, 3);
+#ifdef MUSICSLOT_COMPATIBILITY
+	const char *music_name;
+	UINT32 music_num;
+	char music_compat_name[7];
+	UINT16 music_flags = 0;
+	NOHUD
+	if (lua_isnumber(L, 1))
+	{
+		music_num = (UINT32)luaL_checkinteger(L, 1);
+		music_flags = (UINT16)(music_num & 0x0000FFFF);
+		if (music_flags && music_flags <= 1035)
+			snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
+		else if (music_flags && music_flags <= 1050)
+			strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
+		else
+			music_compat_name[0] = 0; // becomes empty string
+		music_compat_name[6] = 0;
+		music_name = (const char *)&music_compat_name;
+	}
+	else
+	{
+		music_num = 0;
+		music_name = luaL_checkstring(L, 1);
+	}
+#else
+	const char *music_name = luaL_checkstring(L, 1);
+#endif
+	NOHUD
+	lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi));
+	return 1;
+}
+
+static int lib_sSetMusicLoopPoint(lua_State *L)
+{
+	UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1);
+	player_t *player = NULL;
+	NOHUD
+	if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
+	{
+		player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (!player || P_IsLocalPlayer(player))
+		lua_pushboolean(L, S_SetMusicLoopPoint(looppoint));
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
+static int lib_sGetMusicLoopPoint(lua_State *L)
+{
+	player_t *player = NULL;
+	NOHUD
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (!player || P_IsLocalPlayer(player))
+		lua_pushinteger(L, (int)S_GetMusicLoopPoint());
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
+static int lib_sPauseMusic(lua_State *L)
+{
+	player_t *player = NULL;
+	NOHUD
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (!player || P_IsLocalPlayer(player))
+	{
+		S_PauseAudio();
+		lua_pushboolean(L, true);
+	}
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
+static int lib_sResumeMusic(lua_State *L)
+{
+	player_t *player = NULL;
+	NOHUD
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (!player || P_IsLocalPlayer(player))
+	{
+		S_ResumeAudio();
+		lua_pushboolean(L, true);
+	}
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
 // G_GAME
 ////////////
 
@@ -3712,6 +3891,15 @@ static luaL_Reg lib[] = {
 	{"S_IdPlaying",lib_sIdPlaying},
 	{"S_SoundPlaying",lib_sSoundPlaying},
 	{"S_StartMusicCaption", lib_sStartMusicCaption},
+	{"S_MusicType",lib_sMusicType},
+	{"S_MusicPlaying",lib_sMusicPlaying},
+	{"S_MusicPaused",lib_sMusicPaused},
+	{"S_MusicName",lib_sMusicName},
+	{"S_MusicExists",lib_sMusicExists},
+	{"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint},
+	{"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint},
+	{"S_PauseMusic",lib_sPauseMusic},
+	{"S_ResumeMusic", lib_sResumeMusic},
 
 	// g_game
 	{"G_AddGametype", lib_gAddGametype},
diff --git a/src/lua_hook.h b/src/lua_hook.h
index 47850812f0..796f3a9d28 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -60,6 +60,7 @@ enum hook {
 	hook_ShouldJingleContinue,
 	hook_GameQuit,
 	hook_PlayerCmd,
+	hook_MusicChange,
 
 	hook_MAX // last hook
 };
@@ -118,3 +119,4 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_
 boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
 void LUAh_GameQuit(void); // Hook for game quitting
 boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart)
+boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes
\ No newline at end of file
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 65d483dc1a..117aa48a30 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -76,6 +76,7 @@ const char *const hookNames[hook_MAX+1] = {
 	"ShouldJingleContinue",
 	"GameQuit",
 	"PlayerCmd",
+	"MusicChange",
 	NULL
 };
 
@@ -1912,3 +1913,62 @@ boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd)
 	hook_cmd_running = false;
 	return hooked;
 }
+
+// Hook for music changes
+boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
+	UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms)
+{
+	hook_p hookp;
+	boolean hooked = false;
+
+	if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8))))
+		return false;
+
+	lua_settop(gL, 0);
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MusicChange)
+		{
+			PushHook(gL, hookp);
+			lua_pushstring(gL, oldname);
+			lua_pushstring(gL, newname);
+			lua_pushinteger(gL, *mflags);
+			lua_pushboolean(gL, *looping);
+			lua_pushinteger(gL, *position);
+			lua_pushinteger(gL, *prefadems);
+			lua_pushinteger(gL, *fadeinms);
+			if (lua_pcall(gL, 7, 6, 1)) {
+				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+				lua_pop(gL, 1);
+				continue;
+			}
+
+			// output 1: true, false, or string musicname override
+			if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6))
+				hooked = true;
+			else if (lua_isstring(gL, -6))
+				strncpy(newname, lua_tostring(gL, -6), 7);
+			// output 2: mflags override
+			if (lua_isnumber(gL, -5))
+				*mflags = lua_tonumber(gL, -5);
+			// output 3: looping override
+			if (lua_isboolean(gL, -4))
+				*looping = lua_toboolean(gL, -4);
+			// output 4: position override
+			if (lua_isboolean(gL, -3))
+				*position = lua_tonumber(gL, -3);
+			// output 5: prefadems override
+			if (lua_isboolean(gL, -2))
+				*prefadems = lua_tonumber(gL, -2);
+			// output 6: fadeinms override
+			if (lua_isboolean(gL, -1))
+				*fadeinms = lua_tonumber(gL, -1);
+
+			lua_pop(gL, 7);  // Pop returned values and error handler
+		}
+
+	lua_settop(gL, 0);
+	newname[6] = 0;
+	return hooked;
+}
\ No newline at end of file
diff --git a/src/s_sound.c b/src/s_sound.c
index 793794aa7c..36bd454c10 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -29,10 +29,7 @@
 #include "fastcmp.h"
 #include "m_misc.h" // for tunes command
 #include "m_cond.h" // for conditionsets
-
-#ifdef HAVE_LUA_MUSICPLUS
 #include "lua_hook.h" // MusicChange hook
-#endif
 
 #ifdef HW3SOUND
 // 3D Sound Interface
@@ -2272,10 +2269,8 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
 		return;
 
 	strncpy(newmusic, mmusic, 7);
-#ifdef HAVE_LUA_MUSICPLUS
-	if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
+	if (LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
 		return;
-#endif
 	newmusic[6] = 0;
 
  	// No Music (empty string)
-- 
GitLab