-
-
Save Hiradur/94bb7414a40043b2a628 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt | |
index 4a714e1..a113685 100644 | |
--- a/builtin/settingtypes.txt | |
+++ b/builtin/settingtypes.txt | |
@@ -571,6 +571,8 @@ enable_sound (Sound) bool true | |
sound_volume (Volume) float 0.7 0.0 1.0 | |
+enable_mumble (Mumble positional audio) bool false | |
+ | |
[*Advanced] | |
# Timeout for client to remove unused map data from memory. | |
diff --git a/minetest.conf.example b/minetest.conf.example | |
index 34d618f..e693d0e 100644 | |
--- a/minetest.conf.example | |
+++ b/minetest.conf.example | |
@@ -674,6 +674,9 @@ | |
# type: float min: 0 max: 1 | |
# sound_volume = 0.7 | |
+# type: bool | |
+# enable_mumble = false | |
+ | |
## Advanced | |
# Timeout for client to remove unused map data from memory. | |
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt | |
index 6256a85..7a6e955 100644 | |
--- a/src/CMakeLists.txt | |
+++ b/src/CMakeLists.txt | |
@@ -79,6 +79,14 @@ endif() | |
option(ENABLE_SOUND "Enable sound" TRUE) | |
set(USE_SOUND FALSE) | |
+OPTION(ENABLE_MUMBLE "Enable Mumble positional audio" FALSE) | |
+set(USE_MUMBLE FALSE) | |
+ | |
+if(ENABLE_MUMBLE) | |
+ set(USE_MUMBLE TRUE) | |
+ message(STATUS "Mumble positional audio enabled.") | |
+endif(ENABLE_MUMBLE) | |
+ | |
if(BUILD_CLIENT AND ENABLE_SOUND) | |
# Sound libraries | |
find_package(OpenAL) | |
@@ -204,7 +212,6 @@ if(ENABLE_LEVELDB) | |
endif() | |
endif(ENABLE_LEVELDB) | |
- | |
OPTION(ENABLE_REDIS "Enable Redis backend" TRUE) | |
set(USE_REDIS FALSE) | |
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt | |
index a1ec37f..b7f5fb6 100644 | |
--- a/src/client/CMakeLists.txt | |
+++ b/src/client/CMakeLists.txt | |
@@ -1,5 +1,6 @@ | |
set(client_SRCS | |
- ${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp | |
+ ${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp | |
+ ${CMAKE_CURRENT_SOURCE_DIR}/mumbleintegration.cpp | |
${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp | |
PARENT_SCOPE | |
) | |
diff --git a/src/client/mumbleintegration.cpp b/src/client/mumbleintegration.cpp | |
new file mode 100644 | |
index 0000000..98774c6 | |
--- /dev/null | |
+++ b/src/client/mumbleintegration.cpp | |
@@ -0,0 +1,173 @@ | |
+/* | |
+Minetest | |
+Copyright (C) 2010-2015 celeron55, Perttu Ahola <celeron55@gmail.com> | |
+ | |
+This program is free software; you can redistribute it and/or modify | |
+it under the terms of the GNU Lesser General Public License as published by | |
+the Free Software Foundation; either version 2.1 of the License, or | |
+(at your option) any later version. | |
+ | |
+This program is distributed in the hope that it will be useful, | |
+but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+GNU Lesser General Public License for more details. | |
+ | |
+You should have received a copy of the GNU Lesser General Public License along | |
+with this program; if not, write to the Free Software Foundation, Inc., | |
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
+*/ | |
+ | |
+// required for USE_MUMBLE | |
+#include "../cmake_config.h" | |
+ | |
+#if USE_MUMBLE | |
+ | |
+#include "mumbleintegration.h" | |
+ | |
+#include <cstring> | |
+#include <sstream> | |
+#ifdef WIN32 | |
+ #include <windows.h> | |
+#else | |
+ #include <sys/mman.h> | |
+ #include <fcntl.h> /* For O_* constants */ | |
+ #include <unistd.h> | |
+#endif // WIN32 | |
+ | |
+ | |
+ | |
+MumbleIntegration::MumbleIntegration() : lm(NULL) | |
+{ | |
+ initMumble(); | |
+} | |
+ | |
+MumbleIntegration::~MumbleIntegration() | |
+{ | |
+ #ifdef WIN32 | |
+ if (map_object != NULL) { | |
+ CloseHandle(hMapObject); | |
+ map_object = NULL; | |
+ } | |
+ #else | |
+ if (shmfd > 0) { | |
+ close(shmfd); | |
+ shmfd = 0; | |
+ } | |
+ #endif | |
+} | |
+ | |
+void MumbleIntegration::initMumble() | |
+{ | |
+#ifdef WIN32 | |
+ map_object = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink"); | |
+ if (map_object == NULL) | |
+ return; | |
+ | |
+ lm = (LinkedMem *) MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LinkedMem)); | |
+ if (lm == NULL) { | |
+ CloseHandle(map_object); | |
+ map_object = NULL; | |
+ return; | |
+ } | |
+#else | |
+ char memname[256]; | |
+ int size = sizeof(struct LinkedMem); | |
+ snprintf(memname, 256, "/MumbleLink.%d", getuid()); | |
+ | |
+ shmfd = shm_open(memname, O_RDWR, S_IRUSR | S_IWUSR); | |
+ | |
+ if (shmfd < 0) { | |
+ perror("shm_open in MumbleIntegration"); | |
+ return; | |
+ } | |
+ | |
+ ftruncate(shmfd, size); | |
+ lm = (LinkedMem *)(mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0)); | |
+ | |
+ if (lm == (void *)(-1)) { | |
+ lm = NULL; | |
+ return; | |
+ } | |
+#endif // WIN32 | |
+} | |
+ | |
+void MumbleIntegration::updateContext(std::string *address, u16 port, std::string playername) | |
+{ | |
+ if (! lm) | |
+ return; | |
+ // Context is equal for players on the same server | |
+ //TODO allow mods to append something to allow for teams | |
+ std::stringstream contextstringstream; | |
+ contextstringstream << (*address) << ":" << port; | |
+ std::string context = contextstringstream.str(); | |
+ memcpy(lm->context, context.c_str(), context.length()); | |
+ lm->context_len = context.length(); | |
+ | |
+ // Identifier which uniquely identifies the player on the server (nicknames are unique per server) | |
+ std::wstring wplayername; | |
+ wplayername.assign(playername.begin(), playername.end()); | |
+ wcsncpy(lm->identity, wplayername.c_str(), 256); | |
+} | |
+ | |
+void MumbleIntegration::updatePosition(v3f avatar_pos, v3f avatar_dir, v3f avatar_up, v3f camera_pos, v3f camera_dir, v3f camera_up) | |
+{ | |
+ if (! lm) | |
+ return; | |
+ | |
+ if (lm->version != 2) { | |
+ wcsncpy(lm->name, L"Minetest", 256); | |
+ wcsncpy(lm->description, L"Links Minetest to Mumble for positional audio", 2048); | |
+ lm->version = 2; | |
+ } | |
+ lm->tick++; | |
+ | |
+ // Left handed coordinate system. | |
+ // X positive towards "right". | |
+ // Y positive towards "up". | |
+ // Z positive towards "front". | |
+ // | |
+ // 1 unit = 1 meter | |
+ | |
+ // unit vectors are required | |
+ avatar_dir = avatar_dir.normalize(); | |
+ avatar_up = avatar_up.normalize(); | |
+ camera_dir = camera_dir.normalize(); | |
+ camera_up = camera_up.normalize(); | |
+ | |
+ // Position of the avatar | |
+ lm->avatar_position[0] = avatar_pos.X; | |
+ lm->avatar_position[1] = avatar_pos.Y; | |
+ lm->avatar_position[2] = avatar_pos.Z; | |
+ | |
+ // Unit vector pointing out of the avatars eyes | |
+ lm->avatar_front[0] = avatar_dir.X; | |
+ lm->avatar_front[1] = avatar_dir.Y; | |
+ lm->avatar_front[2] = avatar_dir.Z; | |
+ | |
+ // Unit vector pointing out of the top of the avatars head | |
+ lm->avatar_top[0] = avatar_up.X; | |
+ lm->avatar_top[1] = avatar_up.Y; | |
+ lm->avatar_top[2] = avatar_up.Z; | |
+ | |
+ // Same as avatar but for the camera. | |
+ lm->camera_position[0] = camera_pos.X; | |
+ lm->camera_position[1] = camera_pos.Y; | |
+ lm->camera_position[2] = camera_pos.Z; | |
+ | |
+ lm->camera_front[0] = camera_dir.X; | |
+ lm->camera_front[1] = camera_dir.Y; | |
+ lm->camera_front[2] = camera_dir.Z; | |
+ | |
+ lm->camera_top[0] = camera_up.X; | |
+ lm->camera_top[1] = camera_up.Y; | |
+ lm->camera_top[2] = camera_up.Z; | |
+} | |
+ | |
+void MumbleIntegration::reset() | |
+{ | |
+ v3f vz = v3f(0,0,0); | |
+ // set Mumble to non-positional audio | |
+ updatePosition(vz, vz, vz, vz, vz, vz); | |
+} | |
+ | |
+#endif // USE_MUMBLE | |
diff --git a/src/client/mumbleintegration.h b/src/client/mumbleintegration.h | |
new file mode 100644 | |
index 0000000..2ed9205 | |
--- /dev/null | |
+++ b/src/client/mumbleintegration.h | |
@@ -0,0 +1,102 @@ | |
+/* | |
+Minetest | |
+Copyright (C) 2010-2015 celeron55, Perttu Ahola <celeron55@gmail.com> | |
+ | |
+This program is free software; you can redistribute it and/or modify | |
+it under the terms of the GNU Lesser General Public License as published by | |
+the Free Software Foundation; either version 2.1 of the License, or | |
+(at your option) any later version. | |
+ | |
+This program is distributed in the hope that it will be useful, | |
+but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+GNU Lesser General Public License for more details. | |
+ | |
+You should have received a copy of the GNU Lesser General Public License along | |
+with this program; if not, write to the Free Software Foundation, Inc., | |
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
+*/ | |
+ | |
+#include "../cmake_config.h" | |
+ | |
+#if USE_MUMBLE | |
+#pragma once | |
+ | |
+#include "../irrlichttypes_bloated.h" | |
+ | |
+#include <string> | |
+ | |
+/* | |
+ Class which establishes a link to the VOIP software Mumble to | |
+ transmit positional data to other Mumble clients so voices | |
+ are heard from their relative ingame position. | |
+ There should be only one instance of this class at runtime. | |
+*/ | |
+class MumbleIntegration | |
+{ | |
+public: | |
+ MumbleIntegration(); | |
+ ~MumbleIntegration(); | |
+ | |
+ void updatePosition(v3f avatar_pos, v3f avatar_dir, v3f avatar_up, v3f camera_pos, v3f camera_dir, v3f camera_up); | |
+ void updateContext(std::string *address, u16 port, std::string playername); | |
+ void reset(); | |
+ | |
+private: | |
+ void initMumble(); | |
+ | |
+ struct LinkedMem | |
+ { | |
+ | |
+ u32 version; | |
+ u32 tick; | |
+ float avatar_position[3]; | |
+ float avatar_front[3]; | |
+ float avatar_top[3]; | |
+ wchar_t name[256]; | |
+ float camera_position[3]; | |
+ float camera_front[3]; | |
+ float camera_top[3]; | |
+ wchar_t identity[256]; | |
+ u32 context_len; | |
+ unsigned char context[256]; | |
+ wchar_t description[2048]; | |
+ /* TODO: remove this if tests with above struct succeed | |
+ #ifdef WIN32 | |
+ UINT32 version; | |
+ DWORD tick; | |
+ #else | |
+ uint32_t version; | |
+ uint32_t tick; | |
+ #endif | |
+ | |
+ float avatar_position[3]; | |
+ float avatar_front[3]; | |
+ float avatar_top[3]; | |
+ wchar_t name[256]; | |
+ float camera_position[3]; | |
+ float camera_front[3]; | |
+ float camera_top[3]; | |
+ wchar_t identity[256]; | |
+ | |
+ #ifdef WIN32 | |
+ UINT32 context_len; | |
+ #else | |
+ uint32_t context_len; | |
+ #endif | |
+ | |
+ unsigned char context[256]; | |
+ wchar_t description[2048]; | |
+ */ | |
+ }; | |
+ | |
+ LinkedMem *lm; | |
+ | |
+ #ifdef WIN32 | |
+ HANDLE map_object; | |
+ #else | |
+ int shmfd; | |
+ #endif | |
+}; | |
+ | |
+#endif //USE_MUMBLE | |
diff --git a/src/cmake_config.h.in b/src/cmake_config.h.in | |
index 018532d..64dce08 100644 | |
--- a/src/cmake_config.h.in | |
+++ b/src/cmake_config.h.in | |
@@ -18,6 +18,7 @@ | |
#cmakedefine01 USE_GETTEXT | |
#cmakedefine01 USE_CURL | |
#cmakedefine01 USE_SOUND | |
+#cmakedefine01 USE_MUMBLE | |
#cmakedefine01 USE_FREETYPE | |
#cmakedefine01 USE_CURSES | |
#cmakedefine01 USE_LEVELDB | |
diff --git a/src/game.cpp b/src/game.cpp | |
index 5e4f4ca..8283b6b 100644 | |
--- a/src/game.cpp | |
+++ b/src/game.cpp | |
@@ -64,6 +64,10 @@ with this program; if not, write to the Free Software Foundation, Inc., | |
#include "sound_openal.h" | |
#endif | |
+#if USE_MUMBLE | |
+ #include "client/mumbleintegration.h" | |
+#endif | |
+ | |
#ifdef HAVE_TOUCHSCREENGUI | |
#include "touchscreengui.h" | |
#endif | |
@@ -1569,6 +1573,9 @@ class Game { | |
ISoundManager *sound; | |
bool sound_is_dummy; | |
SoundMaker *soundmaker; | |
+ #if USE_MUMBLE | |
+ MumbleIntegration *mumble_link; | |
+ #endif | |
ChatBackend *chat_backend; | |
@@ -1653,6 +1660,9 @@ Game::Game() : | |
sound(NULL), | |
sound_is_dummy(false), | |
soundmaker(NULL), | |
+ #if USE_MUMBLE | |
+ mumble_link(NULL), | |
+ #endif | |
chat_backend(NULL), | |
current_formspec(NULL), | |
eventmgr(NULL), | |
@@ -1701,6 +1711,9 @@ Game::~Game() | |
delete soundmaker; | |
if (!sound_is_dummy) | |
delete sound; | |
+ #if USE_MUMBLE | |
+ delete mumble_link; | |
+ #endif | |
delete server; // deleted first to stop all server threads | |
@@ -1769,6 +1782,17 @@ bool Game::startup(bool *kill, | |
if (!createClient(playername, password, address, port)) | |
return false; | |
+ #if USE_MUMBLE | |
+ /* Mumble Link | |
+ */ | |
+ if (g_settings->getBool("enable_mumble")) { | |
+ if (mumble_link == NULL) | |
+ mumble_link = new MumbleIntegration(); | |
+ | |
+ mumble_link->updateContext(address, port, client->getEnv().getLocalPlayer()->getName()); | |
+ } | |
+ #endif | |
+ | |
return true; | |
} | |
@@ -1860,6 +1884,23 @@ void Game::run() | |
flags.show_hud, flags.show_debug); | |
updateFrame(highlight_boxes, &graph, &stats, &runData, dtime, | |
flags, cam_view); | |
+ #if USE_MUMBLE | |
+ if(g_settings->getBool("enable_mumble")) | |
+ if(mumble_link != NULL) { | |
+ LocalPlayer *avatar = client->getEnv().getLocalPlayer(); | |
+ v3f avatar_pos = avatar->getEyePosition(); | |
+ // TODO: calculate from pitch and yaw | |
+ v3f avatar_dir = camera->getDirection(); | |
+ v3f avatar_up = camera->getCameraNode()->getUpVector(); | |
+ | |
+ v3f camera_pos = camera->getPosition(); | |
+ v3f camera_dir = camera->getDirection(); | |
+ v3f camera_up = camera->getCameraNode()->getUpVector(); | |
+ | |
+ mumble_link->updatePosition(avatar_pos, avatar_dir, avatar_up, | |
+ camera_pos, camera_dir, camera_up); | |
+ } | |
+ #endif | |
updateProfilerGraphs(&graph); | |
// Update if minimap has been disabled by the server | |
@@ -1881,6 +1922,12 @@ void Game::shutdown() | |
if (sky) | |
sky->drop(); | |
+ #if USE_MUMBLE | |
+ if(g_settings->getBool("enable_mumble")) | |
+ if(mumble_link != NULL) | |
+ mumble_link->reset(); | |
+ #endif | |
+ | |
/* cleanup menus */ | |
while (g_menumgr.menuCount() > 0) { | |
g_menumgr.m_stack.front()->setVisible(false); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment