From e114b118bc11c0c179c37427382c5e577a9d6ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Tue, 28 Apr 2020 22:15:21 +0200 Subject: [PATCH 001/104] Mumble preparation. Base class refactoring --- extensions/src/ACRE2Core/Engine.cpp | 2 +- extensions/src/ACRE2Core/NamedPipeServer.cpp | 8 +- .../src/ACRE2Core/setTs3ChannelDetails.h | 4 +- .../ACRE2DistortionTestPlugin/TS3Client.cpp | 97 ++--------- .../src/ACRE2DistortionTestPlugin/TS3Client.h | 96 +++++------ .../TsCallbacks_channelEvents.cpp | 2 +- extensions/src/ACRE2Shared/IClient.h | 154 +++++++++++++++++- extensions/src/ACRE2TS/TS3Client.cpp | 98 ++--------- extensions/src/ACRE2TS/TS3Client.h | 85 ++++------ .../src/ACRE2TS/TsCallbacks_channelEvents.cpp | 2 +- 10 files changed, 258 insertions(+), 290 deletions(-) diff --git a/extensions/src/ACRE2Core/Engine.cpp b/extensions/src/ACRE2Core/Engine.cpp index ef9dd3840..b9d12f68a 100644 --- a/extensions/src/ACRE2Core/Engine.cpp +++ b/extensions/src/ACRE2Core/Engine.cpp @@ -74,7 +74,7 @@ acre::Result CEngine::initialize(IClient *client, IServer *externalServer, std:: this->getRpcEngine()->addProcedure(new updateSelf()); this->getRpcEngine()->addProcedure(new setSelectableVoiceCurve()); this->getRpcEngine()->addProcedure(new setSetting()); - this->getRpcEngine()->addProcedure(new setTs3ChannelDetails()); + this->getRpcEngine()->addProcedure(new setChannelDetails()); // Initialize the client, because it never was derp this->getClient()->initialize(); diff --git a/extensions/src/ACRE2Core/NamedPipeServer.cpp b/extensions/src/ACRE2Core/NamedPipeServer.cpp index f576a28ac..fe48b971c 100644 --- a/extensions/src/ACRE2Core/NamedPipeServer.cpp +++ b/extensions/src/ACRE2Core/NamedPipeServer.cpp @@ -240,7 +240,7 @@ acre::Result CNamedPipeServer::readLoop() { bool ret = ConnectNamedPipe(this->m_PipeHandleRead, NULL); if (GetLastError() == ERROR_PIPE_CONNECTED) { LOG("Client read connected"); - CEngine::getInstance()->getClient()->updateShouldSwitchTS3Channel(false); + CEngine::getInstance()->getClient()->updateShouldSwitchChannel(false); CEngine::getInstance()->getClient()->unMuteAll(); CEngine::getInstance()->getSoundEngine()->onClientGameConnected(); this->setConnectedRead(true); @@ -267,8 +267,8 @@ acre::Result CNamedPipeServer::readLoop() { } //Run channel switch to server channel - if (CEngine::getInstance()->getClient()->shouldSwitchTS3Channel()) { - CEngine::getInstance()->getClient()->moveToServerTS3Channel(); + if (CEngine::getInstance()->getClient()->shouldSwitchChannel()) { + CEngine::getInstance()->getClient()->moveToServerChannel(); } ret = false; @@ -305,7 +305,7 @@ acre::Result CNamedPipeServer::readLoop() { ret = DisconnectNamedPipe(this->m_PipeHandleRead); //Run channel switch to original channel - CEngine::getInstance()->getClient()->moveToPreviousTS3Channel(); + CEngine::getInstance()->getClient()->moveToPreviousChannel(); CEngine::getInstance()->getSoundEngine()->onClientGameDisconnected(); LOG("Client disconnected"); CEngine::getInstance()->getClient()->unMuteAll(); diff --git a/extensions/src/ACRE2Core/setTs3ChannelDetails.h b/extensions/src/ACRE2Core/setTs3ChannelDetails.h index f5f1dd105..404312ac1 100644 --- a/extensions/src/ACRE2Core/setTs3ChannelDetails.h +++ b/extensions/src/ACRE2Core/setTs3ChannelDetails.h @@ -7,14 +7,14 @@ #include -RPC_FUNCTION(setTs3ChannelDetails) { +RPC_FUNCTION(setChannelDetails) { const std::vector details = { std::string((char *)vMessage->getParameter(0)), std::string((char *)vMessage->getParameter(1)), std::string((char *)vMessage->getParameter(2)) }; - CEngine::getInstance()->getClient()->updateTs3ChannelDetails(details); + CEngine::getInstance()->getClient()->updateChannelDetails(details); return acre::Result::ok; } public: diff --git a/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp b/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp index b5cdab362..0cacb7587 100644 --- a/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp +++ b/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp @@ -7,12 +7,6 @@ #include "shlobj.h" #include "Shlwapi.h" #include "Log.h" -#include -#include -#include -#include -#include -#include #include "AcreSettings.h" @@ -26,7 +20,7 @@ extern TS3Functions ts3Functions; //TS3Functions CTS3Client::ts3Functions; acre::Result CTS3Client::initialize(void) { - setPreviousTSChannel(INVALID_TS3_CHANNEL); + setPreviousChannel(INVALID_TS3_CHANNEL); return acre::Result::ok; } @@ -455,15 +449,15 @@ acre::Result CTS3Client::unMuteAll( void ) { return acre::Result::ok; } -acre::Result CTS3Client::moveToServerTS3Channel() { +acre::Result CTS3Client::moveToServerChannel() { if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { anyID clientId; - std::vector details = getTs3ChannelDetails(); + std::vector details = getChannelDetails(); if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; - if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousTSChannel() == INVALID_TS3_CHANNEL) { - setPreviousTSChannel(currentChannelId); + if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousChannel() == INVALID_TS3_CHANNEL) { + setPreviousChannel(currentChannelId); } const uint64_t channelId = findChannelByNames(details); @@ -476,23 +470,23 @@ acre::Result CTS3Client::moveToServerTS3Channel() { } } } - setShouldSwitchTS3Channel(false); + setShouldSwitchChannel(false); return acre::Result::ok; } -acre::Result CTS3Client::moveToPreviousTS3Channel() { +acre::Result CTS3Client::moveToPreviousChannel() { if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { anyID clientId; if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok) { - const uint64_t channelId = getPreviousTSChannel(); + const uint64_t channelId = getPreviousChannel(); if (channelId != INVALID_TS3_CHANNEL && channelId != currentChannelId) { ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, "", nullptr); } } } - setPreviousTSChannel(INVALID_TS3_CHANNEL); + setPreviousChannel(INVALID_TS3_CHANNEL); } return acre::Result::ok; } @@ -560,79 +554,20 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { return INVALID_TS3_CHANNEL; } -unsigned int CTS3Client::getWordMatches(const std::string& string1_, const std::string& string2_) { - std::vector words1, words2; - std::string temp; - std::stringstream stringstream1(string1_); - while (stringstream1 >> temp) { - words1.push_back(temp); - } - std::stringstream stringstream2(string2_); - while (stringstream2 >> temp) { - words2.push_back(temp); - } - - int32_t matches = 0; - for (auto& word1 : words1) { - for (auto& word2 : words2) { - if (word1 == word2) { - matches++; - } - } - } - return matches; -} - -uint32_t CTS3Client::levenshteinDistance(const std::string& string1_, const std::string& string2_) { - int32_t length1 = string1_.size(); - const int32_t length2 = string2_.size(); - - const decltype(length1) columnStart = decltype(length1)(1); - - decltype(length1)*const column = new decltype(length1)[length1 + 1]; - std::iota(column + columnStart, column + length1 + 1, columnStart); - - for (auto x = columnStart; x <= length2; x++) { - column[0] = x; - int32_t lastDiagonal = x - columnStart; - for (auto y = columnStart; y <= length1; y++) { - const int32_t oldDiagonal = column[y]; - const std::initializer_list possibilities = { - column[y] + 1, - column[y - 1] + 1, - lastDiagonal + (string1_[y - 1] == string2_[x - 1] ? 0 : 1) - }; - column[y] = min(possibilities); - lastDiagonal = oldDiagonal; - } - } - const int32_t result = column[length1]; - delete[] column; - return result; -} - -std::string CTS3Client::removeSubstrings(std::string string_, std::string substring_) { - const std::string::size_type substringLength = substring_.length(); - for (auto iterator = string_.find(substring_); - iterator != std::string::npos; - iterator = string_.find(substring_)) - string_.erase(iterator, substringLength); - return string_; -} -acre::Result CTS3Client::updateTs3ChannelDetails(std::vector details_) { - setTs3ChannelDetails(details_); +acre::Result CTS3Client::updateChannelDetails(std::vector details_) { + setChannelDetails(details_); if (!details_.empty()) { - updateShouldSwitchTS3Channel(true); + updateShouldSwitchChannel(true); } return acre::Result::ok; } -acre::Result CTS3Client::updateShouldSwitchTS3Channel(const bool state_) { - setShouldSwitchTS3Channel(state_); +acre::Result CTS3Client::updateShouldSwitchChannel(const bool state_) { + setShouldSwitchChannel(state_); return acre::Result::ok; } -bool CTS3Client::shouldSwitchTS3Channel() { - return getShouldSwitchTS3Channel(); +bool CTS3Client::shouldSwitchChannel() { + return getShouldSwitchChannel(); } diff --git a/extensions/src/ACRE2DistortionTestPlugin/TS3Client.h b/extensions/src/ACRE2DistortionTestPlugin/TS3Client.h index c273d10c5..5b2d76f3d 100644 --- a/extensions/src/ACRE2DistortionTestPlugin/TS3Client.h +++ b/extensions/src/ACRE2DistortionTestPlugin/TS3Client.h @@ -11,25 +11,29 @@ class CTS3Client : public IClient { //static TS3Functions ts3Functions; - CTS3Client() {}; - ~CTS3Client() {}; + CTS3Client() = default; + ~CTS3Client() final = default; - acre::Result initialize(void); + acre::Result initialize(void) final; - acre::Result setMuted(const acre::id_t id_, const bool muted_); - acre::Result setMuted(std::list idList_, const bool muted_); + acre::Result setMuted(const acre::id_t id_, const bool muted_) final; + acre::Result setMuted(std::list idList_, const bool muted_) final; - acre::Result getMuted(const acre::id_t id_); + acre::Result getMuted(const acre::id_t id_) final; - acre::Result stop(); - acre::Result start(const acre::id_t id_); + acre::Result stop() final; + acre::Result start(const acre::id_t id_) final; acre::Result exPersistVersion(void); - acre::Result enableMicrophone(const bool status_); + acre::Result setClientMetadata(const char* const data); + + acre::Result enableMicrophone(const bool status_) final; bool getInputStatus(); + bool getVAD(); + /*! * \brief Handles local player starting speaking. * @@ -37,7 +41,7 @@ class CTS3Client : public IClient { * * \return acre::Result::ok if operation successful */ - acre::Result localStartSpeaking(const acre::Speaking speakingType_); + acre::Result localStartSpeaking(const acre::Speaking speakingType_) final; /*! * \brief Handles local player starting speaking. @@ -47,59 +51,37 @@ class CTS3Client : public IClient { * * \return acre::Result::ok if operation successful */ - acre::Result localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_); + acre::Result localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_) final; /*! - * \brief Handles local player stopping speaking. - * - * \param[in] speakingType_ ACRE speaking type - * - * \return acre::Result::ok if operation successful - */ - acre::Result localStopSpeaking(const acre::Speaking speakingType_); + * \brief Handles local player stopping speaking. + * + * \param[in] speakingType_ ACRE speaking type + * + * \return acre::Result::ok if operation successful + */ + acre::Result localStopSpeaking(const acre::Speaking speakingType_) final; - std::string getTempFilePath(void); - std::string getConfigFilePath(void); + std::string getTempFilePath(void) final; + std::string getConfigFilePath(void) final; - acre::Result playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_); + acre::Result playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) final; - std::string getUniqueId(); + std::string getUniqueId() final; - bool getVAD(); + acre::Result microphoneOpen(const bool status_) final; + + acre::Result unMuteAll(void) final; + + acre::Result moveToServerChannel() final; + acre::Result moveToPreviousChannel() final; + uint64 findChannelByNames(std::vector details_) final; + + acre::Result updateChannelDetails(std::vector details_) final; + acre::Result updateShouldSwitchChannel(const bool state_) final; + bool shouldSwitchChannel() final; - acre::Result microphoneOpen(const bool status_); - - acre::Result unMuteAll(void); - - acre::Result moveToServerTS3Channel(); - acre::Result moveToPreviousTS3Channel(); - uint64 findChannelByNames(std::vector details_); - uint32_t getWordMatches(const std::string& string1_, const std::string& string2_); - uint32_t levenshteinDistance(const std::string& string1_, const std::string& string2_); - std::string removeSubstrings(std::string string_, std::string substring_); - acre::Result updateTs3ChannelDetails(std::vector details_); - acre::Result updateShouldSwitchTS3Channel(const bool state_); - bool shouldSwitchTS3Channel(); - - inline void setState(acre::State value) final { m_state = value; } - inline acre::State getState() const final { return m_state; } - - DECLARE_MEMBER(bool, hadVAD); - DECLARE_MEMBER(bool, InputActive); - DECLARE_MEMBER(bool, OnRadio); - DECLARE_MEMBER(int32_t, TsSpeakingState); - DECLARE_MEMBER(bool, RadioPTTDown); - DECLARE_MEMBER(bool, IntercomPTTDown); - DECLARE_MEMBER(bool, MainPTTDown); - DECLARE_MEMBER(bool, DirectFirst); - DECLARE_MEMBER(bool, HitTSSpeakingEvent); - DECLARE_MEMBER(bool, IsX3DInitialized); - DECLARE_MEMBER(uint32_t, SpeakerMask); - DECLARE_MEMBER(uint64, PreviousTSChannel); - DECLARE_MEMBER(std::vector, Ts3ChannelDetails); - DECLARE_MEMBER(bool, ShouldSwitchTS3Channel) -protected: +private: std::thread m_versionThreadHandle; - char *m_vadLevel; - acre::State m_state; + char* m_vadLevel = nullptr; }; diff --git a/extensions/src/ACRE2DistortionTestPlugin/TsCallbacks_channelEvents.cpp b/extensions/src/ACRE2DistortionTestPlugin/TsCallbacks_channelEvents.cpp index efa8f194d..a0363ec8f 100644 --- a/extensions/src/ACRE2DistortionTestPlugin/TsCallbacks_channelEvents.cpp +++ b/extensions/src/ACRE2DistortionTestPlugin/TsCallbacks_channelEvents.cpp @@ -82,5 +82,5 @@ void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID cl } void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) { - CEngine::getInstance()->getClient()->updateShouldSwitchTS3Channel(true); + CEngine::getInstance()->getClient()->updateShouldSwitchChannel(true); } diff --git a/extensions/src/ACRE2Shared/IClient.h b/extensions/src/ACRE2Shared/IClient.h index ceecf2418..f9a8238c2 100644 --- a/extensions/src/ACRE2Shared/IClient.h +++ b/extensions/src/ACRE2Shared/IClient.h @@ -1,16 +1,22 @@ #pragma once #include "compat.h" - #include "Types.h" #include "Macros.h" #include "ACRE_VECTOR.h" + +#include #include +#include #include #include +#include class IClient { public: + IClient() noexcept = default; + virtual ~IClient() noexcept = default; + virtual acre::Result initialize( void ) = 0; virtual acre::Result setMuted(const acre::id_t id, const bool muted) = 0; @@ -38,12 +44,144 @@ class IClient { virtual acre::Result unMuteAll( void ) = 0; - virtual acre::Result moveToServerTS3Channel() = 0; - virtual acre::Result moveToPreviousTS3Channel() = 0; - virtual acre::Result updateTs3ChannelDetails(const std::vector details) = 0; - virtual acre::Result updateShouldSwitchTS3Channel(const bool state) = 0; - virtual bool shouldSwitchTS3Channel() = 0; + virtual acre::Result moveToServerChannel() = 0; + virtual acre::Result moveToPreviousChannel() = 0; + virtual acre::Result updateChannelDetails(const std::vector details) = 0; + virtual acre::Result updateShouldSwitchChannel(const bool state) = 0; + virtual bool shouldSwitchChannel() = 0; + + virtual std::uint64_t findChannelByNames(std::vector details_) = 0; + + bool gethadVAD() const noexcept { return had_vad; } + void sethadVAD(const bool value_) noexcept { had_vad = value_; } + + bool getInputActive() const noexcept { return input_active; } + void setInputActive(const bool value_) noexcept { input_active = value_; } + + bool getOnRadio() const noexcept { return on_radio; } + void setOnRadio(const bool value_) noexcept { on_radio = value_; } + + std::int32_t getTsSpeakingState() const noexcept { return speaking_state; } + void setTsSpeakingState(const std::int32_t value_) noexcept { speaking_state = value_; } + + bool getRadioPTTDown() const noexcept { return radioPTTDown; } + void setRadioPTTDown(const bool value_) noexcept { radioPTTDown = value_; } + + bool getIntercomPTTDown() const noexcept { return intercom_ptt_down; } + void setIntercomPTTDown(const bool value_) noexcept { intercom_ptt_down = value_; } + + bool getMainPTTDown() const noexcept { return main_ptt_down; } + void setMainPTTDown(const bool value_) noexcept { main_ptt_down = value_; } + + bool getDirectFirst() const noexcept { return direct_first; } + void setDirectFirst(const bool value_) noexcept { direct_first = value_; } + + bool getHitTSSpeakingEvent() const noexcept { return hit_speaking_event; } + void setHitTSSpeakingEvent(const bool value_) noexcept { hit_speaking_event = value_; } + + bool getIsX3DInitialized() const noexcept { return x3d_initialized; } + + void setIsX3DInitialized(const bool value_) noexcept { x3d_initialized = value_; } + + std::uint32_t getSpeakerMask() const noexcept { return speaker_mask; } + void setSpeakerMask(const std::uint32_t value_) noexcept { speaker_mask = value_; } + + virtual std::uint64_t getPreviousChannel() const noexcept { return previous_channel; } + virtual void setPreviousChannel(const std::uint64_t value_) noexcept { previous_channel = value_; } + + virtual const std::vector &getChannelDetails() const noexcept { return channel_details; } + virtual void setChannelDetails(const std::vector &value_) noexcept { channel_details = value_; } - virtual void setState(const acre::State value) = 0; - virtual acre::State getState() const = 0; + virtual bool getShouldSwitchChannel() const noexcept { return should_switch_channel; } + virtual void setShouldSwitchChannel(const bool value_) noexcept { should_switch_channel = value_; } + + acre::State getState() const noexcept { return state; } + void setState(acre::State value) noexcept { state = value; } + +protected: + virtual std::uint32_t getWordMatches(const std::string& string1_, const std::string& string2_) noexcept { + std::vector words1; + std::vector words2; + + std::string temp; + std::stringstream stringstream1(string1_); + + while (stringstream1 >> temp) { + words1.push_back(temp); + } + std::stringstream stringstream2(string2_); + while (stringstream2 >> temp) { + words2.push_back(temp); + } + + std::int32_t matches = 0; + for (auto& word1 : words1) { + for (auto& word2 : words2) { + if (word1 == word2) { + matches++; + } + } + } + return matches; + } + + virtual std::uint32_t levenshteinDistance(const std::string& string1_, const std::string& string2_) noexcept { + std::int32_t length1 = string1_.size(); + const std::int32_t length2 = string2_.size(); + + const decltype(length1) columnStart = decltype(length1)(1); + + decltype(length1)* const column = new decltype(length1)[length1 + 1]; + std::iota(column + columnStart, column + length1 + 1, columnStart); + + for (auto x = columnStart; x <= length2; x++) { + column[0] = x; + std::int32_t lastDiagonal = x - columnStart; + for (auto y = columnStart; y <= length1; y++) { + const int32_t oldDiagonal = column[y]; + const std::initializer_list possibilities = { + column[y] + 1, + column[y - 1] + 1, + lastDiagonal + (string1_[y - 1] == string2_[x - 1] ? 0 : 1) + }; + column[y] = min(possibilities); + lastDiagonal = oldDiagonal; + } + } + const std::int32_t result = column[length1]; + delete[] column; + return result; + } + + virtual std::string removeSubstrings(std::string string_, std::string substring_) noexcept { + const std::string::size_type substringLength = substring_.length(); + for (auto iterator = string_.find(substring_); + iterator != std::string::npos; + iterator = string_.find(substring_)) + string_.erase(iterator, substringLength); + return string_; + } + +private: + bool had_vad = false; + bool input_active = false; + bool on_radio = false; + + std::int32_t speaking_state = 0; + + bool radioPTTDown = false; + bool intercom_ptt_down = false; + bool main_ptt_down = false; + bool direct_first = false; + bool hit_speaking_event = false; + bool x3d_initialized = false; + + std::uint32_t speaker_mask = 0U; + std::uint64_t previous_channel = 0LU; + + std::vector channel_details; + bool should_switch_channel = false; + + acre::State state = acre::State::stopped; }; + diff --git a/extensions/src/ACRE2TS/TS3Client.cpp b/extensions/src/ACRE2TS/TS3Client.cpp index 28f720fa5..853c0a311 100644 --- a/extensions/src/ACRE2TS/TS3Client.cpp +++ b/extensions/src/ACRE2TS/TS3Client.cpp @@ -7,12 +7,6 @@ #include "shlobj.h" #include "Shlwapi.h" #include "Log.h" -#include -#include -#include -#include -#include -#include #include "AcreSettings.h" @@ -26,7 +20,7 @@ extern TS3Functions ts3Functions; //TS3Functions CTS3Client::ts3Functions; acre::Result CTS3Client::initialize(void) { - setPreviousTSChannel(INVALID_TS3_CHANNEL); + setPreviousChannel(INVALID_TS3_CHANNEL); return acre::Result::ok; } @@ -482,15 +476,15 @@ acre::Result CTS3Client::unMuteAll( void ) { return acre::Result::ok; } -acre::Result CTS3Client::moveToServerTS3Channel() { +acre::Result CTS3Client::moveToServerChannel() { if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { anyID clientId; - std::vector details = getTs3ChannelDetails(); + std::vector details = getChannelDetails(); if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; - if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousTSChannel() == INVALID_TS3_CHANNEL) { - setPreviousTSChannel(currentChannelId); + if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousChannel() == INVALID_TS3_CHANNEL) { + setPreviousChannel(currentChannelId); } const uint64_t channelId = findChannelByNames(details); @@ -503,23 +497,23 @@ acre::Result CTS3Client::moveToServerTS3Channel() { } } } - setShouldSwitchTS3Channel(false); + setShouldSwitchChannel(false); return acre::Result::ok; } -acre::Result CTS3Client::moveToPreviousTS3Channel() { +acre::Result CTS3Client::moveToPreviousChannel() { if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { anyID clientId; if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok) { - const uint64_t channelId = getPreviousTSChannel(); + const uint64_t channelId = getPreviousChannel(); if (channelId != INVALID_TS3_CHANNEL && channelId != currentChannelId) { ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, "", nullptr); } } } - setPreviousTSChannel(INVALID_TS3_CHANNEL); + setPreviousChannel(INVALID_TS3_CHANNEL); } return acre::Result::ok; } @@ -587,79 +581,19 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { return INVALID_TS3_CHANNEL; } -unsigned int CTS3Client::getWordMatches(const std::string& string1_, const std::string& string2_) { - std::vector words1, words2; - std::string temp; - std::stringstream stringstream1(string1_); - while (stringstream1 >> temp) { - words1.push_back(temp); - } - std::stringstream stringstream2(string2_); - while (stringstream2 >> temp) { - words2.push_back(temp); - } - - int32_t matches = 0; - for (auto& word1 : words1) { - for (auto& word2 : words2) { - if (word1 == word2) { - matches++; - } - } - } - return matches; -} - -uint32_t CTS3Client::levenshteinDistance(const std::string& string1_, const std::string& string2_) { - int32_t length1 = string1_.size(); - const int32_t length2 = string2_.size(); - - const decltype(length1) columnStart = decltype(length1)(1); - - decltype(length1)*const column = new decltype(length1)[length1 + 1]; - std::iota(column + columnStart, column + length1 + 1, columnStart); - - for (auto x = columnStart; x <= length2; x++) { - column[0] = x; - int32_t lastDiagonal = x - columnStart; - for (auto y = columnStart; y <= length1; y++) { - const int32_t oldDiagonal = column[y]; - const std::initializer_list possibilities = { - column[y] + 1, - column[y - 1] + 1, - lastDiagonal + (string1_[y - 1] == string2_[x - 1] ? 0 : 1) - }; - column[y] = min(possibilities); - lastDiagonal = oldDiagonal; - } - } - const int32_t result = column[length1]; - delete[] column; - return result; -} - -std::string CTS3Client::removeSubstrings(std::string string_, std::string substring_) { - const std::string::size_type substringLength = substring_.length(); - for (auto iterator = string_.find(substring_); - iterator != std::string::npos; - iterator = string_.find(substring_)) - string_.erase(iterator, substringLength); - return string_; -} - -acre::Result CTS3Client::updateTs3ChannelDetails(std::vector details_) { - setTs3ChannelDetails(details_); +acre::Result CTS3Client::updateChannelDetails(std::vector details_) { + setChannelDetails(details_); if (!details_.empty()) { - updateShouldSwitchTS3Channel(true); + updateShouldSwitchChannel(true); } return acre::Result::ok; } -acre::Result CTS3Client::updateShouldSwitchTS3Channel(const bool state_) { - setShouldSwitchTS3Channel(state_); +acre::Result CTS3Client::updateShouldSwitchChannel(const bool state_) { + setShouldSwitchChannel(state_); return acre::Result::ok; } -bool CTS3Client::shouldSwitchTS3Channel() { - return getShouldSwitchTS3Channel(); +bool CTS3Client::shouldSwitchChannel() { + return getShouldSwitchChannel(); } diff --git a/extensions/src/ACRE2TS/TS3Client.h b/extensions/src/ACRE2TS/TS3Client.h index 6603e617f..8be13ca02 100644 --- a/extensions/src/ACRE2TS/TS3Client.h +++ b/extensions/src/ACRE2TS/TS3Client.h @@ -11,27 +11,29 @@ class CTS3Client: public IClient { //static TS3Functions ts3Functions; - CTS3Client() { }; - ~CTS3Client() { }; + CTS3Client() = default; + ~CTS3Client() final = default; - acre::Result initialize( void ); + acre::Result initialize( void ) final; - acre::Result setMuted(const acre::id_t id_, const bool muted_); - acre::Result setMuted(std::list idList_, const bool muted_); + acre::Result setMuted(const acre::id_t id_, const bool muted_) final; + acre::Result setMuted(std::list idList_, const bool muted_) final; - acre::Result getMuted(const acre::id_t id_); + acre::Result getMuted(const acre::id_t id_) final; - acre::Result stop(); - acre::Result start(const acre::id_t id_); + acre::Result stop() final; + acre::Result start(const acre::id_t id_) final; acre::Result exPersistVersion( void ); acre::Result setClientMetadata(const char *const data); - acre::Result enableMicrophone(const bool status_); + acre::Result enableMicrophone(const bool status_) final; bool getInputStatus(); + bool getVAD(); + /*! * \brief Handles local player starting speaking. * @@ -39,7 +41,7 @@ class CTS3Client: public IClient { * * \return acre::Result::ok if operation successful */ - acre::Result localStartSpeaking(const acre::Speaking speakingType_); + acre::Result localStartSpeaking(const acre::Speaking speakingType_) final; /*! * \brief Handles local player starting speaking. @@ -49,7 +51,7 @@ class CTS3Client: public IClient { * * \return acre::Result::ok if operation successful */ - acre::Result localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_); + acre::Result localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_) final; /*! * \brief Handles local player stopping speaking. @@ -58,52 +60,29 @@ class CTS3Client: public IClient { * * \return acre::Result::ok if operation successful */ - acre::Result localStopSpeaking(const acre::Speaking speakingType_ ); + acre::Result localStopSpeaking(const acre::Speaking speakingType_ ) final; - std::string getTempFilePath( void ); - std::string getConfigFilePath(void); + std::string getTempFilePath( void ) final; + std::string getConfigFilePath(void) final; - acre::Result playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_); + acre::Result playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) final; - std::string getUniqueId( ); + std::string getUniqueId( ) final; - bool getVAD(); + acre::Result microphoneOpen(const bool status_) final; - acre::Result microphoneOpen(const bool status_); - - acre::Result unMuteAll( void ); - - acre::Result moveToServerTS3Channel(); - acre::Result moveToPreviousTS3Channel(); - uint64 findChannelByNames(std::vector details_); - uint32_t getWordMatches(const std::string& string1_, const std::string& string2_); - uint32_t levenshteinDistance(const std::string& string1_, const std::string& string2_); - std::string removeSubstrings(std::string string_, std::string substring_); - acre::Result updateTs3ChannelDetails(std::vector details_); - acre::Result updateShouldSwitchTS3Channel(const bool state_); - bool shouldSwitchTS3Channel(); - - - inline void setState(acre::State value) final { m_state = value; } - inline acre::State getState() const final { return m_state; } - - DECLARE_MEMBER(bool, hadVAD); - DECLARE_MEMBER(bool, InputActive); - DECLARE_MEMBER(bool, OnRadio); - DECLARE_MEMBER(int32_t, TsSpeakingState); - DECLARE_MEMBER(bool, RadioPTTDown); - DECLARE_MEMBER(bool, IntercomPTTDown); - DECLARE_MEMBER(bool, MainPTTDown); - DECLARE_MEMBER(bool, DirectFirst); - DECLARE_MEMBER(bool, HitTSSpeakingEvent); - DECLARE_MEMBER(bool, IsX3DInitialized); - DECLARE_MEMBER(uint32_t, SpeakerMask); - DECLARE_MEMBER(uint64, PreviousTSChannel); - DECLARE_MEMBER(std::vector, Ts3ChannelDetails); - DECLARE_MEMBER(bool, ShouldSwitchTS3Channel) -protected: - std::thread m_versionThreadHandle; - char *m_vadLevel; + acre::Result unMuteAll( void ) final; - acre::State m_state; + acre::Result moveToServerChannel() final; + acre::Result moveToPreviousChannel() final; + uint64 findChannelByNames(std::vector details_) final; + + acre::Result updateChannelDetails(std::vector details_) final; + acre::Result updateShouldSwitchChannel(const bool state_) final; + bool shouldSwitchChannel() final; + +private: + + std::thread m_versionThreadHandle; + char *m_vadLevel = nullptr; }; diff --git a/extensions/src/ACRE2TS/TsCallbacks_channelEvents.cpp b/extensions/src/ACRE2TS/TsCallbacks_channelEvents.cpp index 4c9d4827a..b76638e09 100644 --- a/extensions/src/ACRE2TS/TsCallbacks_channelEvents.cpp +++ b/extensions/src/ACRE2TS/TsCallbacks_channelEvents.cpp @@ -82,5 +82,5 @@ void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID cl } void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) { - CEngine::getInstance()->getClient()->updateShouldSwitchTS3Channel(true); + CEngine::getInstance()->getClient()->updateShouldSwitchChannel(true); } From 7353c725694555db2cefaffb62c1fc3343c6b113 Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Sat, 2 May 2020 12:03:20 -0700 Subject: [PATCH 002/104] Dump of initial work, very much WIP. Will **NOT** compile. --- extensions/CMakeLists.txt | 1 + extensions/src/ACRE2Mumble/CMakeLists.txt | 31 ++ extensions/src/ACRE2Mumble/CommandServer.cpp | 67 +++ extensions/src/ACRE2Mumble/CommandServer.h | 42 ++ .../MumbleCallbacks_channelEvents.cpp | 86 ++++ .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 112 +++++ .../MumbleCallbacks_pluginEvents.cpp | 36 ++ .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 132 ++++++ .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 70 +++ .../ACRE2Mumble/MumbleCallbacks_static.cpp | 90 ++++ extensions/src/ACRE2Mumble/MumbleClient.cpp | 428 ++++++++++++++++++ extensions/src/ACRE2Mumble/MumbleClient.h | 86 ++++ extensions/src/ACRE2Mumble/MumbleFunctions.h | 4 + .../src/ACRE2Mumble/acre2_mumble_dllmain.cpp | 25 + .../ACRE2Mumble/mumble_includes/MumbleAPI.h | 237 ++++++++++ .../mumble_includes/MumblePlugin.h | 353 +++++++++++++++ .../mumble_includes/PluginComponents.h | 313 +++++++++++++ 17 files changed, 2113 insertions(+) create mode 100644 extensions/src/ACRE2Mumble/CMakeLists.txt create mode 100644 extensions/src/ACRE2Mumble/CommandServer.cpp create mode 100644 extensions/src/ACRE2Mumble/CommandServer.h create mode 100644 extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp create mode 100644 extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp create mode 100644 extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp create mode 100644 extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp create mode 100644 extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp create mode 100644 extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp create mode 100644 extensions/src/ACRE2Mumble/MumbleClient.cpp create mode 100644 extensions/src/ACRE2Mumble/MumbleClient.h create mode 100644 extensions/src/ACRE2Mumble/MumbleFunctions.h create mode 100644 extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp create mode 100644 extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h create mode 100644 extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h create mode 100644 extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index 3d31cc349..deb3e89d5 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -69,6 +69,7 @@ add_subdirectory(src/ACRE2Arma) add_subdirectory(src/ACRE2Steam) add_subdirectory(src/ACRE2TS) +add_subdirectory(src/ACRE2Mumble) #Extras add_subdirectory(src/Wav2B64) diff --git a/extensions/src/ACRE2Mumble/CMakeLists.txt b/extensions/src/ACRE2Mumble/CMakeLists.txt new file mode 100644 index 000000000..9bdbb055b --- /dev/null +++ b/extensions/src/ACRE2Mumble/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required (VERSION 3.10) + +set(ACRE_NAME "ACRE2Mumble") + +acre_set_build_output() +acre_set_linker_options() + +enable_language(ASM_MASM) +file(GLOB_RECURSE SOURCES *.h *.hpp *.c *.cpp *.asm mumble_includes/*) + +include_directories(mumble_includes) + +add_library( ${ACRE_NAME} MODULE ${SOURCES} ${GLOBAL_SOURCES}) +target_link_libraries(${ACRE_NAME} ACRE2Core ACRE2Shared x3daudio) +set_target_properties(${ACRE_NAME} PROPERTIES FOLDER ACRE2 LINK_FLAGS -SAFESEH:NO) +target_compile_features(${ACRE_NAME} PRIVATE cxx_std_17) + + +# Copy and rename +if(USE_64BIT_BUILD) + set(FINAL_DLL_NAME acre2_win64.dll) +else() + set(FINAL_DLL_NAME acre2_win32.dll) +endif() + +add_custom_command(TARGET ${ACRE_NAME} POST_BUILD + # Copy DLL to plugins + COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_SOURCE_DIR}/../plugin/mumble/${FINAL_DLL_NAME} + # Copy PDB to symbols + COMMAND ${CMAKE_COMMAND} -E copy $/${ACRE_NAME}.pdb ${PROJECT_SOURCE_DIR}/../symbols/mumble/${ACRE_ARCH}/${ACRE_NAME}.pdb +) diff --git a/extensions/src/ACRE2Mumble/CommandServer.cpp b/extensions/src/ACRE2Mumble/CommandServer.cpp new file mode 100644 index 000000000..589626720 --- /dev/null +++ b/extensions/src/ACRE2Mumble/CommandServer.cpp @@ -0,0 +1,67 @@ +#include "CommandServer.h" + +#include "MumbleFunctions.h" + +#include "TextMessage.h" +#include "Log.h" + +#include "MumbleClient.h" + +extern MumbleAPI mumAPI; +extern mumble_connection_t activeConnection; +extern plugin_id_t ownID; + +acre::Result CMumbleCommandServer::initialize(void){ + TRACE("enter"); + + return acre::Result::ok; +} + +acre::Result CMumbleCommandServer::shutdown(void) { + TRACE("enter"); + + return acre::Result::ok; +} + + +acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ + LOCK(this); + + delete msg; + + UNLOCK(this); + + return acre::Result::ok; +} + +acre::Result CMumbleCommandServer::handleMessage(unsigned char *data){ + CTextMessage *msg; + //LOG("recv: [%s]", data); + msg = new CTextMessage((char *)data, strlen((char *)data)); + if (CEngine::getInstance()->getRpcEngine() && (msg != nullptr)) { + CEngine::getInstance()->getRpcEngine()->runProcedure((IServer *)this, (IMessage *)msg); + } + return acre::Result::ok; +} + + +acre::Result CMumbleCommandServer::release(void) { + + + return acre::Result::ok; +} + + +// +// constructor/destructor foo +// +CMumbleCommandServer::CMumbleCommandServer(const acre::id_t id) { + this->setId(id); +} +CMumbleCommandServer::CMumbleCommandServer(void) { + this->setCommandId(0); + this->setConnected(true); +} +CMumbleCommandServer::~CMumbleCommandServer() { + +} diff --git a/extensions/src/ACRE2Mumble/CommandServer.h b/extensions/src/ACRE2Mumble/CommandServer.h new file mode 100644 index 000000000..fc0c8f58e --- /dev/null +++ b/extensions/src/ACRE2Mumble/CommandServer.h @@ -0,0 +1,42 @@ +#pragma once + +#include "compat.h" +#include "Types.h" +#include "Macros.h" +#include "IMessage.h" +#include "IServer.h" + +#include "Engine.h" +#include "Lockable.h" + +#include "MumbleFunctions.h" + +class CMumbleCommandServer : public IServer, public CLockable +{ +public: + CMumbleCommandServer(void); + CMumbleCommandServer(const acre::id_t id); + ~CMumbleCommandServer(void); + + acre::Result initialize(void); + acre::Result shutdown(void); + + acre::Result sendMessage(IMessage *msg); + acre::Result handleMessage(unsigned char *msg); + + acre::Result release(void); + + inline void setCommandId(plugin_id_t value) { m_commandId = value; } + inline plugin_id_t getCommandId() const { return m_commandId; } + + inline void setConnected(const bool value) final { m_connected = value; } + inline bool getConnected() const final { return m_connected; } + + inline void setId(const acre::id_t value) final { m_id = value; } + inline acre::id_t getId() const final { return m_id; } + +protected: + acre::id_t m_id; + bool m_connected; + plugin_id_t m_commandId; +}; diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp new file mode 100644 index 000000000..b76638e09 --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp @@ -0,0 +1,86 @@ +#include "compat.h" + +#include "teamspeak/public_errors.h" +#include "teamspeak/public_definitions.h" +#include "teamspeak/public_rare_definitions.h" +#include "ts3_functions.h" + +#include "Log.h" + +#include "TsCallbacks.h" + +#include "Engine.h" +#include "Types.h" +#include "AcreSettings.h" + +extern TS3Functions ts3Functions; + +// +// Handle move events for silencing +// +void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage) { + + // Only unmute if teamspeak is not linked to ARMA. + if (!CAcreSettings::getInstance()->getDisableUnmuteClients() && !(CEngine::getInstance()->getGameServer()->getConnected())) { + + // Get local client ID + anyID myID; + + if (ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) { + return; // Exit if we don't + } + + //Unmute all clients if local user moves. + if (clientID == myID) { + + anyID* clientsInChannel; + if (ts3Functions.getChannelClientList(serverConnectionHandlerID, newChannelID, &clientsInChannel) == ERROR_ok) { + //Unmute clients in the current channel + ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientsInChannel, NULL); + } + ts3Functions.freeMemory(clientsInChannel); + } else { + //Only unmute joining user when not current client. + anyID clientIDArray[2]; // List of clients to unmute. + clientIDArray[0] = clientID; // Client ID to unmute + clientIDArray[1] = 0; // Mark end of array with a 0 value. + ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientIDArray, NULL); + } + } + +} + +void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID moverID, const char* moverName, const char* moverUniqueIdentifier, const char* moveMessage) { + // Only unmute if teamspeak is not linked to ARMA. + if (!CAcreSettings::getInstance()->getDisableUnmuteClients() && !(CEngine::getInstance()->getGameServer()->getConnected())) { + + // Get local client ID + anyID myID; + + if (ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) { + return; // Exit if we don't + } + + //Unmute all clients if local user moves. + if (clientID == myID) { + + anyID* clientsInChannel; + if (ts3Functions.getChannelClientList(serverConnectionHandlerID, newChannelID, &clientsInChannel) == ERROR_ok) { + //Unmute clients in the current channel + ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientsInChannel, NULL); + } + ts3Functions.freeMemory(clientsInChannel); + } + else { + //Only unmute joining user when not current client. + anyID clientIDArray[2]; // List of clients to unmute. + clientIDArray[0] = clientID; // Client ID to unmute + clientIDArray[1] = 0; // Mark end of array with a 0 value. + ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientIDArray, NULL); + } + } +} + +void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) { + CEngine::getInstance()->getClient()->updateShouldSwitchChannel(true); +} diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp new file mode 100644 index 000000000..0f561f27e --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -0,0 +1,112 @@ +#include "compat.h" + +#include "Log.h" +#include "Engine.h" +#include "MumbleClient.h" +#include "CommandServer.h" +#include "helpers.h" + +#include "MumbleFunctions.h" + +#define FROM_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_fromTS" +#define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toTS" + +extern MumbleAPI mumAPI; +mumble_connection_t activeConnection = -1; +plugin_id_t pluginID = -1; +/* +const char* ts3plugin_name() { + return ACRE_NAME; +} +const char* ts3plugin_version() { + return ACRE_VERSION; +} +int ts3plugin_apiVersion() { + const int32_t api = getTSAPIVersion(); + + // API Compatibility + // v23 + onPluginCommandEvent_v23 = (api < 23) ? 0 : 1; + + return api; +} +const char* ts3plugin_author() { + return ACRE_TEAM_URL; +} +const char* ts3plugin_description() { + return ACRE_DESC; +} +void ts3plugin_setFunctionPointers(const struct TS3Functions funcs) { + ts3Functions = funcs; +} +*/ + + +void registerPluginID(plugin_id_t id) { + pluginID = id; + if (CEngine::getInstance() != NULL) { + if (((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer()) != NULL) { + ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); + } + } +} + +uint32_t getFeatures() { + return FEATURE_AUDIO; +} + +// +// Init +// +int ts3plugin_init() { + + + return 0; +} + +mumble_error_t init() { + CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); + + // if PluginID was already loaded. + if (pluginID != -1) ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); + if (activeConnection != -1) { + // we are activating while connected, call it + // virtualize a connect event + onServerConnected(activeConnection); + } + + return STATUS_OK; +} + + +void onServerConnected(mumble_connection_t connection) { + activeConnection = connection; + + // + // set ID on every new connection + acre::id_t clientId = 0; + //ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), (anyID*)& clientId); + mumAPI.getLocalUserID(pluginID, activeConnection, (mumble_userid_t*)& clientId); + CEngine::getInstance()->getSelf()->setId(clientId); + + // subscribe to all channels to receive event + //ts3Functions.requestChannelSubscribeAll(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); + if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { + CEngine::getInstance()->getClient()->start(static_cast(id)); + } +} + +void onServerDisconnected(mumble_connection_t connection) { + activeConnection = -1; + + if (CEngine::getInstance()->getClient()->getState() != acre::State::stopped && CEngine::getInstance()->getClient()->getState() != acre::State::stopping) { + CEngine::getInstance()->getClient()->stop(); + } +} + +void shutdown() { + if (CEngine::getInstance()->getClient()->getState() != acre::State::stopped && CEngine::getInstance()->getClient()->getState() != acre::State::stopping) { + CEngine::getInstance()->getClient()->stop(); + } + CEngine::getInstance()->stop(); +} diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp new file mode 100644 index 000000000..b6d456606 --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp @@ -0,0 +1,36 @@ +#include "compat.h" + +#include "teamspeak/public_errors.h" +#include "teamspeak/public_definitions.h" +#include "teamspeak/public_rare_definitions.h" +#include "ts3_functions.h" + +#include "CommandServer.h" + +#include "Log.h" + +#include "TsCallbacks.h" + + + +// +// Handle a command event +// +void ts3plugin_onPluginCommandEvent(uint64 serverConnectionHandlerID, const char* pluginName, const char* pluginCommand) { + //LOG("[%s], [%s]", pluginName, pluginCommand); + + if (pluginName && pluginCommand) { + // this we pass to a custom TS3 IServer to handle the damn messages + if (strstr(pluginName, "acre2") != NULL && CEngine::getInstance()->getExternalServer() ) { + CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *)pluginCommand); + } + } +} + +// API Compatibility +// v23 +void ts3plugin_onPluginCommandEvent_v23(uint64 serverConnectionHandlerID, const char* pluginName, const char* pluginCommand, anyID invokerClientID, const char* invokerName, const char* invokerUniqueIdentity) { + //LOG("[%s], [%s]", invokerName, invokerUniqueIdentity); + + ts3plugin_onPluginCommandEvent(serverConnectionHandlerID, pluginName, pluginCommand); +} diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp new file mode 100644 index 000000000..65a2abdb3 --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -0,0 +1,132 @@ +#include "compat.h" + +#include "teamspeak/public_errors.h" +#include "teamspeak/public_definitions.h" +#include "teamspeak/public_rare_definitions.h" +#include "ts3_functions.h" + +#include "FilterVolume.h" +#include "FilterPosition.h" + +#include "Engine.h" + +#include "Log.h" + +#include "TsCallbacks.h" + +#include "TS3Client.h" + +#include "Wave.h" + +#include +#define _USE_MATH_DEFINES + +#include +#include + +#include "AcreDsp.h" + + +extern TS3Functions ts3Functions; + +typedef std::numeric_limits LIMITER; + +void ts3plugin_onEditPlaybackVoiceDataEvent(uint64 server, anyID id, short* samples, int sampleCount, int channels) { + if (CEngine::getInstance()->getSoundSystemOverride()) + return; + if (!CEngine::getInstance()->getGameServer()) + return; + if (!CEngine::getInstance()->getGameServer()->getConnected()) + return; + + int gainAtten; + ts3Functions.getClientVariableAsInt(server, id, CLIENT_VOLUME_MODIFICATOR, &gainAtten); + + float gain = (float)pow(10, (float)gainAtten / 20.0f); + + for (int c = 0; c <= sampleCount - 1; ++c) { + + float result = static_cast(samples[c]) * gain; + + if (result > LIMITER::max())result = LIMITER::max(); + else if (result < LIMITER::min()) result = LIMITER::min(); + + samples[c] = (short)(result); + } + + CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent(static_cast(id), samples, sampleCount, channels); +} + +void ts3plugin_onEditPostProcessVoiceDataEvent(uint64 server, anyID id, short* samples, int sampleCount, int channels, const unsigned int* channelSpeakerArray, unsigned int* channelFillMask) { + //CEngine::getInstance()->getSoundEngine()->onEditPostProcessVoiceDataEvent((acre::id_t)id, samples, sampleCount, channels, channelSpeakerArray, channelFillMask); + //memset(samples, 0x00, (sampleCount*channels)*sizeof(short) ); + //*channelFillMask = (1<getSoundSystemOverride()) + return; + if (!CEngine::getInstance()->getGameServer()) + return; + if (!CEngine::getInstance()->getGameServer()->getConnected()) + return; + UINT32 speakerMask = 0; + if (!((CTS3Client *)(CEngine::getInstance()->getClient()))->getIsX3DInitialized()) + { + + if (channelSpeakerArray[0] >= 0x10000000) { + for (int c = 0; c < channels; c++) { + //LOG("c: %d i: %08x o: %08x", c, channelSpeakerArray[c], this->getChannelMask(channelSpeakerArray[c])); + speakerMask |= channelSpeakerArray[c]; + } + LOG("WARNING! WARNING! Teamspeak is possibly running in Windows Audio Session playback mode. This mode does not correctly determine surround sound channels!"); + LOG("WARNING! WARNING! ACRE IS NOW INITIALIZING POSITIONAL AUDIO IN STEREO MODE!"); + LOG("Speaker setup init: %08x [%dx%d] (2CH = %08x, 5.1CH = %08x/%08x, 7.1CH = %08x/%08x)", speakerMask, sampleCount, channels, SPEAKER_STEREO, SPEAKER_5POINT1, SPEAKER_5POINT1_SURROUND, SPEAKER_7POINT1, SPEAKER_7POINT1_SURROUND); + speakerMask = SPEAKER_STEREO; + } + else { + for (int c = 0; c < channels; c++) { + //LOG("c: %d i: %08x o: %08x", c, channelSpeakerArray[c], this->getChannelMask(channelSpeakerArray[c])); + speakerMask |= channelSpeakerArray[c]; + } + LOG("Speaker setup init: %08x [%dx%d] (2CH = %08x, 5.1CH = %08x/%08x, 7.1CH = %08x/%08x)", speakerMask, sampleCount, channels, SPEAKER_STEREO, SPEAKER_5POINT1, SPEAKER_5POINT1_SURROUND, SPEAKER_7POINT1, SPEAKER_7POINT1_SURROUND); + } + ((CTS3Client *)(CEngine::getInstance()->getClient()))->setIsX3DInitialized(TRUE); + ((CTS3Client *)(CEngine::getInstance()->getClient()))->setSpeakerMask(speakerMask); + } + else + { + speakerMask = ((CTS3Client *)(CEngine::getInstance()->getClient()))->getSpeakerMask(); + } + *channelFillMask = (1 << channels) - 1; + + //LOG("EXIT: ts3plugin_onEditMixedPlaybackVoiceDataEvent: sampleCount=%d,channels=%d,speakerMask=%08x,channelFillMask=%08x", sampleCount, channels, speakerMask, *channelFillMask); + + /* + int gainAtten; + ts3Functions.getClientSelfVariableAsInt(serverConnectionHandlerID, CLIENT_VOLUME_MODIFICATOR, &gainAtten); + + float gain = (float)pow(10, (float)gainAtten / 20.0f); + + for (int c = 0; c <= sampleCount - 1; ++c) { + + int32_t result = samples[c] * gain; + + if (result > LIMITER::max())result = LIMITER::max(); + else if (result < LIMITER::min()) result = LIMITER::min(); + + samples[c] = (short)(result); + } + */ + CEngine::getInstance()->getSoundEngine()->onEditMixedPlaybackVoiceDataEvent(samples, sampleCount, channels, speakerMask); +} + +void ts3plugin_onEditCapturedVoiceDataEvent(uint64 server, short* samples, int sampleCount, int channels, int* edited) { + CEngine::getInstance()->getSoundEngine()->onEditCapturedVoiceDataEvent(samples, sampleCount, channels); +} diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp new file mode 100644 index 000000000..53542dfcc --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -0,0 +1,70 @@ +#include "compat.h" + +#include "teamspeak/public_errors.h" +#include "teamspeak/public_definitions.h" +#include "teamspeak/public_rare_definitions.h" +#include "ts3_functions.h" + +#include "Types.h" +#include "Macros.h" + +#include "Engine.h" + +#include "Log.h" + +#include "TsCallbacks.h" +#include "TS3Client.h" + +// +// TS3 Speaking callbacks +// +void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int status, int isReceivedWhisper, anyID clientID) { + + if (static_cast(clientID) != CEngine::getInstance()->getSelf()->getId()) { + return; + } else if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { + return; + } else if (!CEngine::getInstance()->getGameServer()) { + return; + } else if (CEngine::getInstance()->getState() != acre::State::running) { + return; + } else if (!CEngine::getInstance()->getGameServer()->getConnected()) { + return; + } + + ((CTS3Client *) (CEngine::getInstance()->getClient()))->setTsSpeakingState(status); + if (CEngine::getInstance()->getSoundSystemOverride()) { + return; + } else if (((CTS3Client *) (CEngine::getInstance()->getClient()))->getOnRadio()) { + if (((CTS3Client *) (CEngine::getInstance()->getClient()))->getVAD()) { + return; + } else { + if (status == STATUS_NOT_TALKING) { + if (!((CTS3Client *) (CEngine::getInstance()->getClient()))->getRadioPTTDown()) { + ((CTS3Client *) (CEngine::getInstance()->getClient()))->setOnRadio(false); + } else { + if (!((CTS3Client *) (CEngine::getInstance()->getClient()))->getDirectFirst()) { + ((CTS3Client *) (CEngine::getInstance()->getClient()))->microphoneOpen(true); + } else { + ((CTS3Client *) (CEngine::getInstance()->getClient()))->setDirectFirst(false); + if (((CTS3Client *) (CEngine::getInstance()->getClient()))->getRadioPTTDown()) { + ((CTS3Client *) (CEngine::getInstance()->getClient()))->microphoneOpen(true); + } + } + } + } + return; + } + return; + } + TRACE("enter: [%d],[%d]", clientID, status); + + if (status == STATUS_TALKING) { + ((CTS3Client *) (CEngine::getInstance()->getClient()))->setDirectFirst(true); + CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::direct); + } else if (status == STATUS_NOT_TALKING) { + ((CTS3Client *) (CEngine::getInstance()->getClient()))->setDirectFirst(false); + CEngine::getInstance()->getClient()->localStopSpeaking(acre::Speaking::direct); + ((CTS3Client *) (CEngine::getInstance()->getClient()))->setMainPTTDown(false); + } +} diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp new file mode 100644 index 000000000..670902f5e --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -0,0 +1,90 @@ +#include "compat.h" +#include "Types.h" +#include "Macros.h" +#include "Engine.h" +#include "Player.h" + + +#include "TsFunctions.h" + +#ifdef USE_ACRE2UI + #include "UiEngine.hpp" +#endif + +#include "Log.h" + +extern TS3Functions ts3Functions; + +const char* ts3plugin_commandKeyword() { + return ACRE_COMMAND_KEYWORD; +} +int ts3plugin_requestAutoload() { + return 1; +} + +const char* ts3plugin_infoTitle() { + return ACRE_NAME; +} + +void ts3plugin_infoData(uint64 serverConnectionHandlerID, uint64 id, enum PluginItemType type, char** data) { + /*serverConnectionHandlerID = serverConnectionHandlerID; + data = data; + type = type; + id = id;*/ + + BOOL noAcre = FALSE; + char* metaData; + + switch(type) { + case PLUGIN_SERVER: + break; + case PLUGIN_CHANNEL: + break; + case PLUGIN_CLIENT: + if (ts3Functions.getClientVariableAsString(serverConnectionHandlerID, (anyID)id, CLIENT_META_DATA, &metaData) == ERROR_ok) { + std::string result; + std::string_view sharedMsg; + if (!metaData) { + noAcre = true; + } else { + sharedMsg = metaData; + const size_t start_pos = sharedMsg.find(START_DATA); + const size_t end_pos = sharedMsg.find(END_DATA); + if ((start_pos == std::string::npos) || (end_pos == std::string::npos)) { + noAcre = true; + } else { + result = sharedMsg.substr(start_pos + strlen(START_DATA), end_pos - start_pos - strlen(START_DATA)); + } + } + *data = (char*)malloc(INFODATA_BUFSIZE * sizeof(char)); + if (data != nullptr) { + if (!noAcre) { + _snprintf_s(*data, INFODATA_BUFSIZE, INFODATA_BUFSIZE, "%s\n", result.c_str()); + ts3Functions.freeMemory(metaData); + } else { + _snprintf_s(*data, INFODATA_BUFSIZE, INFODATA_BUFSIZE, "NO ACRE"); + ts3Functions.freeMemory(metaData); + } + } + } + break; + default: + break; + } +} + +void ts3plugin_freeMemory(void* data) { + free(data); +} +// add plugin configuration crap +int ts3plugin_offersConfigure() { + return PLUGIN_OFFERS_NO_CONFIGURE; +} +void ts3plugin_configure(void* handle, void* qParentWidget) { + +} + +int ts3plugin_onServerErrorEvent(uint64 serverConnectionHandlerID, const char* errorMessage, unsigned int error, const char* returnCode, const char* extraMessage) { + + return 0; /* If no plugin return code was used, the return value of this function is ignored */ +} diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp new file mode 100644 index 000000000..3d1c6daca --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -0,0 +1,428 @@ +#include "compat.h" + +#include "MumbleClient.h" +#include "Engine.h" +#include "Types.h" +#include "MumbleFunctions.h" +#include "shlobj.h" +#include "Shlwapi.h" +#include "Log.h" + +#include "AcreSettings.h" + +#pragma comment(lib, "Shlwapi.lib") + +#define INVALID_TS3_CHANNEL -1 +#define DEFAULT_TS3_CHANNEL "ACRE" + +extern MumbleAPI mumAPI; +extern plugin_id_t pluginID; + +//TS3Functions CMumbleClient::ts3Functions; + +acre::Result CMumbleClient::initialize(void) { + setPreviousChannel(INVALID_TS3_CHANNEL); + return acre::Result::ok; +} + +acre::Result CMumbleClient::setMuted(const acre::id_t id_, const bool muted_) { + (void)id_; + (void)muted_; + return acre::Result::ok; +} + +acre::Result CMumbleClient::setMuted(std::list idList_, bool muted_) { + (void)idList_; + (void)muted_; + return acre::Result::ok; +} + +acre::Result CMumbleClient::getMuted(acre::id_t id_) { + (void)id_; + return acre::Result::ok; +} + +acre::Result CMumbleClient::stop() { + if (CEngine::getInstance() != NULL) { + CEngine::getInstance()->stop(); + this->setState(acre::State::stopping); + if (this->m_versionThreadHandle.joinable()) { + this->m_versionThreadHandle.join(); + } + this->setState(acre::State::stopped); + + } + return acre::Result::ok; +} + +acre::Result CMumbleClient::start(const acre::id_t id_) { + CEngine::getInstance()->start(id_); + this->setInputActive(false); + this->setDirectFirst(false); + this->setMainPTTDown(false); + this->setRadioPTTDown(false); + this->setIntercomPTTDown(false); + this->setHitTSSpeakingEvent(false); + this->setOnRadio(false); + this->setState(acre::State::running); + this->setIsX3DInitialized(false); + + //this->m_versionThreadHandle = std::thread(&CMumbleClient::exPersistVersion, this); + + return acre::Result::ok; +} + +/* +acre::Result CMumbleClient::exPersistVersion( void ) { + + CMumbleClient::setClientMetadata(ACRE_VERSION_METADATA); + + ts3Functions.printMessageToCurrentTab("ACRE2 loaded and initialized"); + ts3Functions.printMessageToCurrentTab(ACRE_VERSION_METADATA); + + clock_t run = clock() / CLOCKS_PER_SEC; + clock_t delta = run; + while (this->getState() == acre::State::running && CEngine::getInstance()->getExternalServer()) { + + delta = (clock() / CLOCKS_PER_SEC) - run; + if (delta > (PERSIST_VERSION_TIMER / 1000) ) { + char selfVariableBuffer[4096]; + if (CEngine::getInstance()->getGameServer()->getConnected()) { + _snprintf_s(selfVariableBuffer, 4094, "%s\nArma Connected: Yes", ACRE_VERSION_METADATA); + } else { + _snprintf_s(selfVariableBuffer, 4094, "%s\nArma Connected: No", ACRE_VERSION_METADATA); + } + CMumbleClient::setClientMetadata(selfVariableBuffer); + run = clock() / CLOCKS_PER_SEC; + } + + Sleep(100); + } + + return acre::Result::error; +} + + +acre::Result CMumbleClient::setClientMetadata(const char *const data) { + char* clientInfo; + anyID myID; + ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &myID); + ts3Functions.getClientVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), myID, CLIENT_META_DATA, &clientInfo); + std::string to_set; + std::string_view sharedMsg = clientInfo; + const size_t start_pos = sharedMsg.find(START_DATA); + const size_t end_pos = sharedMsg.find(END_DATA); + if ((start_pos == std::string::npos) || (end_pos == std::string::npos)) { + to_set = to_set + START_DATA + data + END_DATA; + } else { + const std::string before = (std::string)sharedMsg.substr(0, start_pos); + const std::string after = (std::string)sharedMsg.substr(end_pos + strlen(END_DATA), std::string::npos); + to_set = before + START_DATA + data + END_DATA + after; + } + ts3Functions.setClientSelfVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_META_DATA, to_set.c_str()); + ts3Functions.freeMemory(clientInfo); + ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); + return acre::Result::ok; +} +*/ + +bool CMumbleClient::getVAD() { + return false; +} + +acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType_) { + this->localStartSpeaking(speakingType_, ""); + return acre::Result::ok; +} + +acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_) { + bool stopDirectSpeaking = false; + + /* Open or close the microphone. If the microphone is still active, stop direct speaking before + * starting the new PTT method: radio speaking. In theory this would not be needed for intercom since + * at the moment it is a direct speak with audio effect. However, it is planned to have intercoms converted + * to components and unique IDs. + */ + if ((speakingType_ == acre::Speaking::radio) || (speakingType_ == acre::Speaking::intercom)) { + if (speakingType_ == acre::Speaking::radio) { + this->setRadioPTTDown(true); + this->setOnRadio(true); + } else { + this->setIntercomPTTDown(true); + } + + if (!this->getVAD()) { + if (!this->getDirectFirst()) { + this->microphoneOpen(true); + } else { + stopDirectSpeaking = true; + } + } else if (this->getVAD() && (this->getTsSpeakingState() == 1)) { + stopDirectSpeaking = true; + } + } + + if (!this->getVAD() && speakingType_ == acre::Speaking::direct) { + this->microphoneOpen(true); + } + + if (stopDirectSpeaking) { + CEngine::getInstance()->localStopSpeaking(); + } + CEngine::getInstance()->localStartSpeaking(speakingType_, radioId_); + return acre::Result::ok; +} + +acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_) { + bool resendDirectSpeaking = false; + switch (speakingType_) { + case acre::Speaking::direct: + if (!this->getVAD()) { + this->microphoneOpen(false); + } + break; + case acre::Speaking::radio: + this->setRadioPTTDown(false); + break; + case acre::Speaking::intercom: + this->setIntercomPTTDown(false); + break; + case acre::Speaking::unknown: + this->setRadioPTTDown(false); + this->setIntercomPTTDown(false); + break; + default: + break; + } + + if (this->getOnRadio()) { + if (!this->getVAD()) { + if ((speakingType_ == acre::Speaking::radio) && this->getDirectFirst()) { + this->setOnRadio(false); + resendDirectSpeaking = true; + } else { + if (!((CMumbleClient *) (CEngine::getInstance()->getClient()))->getMainPTTDown()) { + this->microphoneOpen(false); + } else { + resendDirectSpeaking = true; + } + } + } else { + this->setOnRadio(false); + if (this->getTsSpeakingState() == 1) { + resendDirectSpeaking = true; + } + } + } else if (speakingType_ == acre::Speaking::intercom) { + if (!this->getVAD()) { + if (!((CMumbleClient *) (CEngine::getInstance()->getClient()))->getIntercomPTTDown()) { + this->microphoneOpen(false); + } else { + resendDirectSpeaking = true; + } + } else if (this->getTsSpeakingState() == 1) { + resendDirectSpeaking = true; + } + } + + CEngine::getInstance()->localStopSpeaking(); + if (resendDirectSpeaking) { + CEngine::getInstance()->localStartSpeaking(acre::Speaking::direct); + } + + return acre::Result::ok; +} + +acre::Result CMumbleClient::enableMicrophone(const bool status_) { + + return acre::Result::ok; +} + + +acre::Result CMumbleClient::playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) { + return acre::Result::ok; +} + +std::string CMumbleClient::getUniqueId( ) { + return "not used"; +} + +std::string CMumbleClient::getConfigFilePath(void) { + char tempPath[MAX_PATH - 14]; + + std::string tempFolder = ".\\acre"; + if (!PathFileExistsA(tempFolder.c_str())) { + if (!CreateDirectoryA(tempFolder.c_str(), NULL)) { + LOG("ERROR: UNABLE TO CREATE TEMP DIR"); + } + } + + return tempFolder; +} + +std::string CMumbleClient::getTempFilePath( void ) { + char tempPath[MAX_PATH - 14]; + GetTempPathA(sizeof(tempPath), tempPath); + std::string tempFolder = std::string(tempPath); + tempFolder += "\\acre"; + if (!PathFileExistsA(tempFolder.c_str())) { + if (!CreateDirectoryA(tempFolder.c_str(), NULL)) { + LOG("ERROR: UNABLE TO CREATE TEMP DIR"); + } + } + + return tempFolder; +} + +acre::Result CMumbleClient::microphoneOpen(bool status_) { + mumble_error_t res; + if (status_) { + res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, true); + if (res != ErrorCode::EC_OK) { + LOG("Error toggling PTT Open\n"); + return acre::Result::error; + } + this->setInputActive(true); + } else { + res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, false); + if (res != ErrorCode::EC_OK) { + LOG("Error toggling PTT Closed\n"); + return acre::Result::error; + } + this->setInputActive(false); + } + return acre::Result::ok; +} + +acre::Result CMumbleClient::unMuteAll( void ) { + + return acre::Result::ok; +} + +acre::Result CMumbleClient::moveToServerChannel() { + /* + if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { + anyID clientId; + std::vector details = getChannelDetails(); + + if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { + uint64_t currentChannelId = INVALID_TS3_CHANNEL; + if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousChannel() == INVALID_TS3_CHANNEL) { + setPreviousChannel(currentChannelId); + } + + const uint64_t channelId = findChannelByNames(details); + if ((channelId != INVALID_TS3_CHANNEL) && (channelId != currentChannelId)) { + std::string password = ""; + if (details.at(1) != "" && details.at(0) != "") { + password = details.at(1); + } + ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr); + } + } + } + setShouldSwitchChannel(false); + */ + return acre::Result::ok; +} + +acre::Result CMumbleClient::moveToPreviousChannel() { + /* + if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { + anyID clientId; + if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { + uint64_t currentChannelId = INVALID_TS3_CHANNEL; + if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok) { + const uint64_t channelId = getPreviousChannel(); + if (channelId != INVALID_TS3_CHANNEL && channelId != currentChannelId) { + ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, "", nullptr); + } + } + } + setPreviousChannel(INVALID_TS3_CHANNEL); + } + */ + return acre::Result::ok; +} + +uint64_t CMumbleClient::findChannelByNames(std::vector details_) { + /* + uint64_t *channelList; + if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { + uint64_t channelId = INVALID_TS3_CHANNEL; + uint64_t defaultChannelId = INVALID_TS3_CHANNEL; + std::map channelMap; + std::string name = details_.at(2); + if (details_.at(0) != "") { + name = details_.at(0); + } + while (*channelList) { + channelId = *channelList; + channelList++; + char* channelName; + if (ts3Functions.getChannelVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { + std::string channelNameString = std::string(channelName); + if (channelNameString.find(DEFAULT_TS3_CHANNEL) != -1 || (details_.at(0) != "" && channelNameString == name)) { + if (channelNameString == DEFAULT_TS3_CHANNEL) { + defaultChannelId = channelId; + } + channelMap.emplace(channelId, channelNameString); + } + } + } + + uint64_t bestChannelId = INVALID_TS3_CHANNEL; + int32_t bestMatches = 0; + int32_t bestDistance = 10; + for (auto& element : channelMap) { + std::string fullChannelName = element.second; + // Full comparison + if (fullChannelName.compare(name) == 0) { + bestChannelId = element.first; + break; + } + const std::string cleanChannelName = removeSubstrings(fullChannelName, DEFAULT_TS3_CHANNEL); + // Word comparison + const int32_t matches = getWordMatches(cleanChannelName, name); + if (matches > bestMatches) { + bestMatches = matches; + bestChannelId = element.first; + continue; + } + // Char comparison + const int32_t distance = levenshteinDistance(cleanChannelName, name); + if (distance <= bestDistance) { + bestDistance = distance; + bestChannelId = element.first; + } + } + if (bestChannelId == INVALID_TS3_CHANNEL) { + if (details_.at(0) != "") { + details_.at(0) = ""; + bestChannelId = findChannelByNames(details_); + } else if (defaultChannelId != INVALID_TS3_CHANNEL) { + bestChannelId = defaultChannelId; + } + } + return bestChannelId; + } + */ + return 0; +} + +acre::Result CMumbleClient::updateChannelDetails(std::vector details_) { + setChannelDetails(details_); + if (!details_.empty()) { + updateShouldSwitchChannel(true); + } + return acre::Result::ok; +} + +acre::Result CMumbleClient::updateShouldSwitchChannel(const bool state_) { + setShouldSwitchChannel(state_); + return acre::Result::ok; +} + +bool CMumbleClient::shouldSwitchChannel() { + return getShouldSwitchChannel(); +} diff --git a/extensions/src/ACRE2Mumble/MumbleClient.h b/extensions/src/ACRE2Mumble/MumbleClient.h new file mode 100644 index 000000000..7f1201730 --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleClient.h @@ -0,0 +1,86 @@ +#pragma once + +#include "IClient.h" +#include "MumbleFunctions.h" +#include +#include +#include + +class CMumbleClient: public IClient { +public: + + CMumbleClient() = default; + ~CMumbleClient() final = default; + + acre::Result initialize( void ) final; + + acre::Result setMuted(const acre::id_t id_, const bool muted_) final; + acre::Result setMuted(std::list idList_, const bool muted_) final; + + acre::Result getMuted(const acre::id_t id_) final; + + acre::Result stop() final; + acre::Result start(const acre::id_t id_) final; + + acre::Result exPersistVersion( void ); + + acre::Result setClientMetadata(const char *const data); + + acre::Result enableMicrophone(const bool status_) final; + + bool getInputStatus(); + + bool getVAD(); + + /*! + * \brief Handles local player starting speaking. + * + * \param[in] speakingType_ ACRE speaking type + * + * \return acre::Result::ok if operation successful + */ + acre::Result localStartSpeaking(const acre::Speaking speakingType_) final; + + /*! + * \brief Handles local player starting speaking. + * + * \param[in] speakingType_ ACRE speaking type + * \param[in] radioId_ Unique radio ideintifier + * + * \return acre::Result::ok if operation successful + */ + acre::Result localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_) final; + + /*! + * \brief Handles local player stopping speaking. + * + * \param[in] speakingType_ ACRE speaking type + * + * \return acre::Result::ok if operation successful + */ + acre::Result localStopSpeaking(const acre::Speaking speakingType_ ) final; + + std::string getTempFilePath( void ) final; + std::string getConfigFilePath(void) final; + + acre::Result playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) final; + + std::string getUniqueId( ) final; + + acre::Result microphoneOpen(const bool status_) final; + + acre::Result unMuteAll( void ) final; + + acre::Result moveToServerChannel() final; + acre::Result moveToPreviousChannel() final; + uint64_t findChannelByNames(std::vector details_) final; + + acre::Result updateChannelDetails(std::vector details_) final; + acre::Result updateShouldSwitchChannel(const bool state_) final; + bool shouldSwitchChannel() final; + +private: + bool currentStatus; + std::thread m_versionThreadHandle; + char *m_vadLevel = nullptr; +}; diff --git a/extensions/src/ACRE2Mumble/MumbleFunctions.h b/extensions/src/ACRE2Mumble/MumbleFunctions.h new file mode 100644 index 000000000..5dbbe6b57 --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleFunctions.h @@ -0,0 +1,4 @@ +#pragma once + +#include "MumblePlugin.h" +#include "MumbleAPI.h" diff --git a/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp b/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp new file mode 100644 index 000000000..f6ff06493 --- /dev/null +++ b/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp @@ -0,0 +1,25 @@ +//#include "compat.h" +//#include "Log.h" +#include "MumbleFunctions.h" + +MumbleAPI mumAPI; + + +#pragma comment(lib, "x3daudio.lib") +#pragma comment(lib, "shlwapi.lib") + +/* +[module(dll, name="acre2", version="1.0")]; + + +BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID) { + + if (reason == DLL_PROCESS_ATTACH){ + //g_Log = (Log *)new Log("acre.log"); + } + if (reason == DLL_PROCESS_DETACH) { + + } + return 1; +} +*/ diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h new file mode 100644 index 000000000..1ef62eaa6 --- /dev/null +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h @@ -0,0 +1,237 @@ +// Copyright 2019-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file contains the definition of Mumble's API + +#ifndef MUMBLE_PLUGIN_API_H_ +#define MUMBLE_PLUGIN_API_H_ + +#include "PluginComponents.h" +#include + +// API version +const int32_t MUMBLE_PLUGIN_API_MAJOR = 1; +const int32_t MUMBLE_PLUGIN_API_MINOR = 0; +const int32_t MUMBLE_PLUGIN_API_PATCH = 0; +const version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PLUGIN_API_MINOR, MUMBLE_PLUGIN_API_PATCH }; + + +struct MumbleAPI { + // -------- Memory management -------- + + /// Frees the given pointer. + /// + /// @param callerID The ID of the plugin calling this function + /// @param pointer The pointer to free + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *freeMemory)(plugin_id_t callerID, void *pointer); + + + + // -------- Getter functions -------- + + /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] connection A pointer to the memory location the ID should be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the + /// value of the provided pointer + mumble_error_t (PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t *connection); + + /// Fills in the information about the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID); + + /// Fills in the information about the given user's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The user's ID whose name should be obtained + /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getUserName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, char **userName); + + /// Fills in the information about the given channel's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The channel's ID whose name should be obtained + /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, char **channelName); + + /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter + /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the + /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users, + size_t *userCount); + + /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent + /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the + /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t **channels, size_t *channelCount); + + /// Gets the ID of the channel the given user is currently connected to. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the ID of the channel shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t *channel); + + /// Gets an array of all users in the specified channel. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The ID of the channel whose users shall be retrieved + /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has + /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function + /// returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, mumble_userid_t **userList, size_t *userCount); + + /// Gets the current transmission mode of the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t *transmissionMode); + + + + // -------- Request functions -------- + + /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set + /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of + /// restoring the previous state afterwards. + /// + /// @param callerID The ID of the plugin calling this function + /// @param transmissionMode The requested transmission mode + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); + + /// Requests Mumble to move the given user into the given channel + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param channelID The ID of the channel to move the user to + /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a + /// password for entering + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t channelID, const char *password); + + /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen + /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again + /// once it is no longer required + /// + /// @param callerID The ID of the plugin calling this function + /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); + + + + // -------- Find functions -------- + + /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userName The respective user's name + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t (PLUGIN_CALLING_CONVENTION *findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char *userName, + mumble_userid_t *userID); + + /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelName The respective channel's name + /// @param[out] channelID A pointer to the memory the channel's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t (PLUGIN_CALLING_CONVENTION *findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, + const char *channelName, mumble_channelid_t *channelID); + + + + // -------- Miscellaneous -------- + + /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active + /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data + /// must not contain sensitive information or anything else that shouldn't be known by others. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to send the data through (the server the given users are on) + /// @param users An array of user IDs to send the data to + /// @param userCount The size of the provided user-array + /// @param data The data that shall be sent as a String + /// @param dataLength The length of the data-string + /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with + /// the data + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *users, + size_t userCount, const char *data, size_t dataLength, const char *dataID); + + /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. + /// + /// @param callerID The ID of the plugin calling this function + /// @param message The message to log + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *log)(plugin_id_t callerID, const char *message); + + /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it + /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). + /// + /// @param callerID The ID of the plugin calling this function + /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *playSample)(plugin_id_t callerID, const char *samplePath); +}; + +#endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h new file mode 100644 index 000000000..548d951f5 --- /dev/null +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h @@ -0,0 +1,353 @@ +// Copyright 2019-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file specifies the Mumble plugin interface + +#ifndef EXTERNAL_MUMBLE_PLUGIN_H_ +#define EXTERNAL_MUMBLE_PLUGIN_H_ + +#include "PluginComponents.h" +#include "MumbleAPI.h" +#include +#include +#include + +#if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems + #define PLUGIN_EXPORT __attribute__((visibility("default"))) +#elif defined(_MSC_VER) + #define PLUGIN_EXPORT __declspec(dllexport) +#elif defined(__MINGW32__) + #define PLUGIN_EXPORT __attribute__((dllexport)) +#else + #error No PLUGIN_EXPORT definition available +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Gets called right after loading the plugin in order to let the plugin initialize. + /// + /// @returns The status of the initialization. If everything went fine, return STATUS_OK + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION init(); + + /// Gets called when unloading the plugin in order to allow it to clean up after itself. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION shutdown(); + + /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied + /// for further usage though. + /// + /// @returns A pointer to the plugin name (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION getName(); + + /// Gets the Version of the plugin-API this plugin intends to use. + /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. + /// + /// @return The respective API Version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION getAPIVersion(); + + /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used + /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use + /// of it at some point. + /// + /// @param api The MumbleAPI struct + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION registerAPIFunctions(struct MumbleAPI api); + + + + ////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Tells the plugin some basic information about the Mumble client loading it. + /// This function will be the first one that is being called on this plugin - even before it is decided whether to load + /// the plugin at all. + /// + /// @param mumbleVersion The Version of the Mumble client + /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with + /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); + + /// Gets the Version of this plugin + /// + /// @returns The plugin's version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION getVersion(); + + /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the author(s) name(s) (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION getAuthor(); + + /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the description (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION getDescription(); + + /// Registers the ID of this plugin. This is the ID Mumble will reference this plugin with and by which this plugin + /// can identify itself when communicating with Mumble. + /// + /// @param id The ID for this plugin + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION registerPluginID(uint32_t id); + + /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum + /// together. + /// + /// @returns The feature set of this plugin + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION getFeatures(); + + /// Requests this plugin to deactivate the given (sub)set of provided features. + /// If this is not possible, the features that can't be deactivated shall be returned by this function. + /// + /// Example (check if FEATURE_POSITIONAL shall be deactivated): + /// @code + /// if (features & FEATURE_POSITIONAL) { + /// // positional shall be deactivated + /// }; + /// @endcode + /// + /// @param features The feature set that shall be deactivated + /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return + /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION deactivateFeatures(uint32_t features); + + + + ////////////////////////////////////////////////////////////////////////////////// + //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // If this plugin wants to provide positional audio, all functions of this category + // have to be implemented + + /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently + /// able to do so and allocate memory that is needed for that process. + /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i + /// belongs to a program whose name is listed at index i in the "name-array". + /// + /// @param programNames An array of pointers to the program names + /// @param programPIDs An array of the corresponding program PIDs + /// @param programCount The length of programNames and programPIDs + /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently + /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) + /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be + /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. + PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); + + /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. + /// + /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it + /// is facing). + /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One + /// unit represents one meter of distance. + /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it + /// is facing). + /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit + /// represents one meter of distance. + /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data + /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical + /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function + /// or until shutdownPositionalData is called. + /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can + /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid + /// until the next invokation of this function or until shutdownPositionalData is called. + /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will + /// be called. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, + float *cameraAxis, const char **context, const char **identity); + + /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should + /// be freed at this point. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION shutdownPositionalData(); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Called when connecting to a server. + /// + /// @param connection The ID of the newly established server-connection + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onServerConnected(mumble_connection_t connection); + + /// Called when disconnecting from a server. + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onServerDisconnected(mumble_connection_t connection); + + /// Called when the client has finished synchronizing with the server + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onServerSynchronized(mumble_connection_t connection); + + /// Called whenever any user on the server enters a channel + /// This function will also be called when freshly connecting to a server as each user on that + /// server needs to be "added" to the respective channel as far as the local client is concerned. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user this event has been triggered for + /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user + /// freshly connected to the server) or the channel isn't available because of any other reason. + /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means + /// that the ID is invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, + mumble_channelid_t newChannelID); + + /// Called whenever a user leaves a channel. + /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user that left the channel + /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is + /// invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); + + /// Called when any user changes his/her talking state. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user whose talking state has been changed + /// @param talkingState The new TalkingState the user has switched to. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); + + /// Called whenever there is audio input. + /// + /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) + /// @returns Whether this callback has modified the audio input-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); + + /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). + /// The provided audio buffer is the raw buffer without any processing applied to it yet. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) + /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, + /// the content of this parameter is unspecified and should not be accessed + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); + + /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). + /// Note that this happens immediately before Mumble clips the audio buffer. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); + + /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the + /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended + /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. + /// + /// @param connection The ID of the server-connection the data is coming from + /// @param sender The ID of the user whose client's plugin has sent the data + /// @param data The sent data represented as a string + /// @param dataLength The length of data + /// @param dataID The ID of this data + /// @return Whether the given data has been processed by this plugin + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, + const char *dataID); + + /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the + /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this + /// method will be called for every client already on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been added + + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the + /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this + /// method will be called for every client on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local + /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been added + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local + /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also + /// considered renaming). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been renamed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a key has been pressed or released while Mumble has keyboard focus. + /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard + /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to + /// enable that. + /// + /// @param keyCode The key code of the respective key. The character codes are defined + /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform + /// to the ASCII code-page with the only difference that case is not distinguished. Therefore + /// always the upper-case letter code will be used for letters. + /// @param wasPres Whether the respective key has been pressed (instead of released) + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onKeyEvent(uint32_t keyCode, bool wasPress); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// This function is used to determine whether the plugin can find an update for itself that is available for download. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @return Whether the plugin was able to find an update for itself + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION hasUpdate(); + + /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. + /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure + /// though that you don't forget about the trailing null byte. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into + /// @param bufferSize The size of the buffer + /// @param offset The offset in the URL from which this functions should start writing it to the buffer + /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called + /// again with a modified offset until the URL has been completely transferred. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h new file mode 100644 index 000000000..b203eb1b7 --- /dev/null +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h @@ -0,0 +1,313 @@ +// Copyright 2019-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file contains definitions of types and other components used in Mumble's plugin system + +#ifndef MUMBLE_PLUGINCOMPONENT_H_ +#define MUMBLE_PLUGINCOMPONENT_H_ + +#include +#include +#include + +#ifdef QT_VERSION + #include +#endif + +// define the calling convention macro based on the compiler being used +#if defined(_MSC_VER) + #define PLUGIN_CALLING_CONVENTION __cdecl +#elif defined(__MINGW32__) + #define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) +#else + #define PLUGIN_CALLING_CONVENTION +#endif + + +/// A macro holding the exit status of a successful operation +#define STATUS_OK EC_OK +/// A macro holding the version object that is considered to correspond to an unknown version +#define VERSION_UNKNOWN Version({0,0,0}) + + +/// This enum's values correspond to special feature sets a plugin may provide. +/// They are meant to be or'ed together to represent the total feature set of a plugin. +enum PluginFeature { + /// None of the below + FEATURE_NONE = 0, + /// The plugin provides positional data from a game + FEATURE_POSITIONAL = 1 << 0, + /// The plugin modifies the input/output audio itself + FEATURE_AUDIO = 1 << 1 +}; + +/// This enum's values represent talking states a user can be in when using Mumble. +enum TalkingState { + INVALID=-1, + PASSIVE=0, + TALKING, + WHISPERING, + SHOUTING +}; + +/// This enum's values represent transmission modes a user might have configured. Transmission mode +/// in this context is referring to a method that determines when a user is speaking and thus when +/// to transmit audio packets. +enum TransmissionMode { + TM_CONTINOUS, + TM_VOICE_ACTIVATION, + TM_PUSH_TO_TALK +}; + +/// This enum's values represent the error codes that are being used by the MumbleAPI. +/// You can get a string-representation for each error code via the errorMessage function. +enum ErrorCode { + EC_GENERIC_ERROR = -1, + EC_OK = 0, + EC_POINTER_NOT_FOUND, + EC_NO_ACTIVE_CONNECTION, + EC_USER_NOT_FOUND, + EC_CHANNEL_NOT_FOUND, + EC_CONNECTION_NOT_FOUND, + EC_UNKNOWN_TRANSMISSION_MODE, + EC_AUDIO_NOT_AVAILABLE, + EC_INVALID_SAMPLE, + EC_INVALID_PLUGIN_ID +}; + +/// This enum's values represent error codes specific to the framework of handling positional data +/// gathering (needed for Mumble's positional audio feature). +enum PositionalDataErrorCode { + /// Positional data has been initialized properly + PDEC_OK = 0, + /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be + /// at another point in time. + PDEC_ERROR_TEMP, + /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). + PDEC_ERROR_PERM +}; + +/// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. +enum KeyCode { + KC_INVALID = -1, + + // Non-printable characters first + KC_NULL = 0, + KC_END = 1, + KC_LEFT = 2, + KC_RIGHT = 4, + KC_UP = 5, + KC_DOWN = 6, + KC_DELETE = 7, + KC_BACKSPACE = 8, + KC_TAB = 9, + KC_ENTER = 10, // == '\n' + KC_ESCAPE = 27, + KC_PAGE_UP = 11, + KC_PAGE_DOWN = 12, + KC_SHIFT = 13, + KC_CONTROL = 14, + KC_META = 15, + KC_ALT = 16, + KC_ALT_GR = 17, + KC_CAPSLOCK = 18, + KC_NUMLOCK = 19, + KC_SUPER = 20, // == windows key + KC_HOME = 21, // == Pos1 + KC_PRINT = 22, + KC_SCROLLLOCK = 23, + + // Printable characters are assigned to their ASCII code + KC_SPACE = ' ', + KC_EXCLAMATION_MARK = '!', + KC_DOUBLE_QUOTE = '"', + KC_HASHTAG = '#', + KC_DOLLAR = '$', + KC_PERCENT = '%', + KC_AMPERSAND = '&', + KC_SINGLE_QUOTE = '\'', + KC_OPEN_PARENTHESIS = '(', + KC_CLOSE_PARENTHESIS = ')', + KC_ASTERISK = '*', + KC_PLUS = '+', + KC_COMMA = ',', + KC_MINUS = '-', + KC_PERIOD = '.', + KC_SLASH = '/', + KC_0 = '0', + KC_1 = '1', + KC_2 = '2', + KC_3 = '3', + KC_4 = '4', + KC_5 = '5', + KC_6 = '6', + KC_7 = '7', + KC_8 = '8', + KC_9 = '9', + KC_COLON = ':', + KC_SEMICOLON = ';', + KC_LESS_THAN = '<', + KC_EQUALS = '=', + KC_GREATER_THAN = '>', + KC_QUESTION_MARK = '?', + KC_AT_SYMBOL = '@', + KC_A = 'A', + KC_B = 'B', + KC_C = 'C', + KC_D = 'D', + KC_E = 'E', + KC_F = 'F', + KC_G = 'G', + KC_H = 'H', + KC_I = 'I', + KC_J = 'J', + KC_K = 'K', + KC_L = 'L', + KC_M = 'M', + KC_N = 'N', + KC_O = 'O', + KC_P = 'P', + KC_Q = 'Q', + KC_R = 'R', + KC_S = 'S', + KC_T = 'T', + KC_U = 'U', + KC_V = 'V', + KC_W = 'W', + KC_X = 'X', + KC_Y = 'Y', + KC_Z = 'Z', + // leave out lowercase letters (for now) + KC_OPEN_BRACKET = '[', + KC_BACKSLASH = '\\', + KC_CLOSE_BRACKET = ']', + KC_CIRCUMFLEX = '^', + KC_UNDERSCORE = '_', + KC_GRAVE_AKCENT = '`', + KC_OPEN_BRACE = '{', + KC_VERTICAL_BAR = '|', + KC_CLOSE_BRACE = '}', + KC_TILDE = '~', + + // Some characters from the extended ASCII code + KC_DEGREE_SIGN = 176, + + + + // F-keys + // Start at a value of 256 as extended ASCII codes range up to 256 + KC_F1 = 256, + KC_F2 = 257, + KC_F3 = 258, + KC_F4 = 259, + KC_F5 = 260, + KC_F6 = 261, + KC_F7 = 262, + KC_F8 = 263, + KC_F9 = 264, + KC_F10 = 265, + KC_F11 = 266, + KC_F12 = 267, + KC_F13 = 268, + KC_F14 = 269, + KC_F15 = 270, + KC_F16 = 271, + KC_F17 = 272, + KC_F18 = 273, + KC_F19 = 274, +}; + +/// A struct for representing a version of the form major.minor.patch +struct Version { + int32_t major; + int32_t minor; + int32_t patch; +#ifdef __cplusplus + bool operator<(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; + } + + bool operator>(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; + } + + bool operator>=(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; + } + + bool operator<=(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; + } + + bool operator==(const Version& other) const { + return this->major == other.major && this->minor == other.minor && this->patch == other.patch; + } + + operator std::string() const { + return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); + } + +#ifdef QT_VERSION + operator QString() const { + return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); + } +#endif +#endif +}; + +/// @param errorCode The error code to get a message for +/// @returns The error message coresponding to the given error code. The message +/// is encoded as a C-string and are static meaning that it is safe to use the +/// returned pointer in your code. +inline const char* errorMessage(int16_t errorCode) { + switch (errorCode) { + case EC_GENERIC_ERROR: + return "Generic error"; + case EC_OK: + return "Ok - this is not an error"; + case EC_POINTER_NOT_FOUND: + return "Can't find the passed pointer"; + case EC_NO_ACTIVE_CONNECTION: + return "There is currently no active connection to a server"; + case EC_USER_NOT_FOUND: + return "Can't find the requested user"; + case EC_CHANNEL_NOT_FOUND: + return "Can't find the requested channel"; + case EC_CONNECTION_NOT_FOUND: + return "Can't identify the requested connection"; + case EC_UNKNOWN_TRANSMISSION_MODE: + return "Unknown transmission mode encountered"; + case EC_AUDIO_NOT_AVAILABLE: + return "There is currently no audio output available"; + case EC_INVALID_SAMPLE: + return "Attempted to use invalid sample (can't play it)"; + case EC_INVALID_PLUGIN_ID: + return "Used an invalid plugin ID"; + default: + return "Unknown error code"; + } +} + + +/// Typedef for the type of a talking state +typedef enum TalkingState talking_state_t; +/// Typedef for the type of a transmission mode +typedef enum TransmissionMode transmission_mode_t; +/// Typedef for the type of a version +typedef struct Version version_t; +/// Typedef for the type of a connection +typedef int32_t mumble_connection_t; +/// Typedef for the type of a user +typedef uint32_t mumble_userid_t; +/// Typedef for the type of a channel +typedef int32_t mumble_channelid_t; +/// Typedef for the type of an error (code) +typedef enum ErrorCode mumble_error_t; +/// Typedef for the type of a plugin ID +typedef uint32_t plugin_id_t; +/// Typedef for the type of a key-code +typedef KeyCode keycode_t; + +#endif // MUMBLE_PLUGINCOMPONENT_H_ From db8d5631e260c564772bd60e56f4b36660311888 Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Sun, 3 May 2020 22:28:27 -0700 Subject: [PATCH 003/104] Most of the plugin translated, minus channel stuff --- .../MumbleCallbacks_channelEvents.cpp | 10 +- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 32 ++--- .../MumbleCallbacks_pluginEvents.cpp | 28 ++-- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 136 ++++++++---------- .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 43 +++--- .../ACRE2Mumble/MumbleCallbacks_static.cpp | 74 +--------- extensions/src/ACRE2Mumble/MumbleClient.cpp | 18 ++- ...mandServer.cpp => MumbleCommandServer.cpp} | 26 +++- ...{CommandServer.h => MumbleCommandServer.h} | 4 +- .../mumble_includes/MumblePlugin.h | 66 ++++----- extensions/src/ACRE2Shared/IClient.h | 5 +- extensions/src/ACRE2Shared/IServer.h | 1 + extensions/src/ACRE2Shared/TextMessage.cpp | 14 +- 13 files changed, 179 insertions(+), 278 deletions(-) rename extensions/src/ACRE2Mumble/{CommandServer.cpp => MumbleCommandServer.cpp} (60%) rename extensions/src/ACRE2Mumble/{CommandServer.h => MumbleCommandServer.h} (89%) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp index b76638e09..5e3d22e25 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp @@ -1,18 +1,13 @@ #include "compat.h" -#include "teamspeak/public_errors.h" -#include "teamspeak/public_definitions.h" -#include "teamspeak/public_rare_definitions.h" -#include "ts3_functions.h" -#include "Log.h" -#include "TsCallbacks.h" +#include "Log.h" #include "Engine.h" #include "Types.h" #include "AcreSettings.h" - +/* extern TS3Functions ts3Functions; // @@ -84,3 +79,4 @@ void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID cl void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) { CEngine::getInstance()->getClient()->updateShouldSwitchChannel(true); } +*/ diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 0f561f27e..ded0ffcb7 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -3,13 +3,13 @@ #include "Log.h" #include "Engine.h" #include "MumbleClient.h" -#include "CommandServer.h" +#include "MumbleCommandServer.h" #include "helpers.h" #include "MumbleFunctions.h" -#define FROM_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_fromTS" -#define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toTS" +#define FROM_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_fromMumble" +#define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toMumble" extern MumbleAPI mumAPI; mumble_connection_t activeConnection = -1; @@ -42,7 +42,7 @@ void ts3plugin_setFunctionPointers(const struct TS3Functions funcs) { */ -void registerPluginID(plugin_id_t id) { +void mumble_registerPluginID(plugin_id_t id) { pluginID = id; if (CEngine::getInstance() != NULL) { if (((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer()) != NULL) { @@ -51,20 +51,18 @@ void registerPluginID(plugin_id_t id) { } } -uint32_t getFeatures() { +uint32_t mumble_getFeatures() { return FEATURE_AUDIO; } +void mumble_registerAPIFunctions(struct MumbleAPI api) { + mumAPI = api; +} + // // Init // -int ts3plugin_init() { - - - return 0; -} - -mumble_error_t init() { +mumble_error_t mumble_init() { CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); // if PluginID was already loaded. @@ -72,14 +70,14 @@ mumble_error_t init() { if (activeConnection != -1) { // we are activating while connected, call it // virtualize a connect event - onServerConnected(activeConnection); + mumble_onServerConnected(activeConnection); } return STATUS_OK; } -void onServerConnected(mumble_connection_t connection) { +void mumble_onServerConnected(mumble_connection_t connection) { activeConnection = connection; // @@ -92,11 +90,11 @@ void onServerConnected(mumble_connection_t connection) { // subscribe to all channels to receive event //ts3Functions.requestChannelSubscribeAll(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { - CEngine::getInstance()->getClient()->start(static_cast(id)); + CEngine::getInstance()->getClient()->start(static_cast(clientId)); } } -void onServerDisconnected(mumble_connection_t connection) { +void mumble_onServerDisconnected(mumble_connection_t connection) { activeConnection = -1; if (CEngine::getInstance()->getClient()->getState() != acre::State::stopped && CEngine::getInstance()->getClient()->getState() != acre::State::stopping) { @@ -104,7 +102,7 @@ void onServerDisconnected(mumble_connection_t connection) { } } -void shutdown() { +void mumble_shutdown() { if (CEngine::getInstance()->getClient()->getState() != acre::State::stopped && CEngine::getInstance()->getClient()->getState() != acre::State::stopping) { CEngine::getInstance()->getClient()->stop(); } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp index b6d456606..f3f0598f1 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp @@ -1,36 +1,26 @@ #include "compat.h" -#include "teamspeak/public_errors.h" -#include "teamspeak/public_definitions.h" -#include "teamspeak/public_rare_definitions.h" -#include "ts3_functions.h" - -#include "CommandServer.h" +#include "Engine.h" #include "Log.h" -#include "TsCallbacks.h" +#include "MumbleFunctions.h" // // Handle a command event // -void ts3plugin_onPluginCommandEvent(uint64 serverConnectionHandlerID, const char* pluginName, const char* pluginCommand) { +bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char* data, size_t dataLength, + const char* dataID) { //LOG("[%s], [%s]", pluginName, pluginCommand); - if (pluginName && pluginCommand) { + if (dataLength) { // this we pass to a custom TS3 IServer to handle the damn messages - if (strstr(pluginName, "acre2") != NULL && CEngine::getInstance()->getExternalServer() ) { - CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *)pluginCommand); + if (CEngine::getInstance()->getExternalServer() ) { + CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *)data, dataLength); + return true; } } -} - -// API Compatibility -// v23 -void ts3plugin_onPluginCommandEvent_v23(uint64 serverConnectionHandlerID, const char* pluginName, const char* pluginCommand, anyID invokerClientID, const char* invokerName, const char* invokerUniqueIdentity) { - //LOG("[%s], [%s]", invokerName, invokerUniqueIdentity); - - ts3plugin_onPluginCommandEvent(serverConnectionHandlerID, pluginName, pluginCommand); + return false } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 65a2abdb3..efb920c64 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -1,10 +1,5 @@ #include "compat.h" -#include "teamspeak/public_errors.h" -#include "teamspeak/public_definitions.h" -#include "teamspeak/public_rare_definitions.h" -#include "ts3_functions.h" - #include "FilterVolume.h" #include "FilterPosition.h" @@ -12,9 +7,7 @@ #include "Log.h" -#include "TsCallbacks.h" - -#include "TS3Client.h" +#include "MumbleClient.h" #include "Wave.h" @@ -27,11 +20,10 @@ #include "AcreDsp.h" -extern TS3Functions ts3Functions; - typedef std::numeric_limits LIMITER; -void ts3plugin_onEditPlaybackVoiceDataEvent(uint64 server, anyID id, short* samples, int sampleCount, int channels) { +//void ts3plugin_onEditPlaybackVoiceDataEvent(uint64 server, anyID id, short* samples, int sampleCount, int channels) { +bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID) { if (CEngine::getInstance()->getSoundSystemOverride()) return; if (!CEngine::getInstance()->getGameServer()) @@ -39,94 +31,78 @@ void ts3plugin_onEditPlaybackVoiceDataEvent(uint64 server, anyID id, short* samp if (!CEngine::getInstance()->getGameServer()->getConnected()) return; - int gainAtten; - ts3Functions.getClientVariableAsInt(server, id, CLIENT_VOLUME_MODIFICATOR, &gainAtten); - - float gain = (float)pow(10, (float)gainAtten / 20.0f); + // Make this faster + short* mixdownSamples; + uint32_t mixdownSampleLength = 0; - for (int c = 0; c <= sampleCount - 1; ++c) { - - float result = static_cast(samples[c]) * gain; - - if (result > LIMITER::max())result = LIMITER::max(); - else if (result < LIMITER::min()) result = LIMITER::min(); + //if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { + mixdownSampleLength = sampleCount * channelCount; + mixdownSamples = new short[mixdownSampleLength]; + //} - samples[c] = (short)(result); + for (int c = 0; c <= mixdownSampleLength - 1; ++c) { + mixdownSamples[c] = static_cast(outputPCM[c] / LIMITER::max()); } - CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent(static_cast(id), samples, sampleCount, channels); -} + CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent(static_cast(userID), mixdownSamples, sampleCount, channelCount); -void ts3plugin_onEditPostProcessVoiceDataEvent(uint64 server, anyID id, short* samples, int sampleCount, int channels, const unsigned int* channelSpeakerArray, unsigned int* channelFillMask) { - //CEngine::getInstance()->getSoundEngine()->onEditPostProcessVoiceDataEvent((acre::id_t)id, samples, sampleCount, channels, channelSpeakerArray, channelFillMask); - //memset(samples, 0x00, (sampleCount*channels)*sizeof(short) ); - //*channelFillMask = (1< 0) { + mixedSample = static_cast(mixdownSamples[c] * LIMITER::max()); + } + else { + mixedSample = -static_cast(mixdownSamples[c] * LIMITER::min()); + } + outputPCM[c] = mixedSample; + } + delete[] mixdownSamples; + return true; } -void ts3plugin_onEditMixedPlaybackVoiceDataEvent(uint64 serverConnectionHandlerID, short* samples, int sampleCount, int channels, const unsigned int* channelSpeakerArray, unsigned int* channelFillMask) { - //LOG("ENTER: ts3plugin_onEditMixedPlaybackVoiceDataEvent: sampleCount=%d,channels=%d,channelFillMask=%08x", sampleCount,channels,*channelFillMask); - //for (int x = 0; x < channels; x++) { - // LOG("\tchannelSpeakerArray[%d]=%08x", x, channelSpeakerArray[x]); - //} - //LOG("MAX AFTER: %d", maxSampleAft); + + +bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount) { + if (CEngine::getInstance()->getSoundSystemOverride()) - return; + return false; if (!CEngine::getInstance()->getGameServer()) - return; + return false; if (!CEngine::getInstance()->getGameServer()->getConnected()) - return; + return false; UINT32 speakerMask = 0; - if (!((CTS3Client *)(CEngine::getInstance()->getClient()))->getIsX3DInitialized()) - { - - if (channelSpeakerArray[0] >= 0x10000000) { - for (int c = 0; c < channels; c++) { - //LOG("c: %d i: %08x o: %08x", c, channelSpeakerArray[c], this->getChannelMask(channelSpeakerArray[c])); - speakerMask |= channelSpeakerArray[c]; - } - LOG("WARNING! WARNING! Teamspeak is possibly running in Windows Audio Session playback mode. This mode does not correctly determine surround sound channels!"); - LOG("WARNING! WARNING! ACRE IS NOW INITIALIZING POSITIONAL AUDIO IN STEREO MODE!"); - LOG("Speaker setup init: %08x [%dx%d] (2CH = %08x, 5.1CH = %08x/%08x, 7.1CH = %08x/%08x)", speakerMask, sampleCount, channels, SPEAKER_STEREO, SPEAKER_5POINT1, SPEAKER_5POINT1_SURROUND, SPEAKER_7POINT1, SPEAKER_7POINT1_SURROUND); - speakerMask = SPEAKER_STEREO; - } - else { - for (int c = 0; c < channels; c++) { - //LOG("c: %d i: %08x o: %08x", c, channelSpeakerArray[c], this->getChannelMask(channelSpeakerArray[c])); - speakerMask |= channelSpeakerArray[c]; - } - LOG("Speaker setup init: %08x [%dx%d] (2CH = %08x, 5.1CH = %08x/%08x, 7.1CH = %08x/%08x)", speakerMask, sampleCount, channels, SPEAKER_STEREO, SPEAKER_5POINT1, SPEAKER_5POINT1_SURROUND, SPEAKER_7POINT1, SPEAKER_7POINT1_SURROUND); - } - ((CTS3Client *)(CEngine::getInstance()->getClient()))->setIsX3DInitialized(TRUE); - ((CTS3Client *)(CEngine::getInstance()->getClient()))->setSpeakerMask(speakerMask); - } - else - { - speakerMask = ((CTS3Client *)(CEngine::getInstance()->getClient()))->getSpeakerMask(); - } - *channelFillMask = (1 << channels) - 1; + speakerMask = SPEAKER_STEREO; - //LOG("EXIT: ts3plugin_onEditMixedPlaybackVoiceDataEvent: sampleCount=%d,channels=%d,speakerMask=%08x,channelFillMask=%08x", sampleCount, channels, speakerMask, *channelFillMask); + // Make this faster + short* mixdownSamples; + uint32_t mixdownSampleLength = 0; - /* - int gainAtten; - ts3Functions.getClientSelfVariableAsInt(serverConnectionHandlerID, CLIENT_VOLUME_MODIFICATOR, &gainAtten); - - float gain = (float)pow(10, (float)gainAtten / 20.0f); - - for (int c = 0; c <= sampleCount - 1; ++c) { + //if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { + mixdownSampleLength = sampleCount * channelCount; + mixdownSamples = new short[mixdownSampleLength]; + //} - int32_t result = samples[c] * gain; + for (int c = 0; c <= mixdownSampleLength - 1; ++c) { + mixdownSamples[c] = static_cast(outputPCM[c] / LIMITER::max()); + } - if (result > LIMITER::max())result = LIMITER::max(); - else if (result < LIMITER::min()) result = LIMITER::min(); + CEngine::getInstance()->getSoundEngine()->onEditMixedPlaybackVoiceDataEvent(mixdownSamples, sampleCount, channelCount, speakerMask); - samples[c] = (short)(result); + for (int c = 0; c <= mixdownSampleLength - 1; ++c) { + float mixedSample; + if (mixdownSamples[c] > 0) { + mixedSample = static_cast(mixdownSamples[c] * LIMITER::max()); + } + else { + mixedSample = -static_cast(mixdownSamples[c] * LIMITER::min()); + } + outputPCM[c] = mixedSample; } - */ - CEngine::getInstance()->getSoundEngine()->onEditMixedPlaybackVoiceDataEvent(samples, sampleCount, channels, speakerMask); + delete[] mixdownSamples; + return true; } -void ts3plugin_onEditCapturedVoiceDataEvent(uint64 server, short* samples, int sampleCount, int channels, int* edited) { +void ts3plugin_onEditCapturedVoiceDataEvent(uint64_t server, short* samples, int sampleCount, int channels, int* edited) { CEngine::getInstance()->getSoundEngine()->onEditCapturedVoiceDataEvent(samples, sampleCount, channels); } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index 53542dfcc..e1ca69abb 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -1,9 +1,5 @@ #include "compat.h" -#include "teamspeak/public_errors.h" -#include "teamspeak/public_definitions.h" -#include "teamspeak/public_rare_definitions.h" -#include "ts3_functions.h" #include "Types.h" #include "Macros.h" @@ -12,15 +8,14 @@ #include "Log.h" -#include "TsCallbacks.h" -#include "TS3Client.h" +#include "MumbleClient.h" // // TS3 Speaking callbacks // -void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int status, int isReceivedWhisper, anyID clientID) { +void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t status) { - if (static_cast(clientID) != CEngine::getInstance()->getSelf()->getId()) { + if (static_cast(userID) != CEngine::getInstance()->getSelf()->getId()) { return; } else if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { return; @@ -32,23 +27,23 @@ void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int sta return; } - ((CTS3Client *) (CEngine::getInstance()->getClient()))->setTsSpeakingState(status); + CEngine::getInstance()->getClient()->setSpeakingState(status); if (CEngine::getInstance()->getSoundSystemOverride()) { return; - } else if (((CTS3Client *) (CEngine::getInstance()->getClient()))->getOnRadio()) { - if (((CTS3Client *) (CEngine::getInstance()->getClient()))->getVAD()) { + } else if (CEngine::getInstance()->getClient()->getOnRadio()) { + if (CEngine::getInstance()->getClient()->getVAD()) { return; } else { - if (status == STATUS_NOT_TALKING) { - if (!((CTS3Client *) (CEngine::getInstance()->getClient()))->getRadioPTTDown()) { - ((CTS3Client *) (CEngine::getInstance()->getClient()))->setOnRadio(false); + if (status != TalkingState::PASSIVE && status != TalkingState::INVALID) { + if (!CEngine::getInstance()->getClient()->getRadioPTTDown()) { + CEngine::getInstance()->getClient()->setOnRadio(false); } else { - if (!((CTS3Client *) (CEngine::getInstance()->getClient()))->getDirectFirst()) { - ((CTS3Client *) (CEngine::getInstance()->getClient()))->microphoneOpen(true); + if (!CEngine::getInstance()->getClient()->getDirectFirst()) { + CEngine::getInstance()->getClient()->microphoneOpen(true); } else { - ((CTS3Client *) (CEngine::getInstance()->getClient()))->setDirectFirst(false); - if (((CTS3Client *) (CEngine::getInstance()->getClient()))->getRadioPTTDown()) { - ((CTS3Client *) (CEngine::getInstance()->getClient()))->microphoneOpen(true); + CEngine::getInstance()->getClient()->setDirectFirst(false); + if (CEngine::getInstance()->getClient()->getRadioPTTDown()) { + CEngine::getInstance()->getClient()->microphoneOpen(true); } } } @@ -59,12 +54,12 @@ void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int sta } TRACE("enter: [%d],[%d]", clientID, status); - if (status == STATUS_TALKING) { - ((CTS3Client *) (CEngine::getInstance()->getClient()))->setDirectFirst(true); + if (status != TalkingState::PASSIVE && status != TalkingState::INVALID) { + CEngine::getInstance()->getClient()->setDirectFirst(true); CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::direct); - } else if (status == STATUS_NOT_TALKING) { - ((CTS3Client *) (CEngine::getInstance()->getClient()))->setDirectFirst(false); + } else { + CEngine::getInstance()->getClient()->setDirectFirst(false); CEngine::getInstance()->getClient()->localStopSpeaking(acre::Speaking::direct); - ((CTS3Client *) (CEngine::getInstance()->getClient()))->setMainPTTDown(false); + CEngine::getInstance()->getClient()->setMainPTTDown(false); } } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp index 670902f5e..c995d8c8f 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -5,7 +5,7 @@ #include "Player.h" -#include "TsFunctions.h" +#include "MumbleFunctions.h" #ifdef USE_ACRE2UI #include "UiEngine.hpp" @@ -13,78 +13,12 @@ #include "Log.h" -extern TS3Functions ts3Functions; - -const char* ts3plugin_commandKeyword() { - return ACRE_COMMAND_KEYWORD; -} -int ts3plugin_requestAutoload() { - return 1; -} - -const char* ts3plugin_infoTitle() { +const char* mumble_getName() { return ACRE_NAME; } -void ts3plugin_infoData(uint64 serverConnectionHandlerID, uint64 id, enum PluginItemType type, char** data) { - /*serverConnectionHandlerID = serverConnectionHandlerID; - data = data; - type = type; - id = id;*/ - - BOOL noAcre = FALSE; - char* metaData; - - switch(type) { - case PLUGIN_SERVER: - break; - case PLUGIN_CHANNEL: - break; - case PLUGIN_CLIENT: - if (ts3Functions.getClientVariableAsString(serverConnectionHandlerID, (anyID)id, CLIENT_META_DATA, &metaData) == ERROR_ok) { - std::string result; - std::string_view sharedMsg; - if (!metaData) { - noAcre = true; - } else { - sharedMsg = metaData; - const size_t start_pos = sharedMsg.find(START_DATA); - const size_t end_pos = sharedMsg.find(END_DATA); - if ((start_pos == std::string::npos) || (end_pos == std::string::npos)) { - noAcre = true; - } else { - result = sharedMsg.substr(start_pos + strlen(START_DATA), end_pos - start_pos - strlen(START_DATA)); - } - } - *data = (char*)malloc(INFODATA_BUFSIZE * sizeof(char)); - if (data != nullptr) { - if (!noAcre) { - _snprintf_s(*data, INFODATA_BUFSIZE, INFODATA_BUFSIZE, "%s\n", result.c_str()); - ts3Functions.freeMemory(metaData); - } else { - _snprintf_s(*data, INFODATA_BUFSIZE, INFODATA_BUFSIZE, "NO ACRE"); - ts3Functions.freeMemory(metaData); - } - } - } - break; - default: - break; - } -} - -void ts3plugin_freeMemory(void* data) { - free(data); -} -// add plugin configuration crap -int ts3plugin_offersConfigure() { - return PLUGIN_OFFERS_NO_CONFIGURE; -} -void ts3plugin_configure(void* handle, void* qParentWidget) { - +version_t mumble_getAPIVersion() { + return MUMBLE_PLUGIN_API_VERSION; } -int ts3plugin_onServerErrorEvent(uint64 serverConnectionHandlerID, const char* errorMessage, unsigned int error, const char* returnCode, const char* extraMessage) { - return 0; /* If no plugin return code was used, the return value of this function is ignored */ -} diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 3d1c6daca..679cf04d5 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -127,6 +127,14 @@ acre::Result CMumbleClient::setClientMetadata(const char *const data) { */ bool CMumbleClient::getVAD() { + transmission_mode_t transmitMode; + mumble_error_t err = mumAPI.getLocalUserTransmissionMode(pluginID, &transmitMode); + if (err != ErrorCode::EC_OK) { + return false; + } + if (transmitMode == TransmissionMode::TM_VOICE_ACTIVATION) { + return true; + } return false; } @@ -157,7 +165,7 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } else { stopDirectSpeaking = true; } - } else if (this->getVAD() && (this->getTsSpeakingState() == 1)) { + } else if (this->getVAD() && (this->getSpeakingState() != TalkingState::PASSIVE && this->getSpeakingState() != TalkingState::INVALID)) { stopDirectSpeaking = true; } } @@ -201,7 +209,7 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ this->setOnRadio(false); resendDirectSpeaking = true; } else { - if (!((CMumbleClient *) (CEngine::getInstance()->getClient()))->getMainPTTDown()) { + if (!CEngine::getInstance()->getClient()->getMainPTTDown()) { this->microphoneOpen(false); } else { resendDirectSpeaking = true; @@ -209,18 +217,18 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ } } else { this->setOnRadio(false); - if (this->getTsSpeakingState() == 1) { + if (this->getSpeakingState() == 1) { resendDirectSpeaking = true; } } } else if (speakingType_ == acre::Speaking::intercom) { if (!this->getVAD()) { - if (!((CMumbleClient *) (CEngine::getInstance()->getClient()))->getIntercomPTTDown()) { + if (!CEngine::getInstance()->getClient()->getIntercomPTTDown()) { this->microphoneOpen(false); } else { resendDirectSpeaking = true; } - } else if (this->getTsSpeakingState() == 1) { + } else if (this->getSpeakingState() == 1) { resendDirectSpeaking = true; } } diff --git a/extensions/src/ACRE2Mumble/CommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp similarity index 60% rename from extensions/src/ACRE2Mumble/CommandServer.cpp rename to extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index 589626720..bcb1108c1 100644 --- a/extensions/src/ACRE2Mumble/CommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -1,4 +1,4 @@ -#include "CommandServer.h" +#include "MumbleCommandServer.h" #include "MumbleFunctions.h" @@ -9,7 +9,7 @@ extern MumbleAPI mumAPI; extern mumble_connection_t activeConnection; -extern plugin_id_t ownID; +extern plugin_id_t pluginId; acre::Result CMumbleCommandServer::initialize(void){ TRACE("enter"); @@ -26,6 +26,14 @@ acre::Result CMumbleCommandServer::shutdown(void) { acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ LOCK(this); + /* + ts3Functions.sendPluginCommand((unsigned __int64)ts3Functions.getCurrentServerConnectionHandlerID(), + (const char*)this->getCommandId(), + (const char*)msg->getData(), + PluginCommandTarget_CURRENT_CHANNEL, NULL, NULL); + */ + + mumAPI.sendData(pluginId) delete msg; @@ -34,12 +42,16 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ return acre::Result::ok; } -acre::Result CMumbleCommandServer::handleMessage(unsigned char *data){ - CTextMessage *msg; - //LOG("recv: [%s]", data); - msg = new CTextMessage((char *)data, strlen((char *)data)); +acre::Result CMumbleCommandServer::handleMessage(unsigned char* data) { + return this->handleMessage(data, strlen((char*)data)); +} + +acre::Result CMumbleCommandServer::handleMessage(unsigned char* data, size_t length) { + CTextMessage* msg; + //TRACE("recv: [%s]", data); + msg = new CTextMessage((char*)data, length); if (CEngine::getInstance()->getRpcEngine() && (msg != nullptr)) { - CEngine::getInstance()->getRpcEngine()->runProcedure((IServer *)this, (IMessage *)msg); + CEngine::getInstance()->getRpcEngine()->runProcedure((IServer*)this, (IMessage*)msg); } return acre::Result::ok; } diff --git a/extensions/src/ACRE2Mumble/CommandServer.h b/extensions/src/ACRE2Mumble/MumbleCommandServer.h similarity index 89% rename from extensions/src/ACRE2Mumble/CommandServer.h rename to extensions/src/ACRE2Mumble/MumbleCommandServer.h index fc0c8f58e..99d67ca05 100644 --- a/extensions/src/ACRE2Mumble/CommandServer.h +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.h @@ -22,7 +22,9 @@ class CMumbleCommandServer : public IServer, public CLockable acre::Result shutdown(void); acre::Result sendMessage(IMessage *msg); - acre::Result handleMessage(unsigned char *msg); + acre::Result handleMessage(unsigned char* msg); + acre::Result handleMessage(unsigned char* msg, size_t length); + acre::Result release(void); diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h index 548d951f5..002ede54c 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h @@ -35,29 +35,29 @@ extern "C" { /// Gets called right after loading the plugin in order to let the plugin initialize. /// /// @returns The status of the initialization. If everything went fine, return STATUS_OK - PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION init(); + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(); /// Gets called when unloading the plugin in order to allow it to clean up after itself. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION shutdown(); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied /// for further usage though. /// /// @returns A pointer to the plugin name (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION getName(); + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); /// Gets the Version of the plugin-API this plugin intends to use. /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. /// /// @return The respective API Version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION getAPIVersion(); + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use /// of it at some point. /// /// @param api The MumbleAPI struct - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION registerAPIFunctions(struct MumbleAPI api); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); @@ -72,36 +72,36 @@ extern "C" { /// @param mumbleVersion The Version of the Mumble client /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); /// Gets the Version of this plugin /// /// @returns The plugin's version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION getVersion(); + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will /// be copied for further usage though. /// /// @returns A pointer to the author(s) name(s) (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION getAuthor(); + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will /// be copied for further usage though. /// /// @returns A pointer to the description (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION getDescription(); + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); /// Registers the ID of this plugin. This is the ID Mumble will reference this plugin with and by which this plugin /// can identify itself when communicating with Mumble. /// /// @param id The ID for this plugin - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION registerPluginID(uint32_t id); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerPluginID(uint32_t id); /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum /// together. /// /// @returns The feature set of this plugin - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION getFeatures(); + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); /// Requests this plugin to deactivate the given (sub)set of provided features. /// If this is not possible, the features that can't be deactivated shall be returned by this function. @@ -116,7 +116,7 @@ extern "C" { /// @param features The feature set that shall be deactivated /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION deactivateFeatures(uint32_t features); + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); @@ -138,7 +138,7 @@ extern "C" { /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. - PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); + PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. /// @@ -163,12 +163,12 @@ extern "C" { /// until the next invokation of this function or until shutdownPositionalData is called. /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will /// be called. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, float *cameraAxis, const char **context, const char **identity); /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should /// be freed at this point. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION shutdownPositionalData(); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); @@ -179,17 +179,17 @@ extern "C" { /// Called when connecting to a server. /// /// @param connection The ID of the newly established server-connection - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onServerConnected(mumble_connection_t connection); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); /// Called when disconnecting from a server. /// /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onServerDisconnected(mumble_connection_t connection); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); /// Called when the client has finished synchronizing with the server /// /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onServerSynchronized(mumble_connection_t connection); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); /// Called whenever any user on the server enters a channel /// This function will also be called when freshly connecting to a server as each user on that @@ -201,7 +201,7 @@ extern "C" { /// freshly connected to the server) or the channel isn't available because of any other reason. /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means /// that the ID is invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, mumble_channelid_t newChannelID); /// Called whenever a user leaves a channel. @@ -211,14 +211,14 @@ extern "C" { /// @param userID The ID of the user that left the channel /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is /// invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); /// Called when any user changes his/her talking state. /// /// @param connection The ID of the server-connection this event is connected to /// @param userID The ID of the user whose talking state has been changed /// @param talkingState The new TalkingState the user has switched to. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); /// Called whenever there is audio input. /// @@ -228,7 +228,7 @@ extern "C" { /// @param channelCount The amount of channels in the audio /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) /// @returns Whether this callback has modified the audio input-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). /// The provided audio buffer is the raw buffer without any processing applied to it yet. @@ -241,7 +241,7 @@ extern "C" { /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, /// the content of this parameter is unspecified and should not be accessed /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). /// Note that this happens immediately before Mumble clips the audio buffer. @@ -251,7 +251,7 @@ extern "C" { /// @param sampleCount The amount of sample points per channel /// @param channelCount The amount of channels in the audio /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended @@ -263,7 +263,7 @@ extern "C" { /// @param dataLength The length of data /// @param dataID The ID of this data /// @return Whether the given data has been processed by this plugin - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, const char *dataID); /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the @@ -273,7 +273,7 @@ extern "C" { /// @param connection An object used to identify the current connection /// @param userID The ID of the user that has been added - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this @@ -281,7 +281,7 @@ extern "C" { /// /// @param connection An object used to identify the current connection /// @param userID The ID of the user that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case @@ -289,7 +289,7 @@ extern "C" { /// /// @param connection An object used to identify the current connection /// @param channelID The ID of the channel that has been added - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case @@ -297,14 +297,14 @@ extern "C" { /// /// @param connection An object used to identify the current connection /// @param channelID The ID of the channel that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also /// considered renaming). /// /// @param connection An object used to identify the current connection /// @param channelID The ID of the channel that has been renamed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); /// Called when a key has been pressed or released while Mumble has keyboard focus. /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard @@ -316,7 +316,7 @@ extern "C" { /// to the ASCII code-page with the only difference that case is not distinguished. Therefore /// always the upper-case letter code will be used for letters. /// @param wasPres Whether the respective key has been pressed (instead of released) - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION onKeyEvent(uint32_t keyCode, bool wasPress); + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); @@ -329,7 +329,7 @@ extern "C" { /// NOTE: This function may be called without the plugin being loaded /// /// @return Whether the plugin was able to find an update for itself - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION hasUpdate(); + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure @@ -342,7 +342,7 @@ extern "C" { /// @param offset The offset in the URL from which this functions should start writing it to the buffer /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called /// again with a modified offset until the URL has been completely transferred. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); #ifdef __cplusplus diff --git a/extensions/src/ACRE2Shared/IClient.h b/extensions/src/ACRE2Shared/IClient.h index f9a8238c2..7898a7bda 100644 --- a/extensions/src/ACRE2Shared/IClient.h +++ b/extensions/src/ACRE2Shared/IClient.h @@ -49,6 +49,7 @@ class IClient { virtual acre::Result updateChannelDetails(const std::vector details) = 0; virtual acre::Result updateShouldSwitchChannel(const bool state) = 0; virtual bool shouldSwitchChannel() = 0; + virtual bool getVAD() = 0; virtual std::uint64_t findChannelByNames(std::vector details_) = 0; @@ -61,8 +62,8 @@ class IClient { bool getOnRadio() const noexcept { return on_radio; } void setOnRadio(const bool value_) noexcept { on_radio = value_; } - std::int32_t getTsSpeakingState() const noexcept { return speaking_state; } - void setTsSpeakingState(const std::int32_t value_) noexcept { speaking_state = value_; } + std::int32_t getSpeakingState() const noexcept { return speaking_state; } + void setSpeakingState(const std::int32_t value_) noexcept { speaking_state = value_; } bool getRadioPTTDown() const noexcept { return radioPTTDown; } void setRadioPTTDown(const bool value_) noexcept { radioPTTDown = value_; } diff --git a/extensions/src/ACRE2Shared/IServer.h b/extensions/src/ACRE2Shared/IServer.h index b3213e7f8..31f75b39d 100644 --- a/extensions/src/ACRE2Shared/IServer.h +++ b/extensions/src/ACRE2Shared/IServer.h @@ -16,6 +16,7 @@ class IServer { virtual acre::Result sendMessage(IMessage *const msg) = 0; virtual acre::Result handleMessage(unsigned char *const data) = 0; + virtual acre::Result handleMessage(unsigned char* msg, size_t length) = 0; virtual acre::Result release(void) = 0; diff --git a/extensions/src/ACRE2Shared/TextMessage.cpp b/extensions/src/ACRE2Shared/TextMessage.cpp index fdad6a27e..01d29e00d 100644 --- a/extensions/src/ACRE2Shared/TextMessage.cpp +++ b/extensions/src/ACRE2Shared/TextMessage.cpp @@ -22,19 +22,7 @@ acre::Result CTextMessage::parse(char *const value, const size_t len) { return acre::Result::ok; } - // Check to make sure the entire chunk of data is a NULL terminated ascii string - for (size_t x = 0 ; x < len; x++) { - if (!__isascii(value[x]) && value[x] != 0x00) { - this->m_IsValid = false; - LOG("INVALID PACKET DETECTED l:%d", len); - return acre::Result::error; - } - if (value[x] == 0x00) { // null terminate, bail - break; - } - } - - const size_t length = strlen(value) + 1; + const size_t length = len + 1; if (length < 3) { this->m_IsValid = false; return acre::Result::error; From 8a891a67c122fa8127ee5c6a69f1573ce15daa09 Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Mon, 4 May 2020 12:27:57 -0700 Subject: [PATCH 004/104] Compilable version of Mumble plugin --- extensions/src/ACRE2Core/NamedPipeServer.h | 4 +++- .../ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp | 2 +- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 6 +++--- extensions/src/ACRE2Mumble/MumbleCommandServer.cpp | 13 ++++++++----- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/extensions/src/ACRE2Core/NamedPipeServer.h b/extensions/src/ACRE2Core/NamedPipeServer.h index 59c386268..65314ca91 100644 --- a/extensions/src/ACRE2Core/NamedPipeServer.h +++ b/extensions/src/ACRE2Core/NamedPipeServer.h @@ -22,7 +22,9 @@ class CNamedPipeServer : public IServer, public CLockable { acre::Result initialize( void ); acre::Result shutdown( void ); - acre::Result handleMessage(unsigned char *data) { (void) data; return acre::Result::notImplemented; } + acre::Result handleMessage(unsigned char* data) { (void)data; return acre::Result::notImplemented; } + acre::Result handleMessage(unsigned char* data, size_t length) { (void)data; return acre::Result::notImplemented; } + acre::Result sendMessage( IMessage *message ); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp index f3f0598f1..94c81c11e 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp @@ -22,5 +22,5 @@ bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender return true; } } - return false + return false; } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index efb920c64..6448d7874 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -25,11 +25,11 @@ typedef std::numeric_limits LIMITER; //void ts3plugin_onEditPlaybackVoiceDataEvent(uint64 server, anyID id, short* samples, int sampleCount, int channels) { bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID) { if (CEngine::getInstance()->getSoundSystemOverride()) - return; + return false; if (!CEngine::getInstance()->getGameServer()) - return; + return false; if (!CEngine::getInstance()->getGameServer()->getConnected()) - return; + return false; // Make this faster short* mixdownSamples; diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index bcb1108c1..612266828 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -9,7 +9,7 @@ extern MumbleAPI mumAPI; extern mumble_connection_t activeConnection; -extern plugin_id_t pluginId; +extern plugin_id_t pluginID; acre::Result CMumbleCommandServer::initialize(void){ TRACE("enter"); @@ -32,8 +32,13 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ (const char*)msg->getData(), PluginCommandTarget_CURRENT_CHANNEL, NULL, NULL); */ - - mumAPI.sendData(pluginId) + mumble_userid_t* channelUsers; + size_t userCount; + mumble_channelid_t currentChannel; + mumAPI.getChannelOfUser(pluginID, activeConnection, CEngine::getInstance()->getSelf()->getId(), ¤tChannel); + mumAPI.getUsersInChannel(pluginID, activeConnection, currentChannel, &channelUsers, &userCount); + mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const char*)msg->getData(), msg->getLength(), "ACRE2"); + mumAPI.freeMemory(pluginID, (void *)&channelUsers); delete msg; @@ -58,8 +63,6 @@ acre::Result CMumbleCommandServer::handleMessage(unsigned char* data, size_t len acre::Result CMumbleCommandServer::release(void) { - - return acre::Result::ok; } From 88874aaf45d84ab76a731f7e82d531e7ec285b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Mon, 4 May 2020 21:33:08 +0200 Subject: [PATCH 005/104] small modifications --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 15 ++--- .../MumbleCallbacks_pluginEvents.cpp | 4 +- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 55 +++++++++++-------- extensions/src/ACRE2Mumble/MumbleClient.cpp | 8 +-- .../src/ACRE2Mumble/MumbleCommandServer.cpp | 4 +- 5 files changed, 48 insertions(+), 38 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index ded0ffcb7..6e8cf4567 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -44,10 +44,8 @@ void ts3plugin_setFunctionPointers(const struct TS3Functions funcs) { void mumble_registerPluginID(plugin_id_t id) { pluginID = id; - if (CEngine::getInstance() != NULL) { - if (((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer()) != NULL) { - ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); - } + if ((CEngine::getInstance() != nullptr) && (((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer()) != nullptr)) { + ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); } } @@ -66,7 +64,10 @@ mumble_error_t mumble_init() { CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); // if PluginID was already loaded. - if (pluginID != -1) ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); + if (pluginID != -1) { + ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); + } + if (activeConnection != -1) { // we are activating while connected, call it // virtualize a connect event @@ -97,13 +98,13 @@ void mumble_onServerConnected(mumble_connection_t connection) { void mumble_onServerDisconnected(mumble_connection_t connection) { activeConnection = -1; - if (CEngine::getInstance()->getClient()->getState() != acre::State::stopped && CEngine::getInstance()->getClient()->getState() != acre::State::stopping) { + if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { CEngine::getInstance()->getClient()->stop(); } } void mumble_shutdown() { - if (CEngine::getInstance()->getClient()->getState() != acre::State::stopped && CEngine::getInstance()->getClient()->getState() != acre::State::stopping) { + if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { CEngine::getInstance()->getClient()->stop(); } CEngine::getInstance()->stop(); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp index 94c81c11e..fd31d1173 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp @@ -15,9 +15,9 @@ bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender const char* dataID) { //LOG("[%s], [%s]", pluginName, pluginCommand); - if (dataLength) { + if (dataLength > 0U) { // this we pass to a custom TS3 IServer to handle the damn messages - if (CEngine::getInstance()->getExternalServer() ) { + if (CEngine::getInstance()->getExternalServer()) { CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *)data, dataLength); return true; } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 6448d7874..a639dbe8f 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -20,34 +20,37 @@ #include "AcreDsp.h" -typedef std::numeric_limits LIMITER; +typedef std::numeric_limits LIMITER; //void ts3plugin_onEditPlaybackVoiceDataEvent(uint64 server, anyID id, short* samples, int sampleCount, int channels) { bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID) { - if (CEngine::getInstance()->getSoundSystemOverride()) + if (CEngine::getInstance()->getSoundSystemOverride()) { return false; - if (!CEngine::getInstance()->getGameServer()) + } + + if (!CEngine::getInstance()->getGameServer()) { return false; - if (!CEngine::getInstance()->getGameServer()->getConnected()) + } + + if (!CEngine::getInstance()->getGameServer()->getConnected()) { return false; + } // Make this faster - short* mixdownSamples; - uint32_t mixdownSampleLength = 0; - + //if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { - mixdownSampleLength = sampleCount * channelCount; - mixdownSamples = new short[mixdownSampleLength]; + const std::uint32_t mixdownSampleLength = sampleCount * channelCount; + int16_t *mixdownSamples = new int16_t[mixdownSampleLength]; //} - for (int c = 0; c <= mixdownSampleLength - 1; ++c) { - mixdownSamples[c] = static_cast(outputPCM[c] / LIMITER::max()); + for (std::int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { + mixdownSamples[c] = static_cast(outputPCM[c] / LIMITER::max()); } CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent(static_cast(userID), mixdownSamples, sampleCount, channelCount); - for (int c = 0; c <= mixdownSampleLength - 1; ++c) { - float mixedSample; + for (std::int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { + float mixedSample = 0.0F; if (mixdownSamples[c] > 0) { mixedSample = static_cast(mixdownSamples[c] * LIMITER::max()); } @@ -65,32 +68,36 @@ bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount) { - if (CEngine::getInstance()->getSoundSystemOverride()) + if (CEngine::getInstance()->getSoundSystemOverride()) { return false; - if (!CEngine::getInstance()->getGameServer()) + } + + if (!CEngine::getInstance()->getGameServer()) { return false; - if (!CEngine::getInstance()->getGameServer()->getConnected()) + } + + if (!CEngine::getInstance()->getGameServer()->getConnected()) { return false; - UINT32 speakerMask = 0; + } + + uint32_t speakerMask = 0U; speakerMask = SPEAKER_STEREO; // Make this faster - short* mixdownSamples; - uint32_t mixdownSampleLength = 0; //if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { - mixdownSampleLength = sampleCount * channelCount; - mixdownSamples = new short[mixdownSampleLength]; + const uint32_t mixdownSampleLength = sampleCount * channelCount; + int16_t *mixdownSamples = new int16_t[mixdownSampleLength]; //} - for (int c = 0; c <= mixdownSampleLength - 1; ++c) { + for (int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { mixdownSamples[c] = static_cast(outputPCM[c] / LIMITER::max()); } CEngine::getInstance()->getSoundEngine()->onEditMixedPlaybackVoiceDataEvent(mixdownSamples, sampleCount, channelCount, speakerMask); - for (int c = 0; c <= mixdownSampleLength - 1; ++c) { - float mixedSample; + for (int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { + float mixedSample = 0.0F; if (mixdownSamples[c] > 0) { mixedSample = static_cast(mixdownSamples[c] * LIMITER::max()); } diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 679cf04d5..b7a44f848 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -43,7 +43,7 @@ acre::Result CMumbleClient::getMuted(acre::id_t id_) { } acre::Result CMumbleClient::stop() { - if (CEngine::getInstance() != NULL) { + if (CEngine::getInstance() != nullptr) { CEngine::getInstance()->stop(); this->setState(acre::State::stopping); if (this->m_versionThreadHandle.joinable()) { @@ -121,7 +121,7 @@ acre::Result CMumbleClient::setClientMetadata(const char *const data) { } ts3Functions.setClientSelfVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_META_DATA, to_set.c_str()); ts3Functions.freeMemory(clientInfo); - ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); + ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), nullptr); return acre::Result::ok; } */ @@ -260,7 +260,7 @@ std::string CMumbleClient::getConfigFilePath(void) { std::string tempFolder = ".\\acre"; if (!PathFileExistsA(tempFolder.c_str())) { - if (!CreateDirectoryA(tempFolder.c_str(), NULL)) { + if (!CreateDirectoryA(tempFolder.c_str(), nullptr)) { LOG("ERROR: UNABLE TO CREATE TEMP DIR"); } } @@ -274,7 +274,7 @@ std::string CMumbleClient::getTempFilePath( void ) { std::string tempFolder = std::string(tempPath); tempFolder += "\\acre"; if (!PathFileExistsA(tempFolder.c_str())) { - if (!CreateDirectoryA(tempFolder.c_str(), NULL)) { + if (!CreateDirectoryA(tempFolder.c_str(), nullptr)) { LOG("ERROR: UNABLE TO CREATE TEMP DIR"); } } diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index 612266828..28b8bebe6 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -52,7 +52,7 @@ acre::Result CMumbleCommandServer::handleMessage(unsigned char* data) { } acre::Result CMumbleCommandServer::handleMessage(unsigned char* data, size_t length) { - CTextMessage* msg; + CTextMessage* msg = nullptr; //TRACE("recv: [%s]", data); msg = new CTextMessage((char*)data, length); if (CEngine::getInstance()->getRpcEngine() && (msg != nullptr)) { @@ -73,10 +73,12 @@ acre::Result CMumbleCommandServer::release(void) { CMumbleCommandServer::CMumbleCommandServer(const acre::id_t id) { this->setId(id); } + CMumbleCommandServer::CMumbleCommandServer(void) { this->setCommandId(0); this->setConnected(true); } + CMumbleCommandServer::~CMumbleCommandServer() { } From c661bc8e8f8bea1fa168f5294b55622bb94becb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Mon, 4 May 2020 22:29:25 +0200 Subject: [PATCH 006/104] Add moving functionality --- extensions/src/ACRE2Core/AcreSettings.cpp | 6 +- extensions/src/ACRE2Core/AcreSettings.h | 2 +- extensions/src/ACRE2Core/setSetting.h | 6 +- extensions/src/ACRE2Mumble/MumbleClient.cpp | 97 ++++++++++++--------- 4 files changed, 61 insertions(+), 50 deletions(-) diff --git a/extensions/src/ACRE2Core/AcreSettings.cpp b/extensions/src/ACRE2Core/AcreSettings.cpp index b6a341188..090770e7f 100644 --- a/extensions/src/ACRE2Core/AcreSettings.cpp +++ b/extensions/src/ACRE2Core/AcreSettings.cpp @@ -15,7 +15,7 @@ acre::Result CAcreSettings::save(std::string filename) { iniFile << "globalVolume = " << this->m_GlobalVolume << ";\n"; iniFile << "premixGlobalVolume = " << this->m_PremixGlobalVolume << ";\n"; iniFile << "disableUnmuteClients = " << (this->m_DisableUnmuteClients ? "true" : "false") << ";\n"; - iniFile << "disableTS3ChannelSwitch = " << (this->m_DisableTS3ChannelSwitch ? "true" : "false") << ";\n"; + iniFile << "disableChannelSwitch = " << (this->m_DisableChannelSwitch ? "true" : "false") << ";\n"; //LOG("Config Save: %f,%f", m_GlobalVolume, m_PremixGlobalVolume); iniFile.flush(); @@ -40,7 +40,7 @@ acre::Result CAcreSettings::load(std::string filename) { this->m_GlobalVolume = (float)config.GetReal("acre2", "globalVolume", 1.0f); this->m_PremixGlobalVolume = (float)config.GetReal("acre2", "premixGlobalVolume", 1.0f); this->m_DisableUnmuteClients = config.GetBoolean("acre2", "disableUnmuteClients", false); - this->m_DisableTS3ChannelSwitch = config.GetBoolean("acre2", "disableTS3ChannelSwitch", false); + this->m_DisableChannelSwitch = config.GetBoolean("acre2", "disableChannelSwitch", false); //LOG("Config Load: %f,%f", m_GlobalVolume, m_PremixGlobalVolume); this->m_Path = filename; @@ -65,7 +65,7 @@ CAcreSettings::CAcreSettings() : m_EnableAudioTest(false), m_DisableRadioFilter(false), m_DisableUnmuteClients(false), - m_DisableTS3ChannelSwitch(false), + m_DisableChannelSwitch(false), m_LastVersion(ACRE_VERSION), m_Path("acre2.ini") { diff --git a/extensions/src/ACRE2Core/AcreSettings.h b/extensions/src/ACRE2Core/AcreSettings.h index 02b4c61fe..6cc84c8b7 100644 --- a/extensions/src/ACRE2Core/AcreSettings.h +++ b/extensions/src/ACRE2Core/AcreSettings.h @@ -27,8 +27,8 @@ class CAcreSettings : DECLARE_MEMBER(bool, DisableMuting); DECLARE_MEMBER(bool, DisableRadioFilter); DECLARE_MEMBER(bool, DisableUnmuteClients); - DECLARE_MEMBER(bool, DisableTS3ChannelSwitch); + DECLARE_MEMBER(bool, DisableChannelSwitch); DECLARE_MEMBER(bool, EnableAudioTest); DECLARE_MEMBER(std::string, Path); diff --git a/extensions/src/ACRE2Core/setSetting.h b/extensions/src/ACRE2Core/setSetting.h index 53e9636ff..237f87479 100644 --- a/extensions/src/ACRE2Core/setSetting.h +++ b/extensions/src/ACRE2Core/setSetting.h @@ -21,9 +21,9 @@ RPC_FUNCTION(setSetting) { if (CAcreSettings::getInstance()->getDisableUnmuteClients() != (value != 1)) { CAcreSettings::getInstance()->setDisableUnmuteClients(value != 1); } - } else if (name == "disableTS3ChannelSwitch") { - if (CAcreSettings::getInstance()->getDisableTS3ChannelSwitch() != (value != 1)) { - CAcreSettings::getInstance()->setDisableTS3ChannelSwitch(value != 1); + } else if (name == "disableChannelSwitch") { + if (CAcreSettings::getInstance()->getDisableChannelSwitch() != (value != 1)) { + CAcreSettings::getInstance()->setDisableChannelSwitch(value != 1); } } else { LOG("Setting [%s] failed to change to [%f]", name.c_str(), value); diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index b7a44f848..51ebefeb7 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -12,16 +12,16 @@ #pragma comment(lib, "Shlwapi.lib") -#define INVALID_TS3_CHANNEL -1 -#define DEFAULT_TS3_CHANNEL "ACRE" +#define INVALID_MUMBLE_CHANNEL -1 +#define DEFAULT_MUMBLE_CHANNEL "ACRE" extern MumbleAPI mumAPI; +extern mumble_connection_t activeConnection; extern plugin_id_t pluginID; - //TS3Functions CMumbleClient::ts3Functions; acre::Result CMumbleClient::initialize(void) { - setPreviousChannel(INVALID_TS3_CHANNEL); + setPreviousChannel(INVALID_MUMBLE_CHANNEL); return acre::Result::ok; } @@ -308,58 +308,68 @@ acre::Result CMumbleClient::unMuteAll( void ) { } acre::Result CMumbleClient::moveToServerChannel() { - /* - if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { - anyID clientId; + + if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { + mumble_userid_t clientId; std::vector details = getChannelDetails(); - if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { - uint64_t currentChannelId = INVALID_TS3_CHANNEL; - if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousChannel() == INVALID_TS3_CHANNEL) { + //if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { + if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == STATUS_OK) { + mumble_channelid_t currentChannelId = INVALID_MUMBLE_CHANNEL; + //if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousChannel() == INVALID_MUMBLE_CHANNEL) { + if ((mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) && (getPreviousChannel() == INVALID_MUMBLE_CHANNEL)) { setPreviousChannel(currentChannelId); } - const uint64_t channelId = findChannelByNames(details); - if ((channelId != INVALID_TS3_CHANNEL) && (channelId != currentChannelId)) { - std::string password = ""; + const mumble_channelid_t channelId = static_cast(findChannelByNames(details)); + if ((channelId != INVALID_MUMBLE_CHANNEL) && (channelId != currentChannelId)) { + std::string password; if (details.at(1) != "" && details.at(0) != "") { password = details.at(1); } - ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr); + + //ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr); + mumAPI.requestUserMove(pluginID, activeConnection, clientId, channelId, password.c_str()); + } } } setShouldSwitchChannel(false); - */ + return acre::Result::ok; } acre::Result CMumbleClient::moveToPreviousChannel() { - /* - if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { - anyID clientId; - if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { - uint64_t currentChannelId = INVALID_TS3_CHANNEL; - if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok) { - const uint64_t channelId = getPreviousChannel(); - if (channelId != INVALID_TS3_CHANNEL && channelId != currentChannelId) { - ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, "", nullptr); + + if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { + mumble_userid_t clientId = -1; + //if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { + if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == STATUS_OK) { + mumble_channelid_t currentChannelId = INVALID_MUMBLE_CHANNEL; + //if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok) { + if (mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) { + const mumble_channelid_t channelId = static_cast(getPreviousChannel()); + if (channelId != INVALID_MUMBLE_CHANNEL && channelId != currentChannelId) { + //ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, "", nullptr); + mumAPI.requestUserMove(pluginID, activeConnection, clientId, channelId, ""); } } } - setPreviousChannel(INVALID_TS3_CHANNEL); + setPreviousChannel(INVALID_MUMBLE_CHANNEL); } - */ + return acre::Result::ok; } uint64_t CMumbleClient::findChannelByNames(std::vector details_) { - /* - uint64_t *channelList; - if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { - uint64_t channelId = INVALID_TS3_CHANNEL; - uint64_t defaultChannelId = INVALID_TS3_CHANNEL; - std::map channelMap; + + mumble_channelid_t*channelList; + std::size_t channelCount = 0U; + //if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { + if (mumAPI.getAllChannels(pluginID, activeConnection, &channelList, &channelCount) == STATUS_OK) { + mumble_channelid_t channelId = INVALID_MUMBLE_CHANNEL; + mumble_channelid_t defaultChannelId = INVALID_MUMBLE_CHANNEL; + std::map channelMap; std::string name = details_.at(2); if (details_.at(0) != "") { name = details_.at(0); @@ -367,11 +377,12 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { while (*channelList) { channelId = *channelList; channelList++; - char* channelName; - if (ts3Functions.getChannelVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { - std::string channelNameString = std::string(channelName); - if (channelNameString.find(DEFAULT_TS3_CHANNEL) != -1 || (details_.at(0) != "" && channelNameString == name)) { - if (channelNameString == DEFAULT_TS3_CHANNEL) { + char* channelName = nullptr; + //if (ts3Functions.getChannelVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { + if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == STATUS_OK) { + std::string channelNameString(channelName); + if (channelNameString.find(DEFAULT_MUMBLE_CHANNEL) != -1 || (!details_.at(0).empty() && channelNameString == name)) { + if (channelNameString == DEFAULT_MUMBLE_CHANNEL) { defaultChannelId = channelId; } channelMap.emplace(channelId, channelNameString); @@ -379,7 +390,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { } } - uint64_t bestChannelId = INVALID_TS3_CHANNEL; + mumble_channelid_t bestChannelId = INVALID_MUMBLE_CHANNEL; int32_t bestMatches = 0; int32_t bestDistance = 10; for (auto& element : channelMap) { @@ -389,7 +400,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { bestChannelId = element.first; break; } - const std::string cleanChannelName = removeSubstrings(fullChannelName, DEFAULT_TS3_CHANNEL); + const std::string cleanChannelName = removeSubstrings(fullChannelName, DEFAULT_MUMBLE_CHANNEL); // Word comparison const int32_t matches = getWordMatches(cleanChannelName, name); if (matches > bestMatches) { @@ -404,17 +415,17 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { bestChannelId = element.first; } } - if (bestChannelId == INVALID_TS3_CHANNEL) { - if (details_.at(0) != "") { + if (bestChannelId == INVALID_MUMBLE_CHANNEL) { + if (!details_.at(0).empty()) { details_.at(0) = ""; bestChannelId = findChannelByNames(details_); - } else if (defaultChannelId != INVALID_TS3_CHANNEL) { + } else if (defaultChannelId != INVALID_MUMBLE_CHANNEL) { bestChannelId = defaultChannelId; } } return bestChannelId; } - */ + return 0; } From 95dec23fada5e7271cd2ed7f3a34b7ce7661b727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Mon, 4 May 2020 22:30:53 +0200 Subject: [PATCH 007/104] Fix warning --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 51ebefeb7..16912b979 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -418,7 +418,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { if (bestChannelId == INVALID_MUMBLE_CHANNEL) { if (!details_.at(0).empty()) { details_.at(0) = ""; - bestChannelId = findChannelByNames(details_); + bestChannelId = static_cast(findChannelByNames(details_)); } else if (defaultChannelId != INVALID_MUMBLE_CHANNEL) { bestChannelId = defaultChannelId; } From e88ed24ef15136d83c68010e7d781bfc5606777a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Mon, 4 May 2020 22:33:56 +0200 Subject: [PATCH 008/104] Free memory --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 16912b979..8a145cf27 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -390,6 +390,8 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { } } + mumAPI.freeMemory(pluginID, channelList); + mumble_channelid_t bestChannelId = INVALID_MUMBLE_CHANNEL; int32_t bestMatches = 0; int32_t bestDistance = 10; From f900e6893a3038370b83f6828f0f96f88499a78c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Mon, 4 May 2020 22:51:23 +0200 Subject: [PATCH 009/104] Channel events. muting is not supported --- .../MumbleCallbacks_channelEvents.cpp | 73 +++++++++++-------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp index 5e3d22e25..be8736e8e 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp @@ -7,76 +7,87 @@ #include "Engine.h" #include "Types.h" #include "AcreSettings.h" -/* -extern TS3Functions ts3Functions; +#include "MumbleFunctions.h" +extern MumbleAPI mumAPI; +extern mumble_connection_t activeConnection; +extern plugin_id_t pluginID; +//extern TS3Functions ts3Functions; +/* // // Handle move events for silencing // -void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage) { - +//void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage) { +void mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, mumble_channelid_t newChannelID) { // Only unmute if teamspeak is not linked to ARMA. if (!CAcreSettings::getInstance()->getDisableUnmuteClients() && !(CEngine::getInstance()->getGameServer()->getConnected())) { // Get local client ID - anyID myID; + mumble_userid_t myID; - if (ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) { + //if (ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) { + if (mumAPI.getLocalUserID(pluginID, activeConnection, &myID) != STATUS_OK) { return; // Exit if we don't } //Unmute all clients if local user moves. - if (clientID == myID) { - - anyID* clientsInChannel; - if (ts3Functions.getChannelClientList(serverConnectionHandlerID, newChannelID, &clientsInChannel) == ERROR_ok) { - //Unmute clients in the current channel - ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientsInChannel, NULL); + if (userID == myID) { + mumble_userid_t* clientsInChannel; + std::size_t userCount = 0U; + //if (ts3Functions.getChannelClientList(serverConnectionHandlerID, newChannelID, &clientsInChannel) == ERROR_ok) { + if (mumAPI.getUsersInChannel(pluginID, activeConnection, newChannelID, &clientsInChannel, &userCount) { + // Unmute clients in the current channel. Not Supported in mumble. + // ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientsInChannel, NULL); } - ts3Functions.freeMemory(clientsInChannel); + mumAPI.freeMemory(pluginID, clientsInChannel); } else { //Only unmute joining user when not current client. - anyID clientIDArray[2]; // List of clients to unmute. - clientIDArray[0] = clientID; // Client ID to unmute + mumble_userid_t clientIDArray[2]; // List of clients to unmute. + clientIDArray[0] = userID; // Client ID to unmute clientIDArray[1] = 0; // Mark end of array with a 0 value. - ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientIDArray, NULL); + //ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientIDArray, NULL); } } } -void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID moverID, const char* moverName, const char* moverUniqueIdentifier, const char* moveMessage) { +//void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID moverID, const char* moverName, const char* moverUniqueIdentifier, const char* moveMessage) { +void mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, mumble_channelid_t newChannelID) { // Only unmute if teamspeak is not linked to ARMA. if (!CAcreSettings::getInstance()->getDisableUnmuteClients() && !(CEngine::getInstance()->getGameServer()->getConnected())) { // Get local client ID - anyID myID; + mumble_userid_t myID; - if (ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) { + //if (ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) { + if(mumAPI.getLocalUserID(pluginID, activeConnection, &myID) != STATUS_OK) { return; // Exit if we don't } //Unmute all clients if local user moves. - if (clientID == myID) { - - anyID* clientsInChannel; - if (ts3Functions.getChannelClientList(serverConnectionHandlerID, newChannelID, &clientsInChannel) == ERROR_ok) { - //Unmute clients in the current channel + if (userID == myID) { + mumble_userid_t* clientsInChannel; + std::size_t userCount = 0U; + // if (ts3Functions.getChannelClientList(serverConnectionHandlerID, newChannelID, &clientsInChannel) == ERROR_ok) { + if (mumAPI.getUsersInChannel(pluginID, activeConnection, newChannelID, &clientsInChannel, &userCount) { + // Unmute clients in the current channel. Not Supported in mumble. ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientsInChannel, NULL); } ts3Functions.freeMemory(clientsInChannel); - } - else { + } else { //Only unmute joining user when not current client. - anyID clientIDArray[2]; // List of clients to unmute. - clientIDArray[0] = clientID; // Client ID to unmute + mumble_userid_t clientIDArray[2]; // List of clients to unmute. + clientIDArray[0] = userID; // Client ID to unmute clientIDArray[1] = 0; // Mark end of array with a 0 value. - ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientIDArray, NULL); + //ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientIDArray, NULL); } } } +*/ -void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) { +// void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) { +void mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID) { + (void)connection; + (void)channelID; CEngine::getInstance()->getClient()->updateShouldSwitchChannel(true); } -*/ From 322a7aa95973d44ff8bf37878ca70011ff4d7847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Mon, 4 May 2020 23:12:46 +0200 Subject: [PATCH 010/104] Fix TS3 build --- .../src/ACRE2DistortionTestPlugin/CommandServer.h | 6 ++++++ extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp | 10 +++++----- .../ACRE2DistortionTestPlugin/TsCallbacks_speaking.cpp | 2 +- extensions/src/ACRE2TS/CommandServer.h | 8 +++++++- extensions/src/ACRE2TS/TS3Client.cpp | 10 +++++----- extensions/src/ACRE2TS/TsCallbacks_speaking.cpp | 2 +- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/extensions/src/ACRE2DistortionTestPlugin/CommandServer.h b/extensions/src/ACRE2DistortionTestPlugin/CommandServer.h index 81fc76e67..31648b6c3 100644 --- a/extensions/src/ACRE2DistortionTestPlugin/CommandServer.h +++ b/extensions/src/ACRE2DistortionTestPlugin/CommandServer.h @@ -20,6 +20,12 @@ class CCommandServer : public IServer, public CLockable { acre::Result sendMessage(IMessage *msg); acre::Result handleMessage(unsigned char *msg); + acre::Result handleMessage(unsigned char* msg, size_t length) override { + (void)msg; + (void)length; + + return acre::Result::notImplemented; + } acre::Result release(void); diff --git a/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp b/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp index 0cacb7587..3d9c38d15 100644 --- a/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp +++ b/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp @@ -151,7 +151,7 @@ acre::Result CTS3Client::localStartSpeaking(const acre::Speaking speakingType_, } else { stopDirectSpeaking = true; } - } else if (this->getVAD() && (this->getTsSpeakingState() == STATUS_TALKING)) { + } else if (this->getVAD() && (this->getSpeakingState() == STATUS_TALKING)) { stopDirectSpeaking = true; } } @@ -196,7 +196,7 @@ acre::Result CTS3Client::localStopSpeaking(const acre::Speaking speakingType_) { } } else { this->setOnRadio(false); - if (this->getTsSpeakingState() == STATUS_TALKING) { + if (this->getSpeakingState() == STATUS_TALKING) { resendDirectSpeaking = true; } } @@ -207,7 +207,7 @@ acre::Result CTS3Client::localStopSpeaking(const acre::Speaking speakingType_) { } else { resendDirectSpeaking = true; } - } else if (this->getTsSpeakingState() == STATUS_TALKING) { + } else if (this->getSpeakingState() == STATUS_TALKING) { resendDirectSpeaking = true; } } @@ -450,7 +450,7 @@ acre::Result CTS3Client::unMuteAll( void ) { } acre::Result CTS3Client::moveToServerChannel() { - if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { + if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { anyID clientId; std::vector details = getChannelDetails(); @@ -475,7 +475,7 @@ acre::Result CTS3Client::moveToServerChannel() { } acre::Result CTS3Client::moveToPreviousChannel() { - if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { + if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { anyID clientId; if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; diff --git a/extensions/src/ACRE2DistortionTestPlugin/TsCallbacks_speaking.cpp b/extensions/src/ACRE2DistortionTestPlugin/TsCallbacks_speaking.cpp index 66e324193..f76f69ad3 100644 --- a/extensions/src/ACRE2DistortionTestPlugin/TsCallbacks_speaking.cpp +++ b/extensions/src/ACRE2DistortionTestPlugin/TsCallbacks_speaking.cpp @@ -32,7 +32,7 @@ void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int sta return; } - ((CTS3Client *) (CEngine::getInstance()->getClient()))->setTsSpeakingState(status); + ((CTS3Client *) (CEngine::getInstance()->getClient()))->setSpeakingState(status); if (CEngine::getInstance()->getSoundSystemOverride()) { return; } else if (((CTS3Client *) (CEngine::getInstance()->getClient()))->getOnRadio()) { diff --git a/extensions/src/ACRE2TS/CommandServer.h b/extensions/src/ACRE2TS/CommandServer.h index a927a873a..234e8fced 100644 --- a/extensions/src/ACRE2TS/CommandServer.h +++ b/extensions/src/ACRE2TS/CommandServer.h @@ -21,6 +21,12 @@ class CCommandServer : public IServer, public CLockable acre::Result sendMessage(IMessage *msg); acre::Result handleMessage(unsigned char *msg); + acre::Result handleMessage(unsigned char* msg, size_t length) override { + (void)msg; + (void)length; + + return acre::Result::notImplemented; + } acre::Result release(void); @@ -31,7 +37,7 @@ class CCommandServer : public IServer, public CLockable inline bool getConnected() const final { return m_connected; } inline void setId(const acre::id_t value) final { m_id = value; } - inline acre::id_t getId() const final { return m_id; } + inline acre::id_t getId() const final { return m_id; } protected: acre::id_t m_id; diff --git a/extensions/src/ACRE2TS/TS3Client.cpp b/extensions/src/ACRE2TS/TS3Client.cpp index 853c0a311..a54820ba5 100644 --- a/extensions/src/ACRE2TS/TS3Client.cpp +++ b/extensions/src/ACRE2TS/TS3Client.cpp @@ -171,7 +171,7 @@ acre::Result CTS3Client::localStartSpeaking(const acre::Speaking speakingType_, } else { stopDirectSpeaking = true; } - } else if (this->getVAD() && (this->getTsSpeakingState() == STATUS_TALKING)) { + } else if (this->getVAD() && (this->getSpeakingState() == STATUS_TALKING)) { stopDirectSpeaking = true; } } @@ -223,7 +223,7 @@ acre::Result CTS3Client::localStopSpeaking(const acre::Speaking speakingType_) { } } else { this->setOnRadio(false); - if (this->getTsSpeakingState() == STATUS_TALKING) { + if (this->getSpeakingState() == STATUS_TALKING) { resendDirectSpeaking = true; } } @@ -234,7 +234,7 @@ acre::Result CTS3Client::localStopSpeaking(const acre::Speaking speakingType_) { } else { resendDirectSpeaking = true; } - } else if (this->getTsSpeakingState() == STATUS_TALKING) { + } else if (this->getSpeakingState() == STATUS_TALKING) { resendDirectSpeaking = true; } } @@ -477,7 +477,7 @@ acre::Result CTS3Client::unMuteAll( void ) { } acre::Result CTS3Client::moveToServerChannel() { - if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { + if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { anyID clientId; std::vector details = getChannelDetails(); @@ -502,7 +502,7 @@ acre::Result CTS3Client::moveToServerChannel() { } acre::Result CTS3Client::moveToPreviousChannel() { - if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) { + if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { anyID clientId; if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; diff --git a/extensions/src/ACRE2TS/TsCallbacks_speaking.cpp b/extensions/src/ACRE2TS/TsCallbacks_speaking.cpp index 53542dfcc..7c13d61a7 100644 --- a/extensions/src/ACRE2TS/TsCallbacks_speaking.cpp +++ b/extensions/src/ACRE2TS/TsCallbacks_speaking.cpp @@ -32,7 +32,7 @@ void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int sta return; } - ((CTS3Client *) (CEngine::getInstance()->getClient()))->setTsSpeakingState(status); + ((CTS3Client *) (CEngine::getInstance()->getClient()))->setSpeakingState(status); if (CEngine::getInstance()->getSoundSystemOverride()) { return; } else if (((CTS3Client *) (CEngine::getInstance()->getClient()))->getOnRadio()) { From a7efc3017c3ce0b5833fbdd84503ef976eb32377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Tue, 5 May 2020 21:35:28 +0200 Subject: [PATCH 011/104] Code pass --- .../MumbleCallbacks_channelEvents.cpp | 2 +- .../MumbleCallbacks_pluginEvents.cpp | 9 ++-- .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 43 +++++++++++-------- extensions/src/ACRE2Mumble/MumbleClient.cpp | 36 ++++++---------- .../src/ACRE2Mumble/MumbleCommandServer.cpp | 10 ++--- .../src/ACRE2Mumble/MumbleCommandServer.h | 20 ++++----- extensions/src/ACRE2Shared/IServer.h | 2 +- 7 files changed, 57 insertions(+), 65 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp index be8736e8e..c505fa5ce 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp @@ -39,7 +39,7 @@ void mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t use // Unmute clients in the current channel. Not Supported in mumble. // ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientsInChannel, NULL); } - mumAPI.freeMemory(pluginID, clientsInChannel); + mumAPI.freeMemory(pluginID, (void *) &clientsInChannel); } else { //Only unmute joining user when not current client. mumble_userid_t clientIDArray[2]; // List of clients to unmute. diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp index fd31d1173..e1048741d 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp @@ -15,12 +15,9 @@ bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender const char* dataID) { //LOG("[%s], [%s]", pluginName, pluginCommand); - if (dataLength > 0U) { - // this we pass to a custom TS3 IServer to handle the damn messages - if (CEngine::getInstance()->getExternalServer()) { - CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *)data, dataLength); - return true; - } + if ((dataLength > 0U) && CEngine::getInstance()->getExternalServer()) { + CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *)data, dataLength); + return true; } return false; } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index e1ca69abb..1ff1c7ce2 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -17,44 +17,53 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use if (static_cast(userID) != CEngine::getInstance()->getSelf()->getId()) { return; - } else if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { + } + + if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { return; - } else if (!CEngine::getInstance()->getGameServer()) { + } + + if (!CEngine::getInstance()->getGameServer()) { return; - } else if (CEngine::getInstance()->getState() != acre::State::running) { + } + + if (CEngine::getInstance()->getState() != acre::State::running) { return; - } else if (!CEngine::getInstance()->getGameServer()->getConnected()) { + } + + if (!CEngine::getInstance()->getGameServer()->getConnected()) { return; } CEngine::getInstance()->getClient()->setSpeakingState(status); if (CEngine::getInstance()->getSoundSystemOverride()) { return; - } else if (CEngine::getInstance()->getClient()->getOnRadio()) { + } + + if (CEngine::getInstance()->getClient()->getOnRadio()) { if (CEngine::getInstance()->getClient()->getVAD()) { return; - } else { - if (status != TalkingState::PASSIVE && status != TalkingState::INVALID) { - if (!CEngine::getInstance()->getClient()->getRadioPTTDown()) { - CEngine::getInstance()->getClient()->setOnRadio(false); + } + + if (status != TalkingState::PASSIVE && status != TalkingState::INVALID) { + if (!CEngine::getInstance()->getClient()->getRadioPTTDown()) { + CEngine::getInstance()->getClient()->setOnRadio(false); + } else { + if (!CEngine::getInstance()->getClient()->getDirectFirst()) { + CEngine::getInstance()->getClient()->microphoneOpen(true); } else { - if (!CEngine::getInstance()->getClient()->getDirectFirst()) { + CEngine::getInstance()->getClient()->setDirectFirst(false); + if (CEngine::getInstance()->getClient()->getRadioPTTDown()) { CEngine::getInstance()->getClient()->microphoneOpen(true); - } else { - CEngine::getInstance()->getClient()->setDirectFirst(false); - if (CEngine::getInstance()->getClient()->getRadioPTTDown()) { - CEngine::getInstance()->getClient()->microphoneOpen(true); - } } } } - return; } return; } TRACE("enter: [%d],[%d]", clientID, status); - if (status != TalkingState::PASSIVE && status != TalkingState::INVALID) { + if ((status != TalkingState::PASSIVE) && (status != TalkingState::INVALID)) { CEngine::getInstance()->getClient()->setDirectFirst(true); CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::direct); } else { diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 8a145cf27..56aac700b 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -128,14 +128,12 @@ acre::Result CMumbleClient::setClientMetadata(const char *const data) { bool CMumbleClient::getVAD() { transmission_mode_t transmitMode; - mumble_error_t err = mumAPI.getLocalUserTransmissionMode(pluginID, &transmitMode); + const mumble_error_t err = mumAPI.getLocalUserTransmissionMode(pluginID, &transmitMode); if (err != ErrorCode::EC_OK) { return false; } - if (transmitMode == TransmissionMode::TM_VOICE_ACTIVATION) { - return true; - } - return false; + + return transmitMode == TransmissionMode::TM_VOICE_ACTIVATION; } acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType_) { @@ -242,7 +240,7 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ } acre::Result CMumbleClient::enableMicrophone(const bool status_) { - + (void)status_; return acre::Result::ok; } @@ -256,13 +254,9 @@ std::string CMumbleClient::getUniqueId( ) { } std::string CMumbleClient::getConfigFilePath(void) { - char tempPath[MAX_PATH - 14]; - std::string tempFolder = ".\\acre"; - if (!PathFileExistsA(tempFolder.c_str())) { - if (!CreateDirectoryA(tempFolder.c_str(), nullptr)) { - LOG("ERROR: UNABLE TO CREATE TEMP DIR"); - } + if (!PathFileExistsA(tempFolder.c_str()) && !CreateDirectoryA(tempFolder.c_str(), nullptr)) { + LOG("ERROR: UNABLE TO CREATE TEMP DIR"); } return tempFolder; @@ -272,27 +266,24 @@ std::string CMumbleClient::getTempFilePath( void ) { char tempPath[MAX_PATH - 14]; GetTempPathA(sizeof(tempPath), tempPath); std::string tempFolder = std::string(tempPath); - tempFolder += "\\acre"; - if (!PathFileExistsA(tempFolder.c_str())) { - if (!CreateDirectoryA(tempFolder.c_str(), nullptr)) { - LOG("ERROR: UNABLE TO CREATE TEMP DIR"); - } + tempFolder.append("\\acre"); + if (!PathFileExistsA(tempFolder.c_str()) && !CreateDirectoryA(tempFolder.c_str(), nullptr)) { + LOG("ERROR: UNABLE TO CREATE TEMP DIR"); } return tempFolder; } acre::Result CMumbleClient::microphoneOpen(bool status_) { - mumble_error_t res; if (status_) { - res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, true); + const mumble_error_t res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, true); if (res != ErrorCode::EC_OK) { LOG("Error toggling PTT Open\n"); return acre::Result::error; } this->setInputActive(true); } else { - res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, false); + const mumble_error_t res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, false); if (res != ErrorCode::EC_OK) { LOG("Error toggling PTT Closed\n"); return acre::Result::error; @@ -303,7 +294,6 @@ acre::Result CMumbleClient::microphoneOpen(bool status_) { } acre::Result CMumbleClient::unMuteAll( void ) { - return acre::Result::ok; } @@ -363,7 +353,7 @@ acre::Result CMumbleClient::moveToPreviousChannel() { uint64_t CMumbleClient::findChannelByNames(std::vector details_) { - mumble_channelid_t*channelList; + mumble_channelid_t*channelList = nullptr; std::size_t channelCount = 0U; //if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { if (mumAPI.getAllChannels(pluginID, activeConnection, &channelList, &channelCount) == STATUS_OK) { @@ -390,7 +380,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { } } - mumAPI.freeMemory(pluginID, channelList); + mumAPI.freeMemory(pluginID, (void *) &channelList); mumble_channelid_t bestChannelId = INVALID_MUMBLE_CHANNEL; int32_t bestMatches = 0; diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index 28b8bebe6..6935fdc2f 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -32,8 +32,8 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ (const char*)msg->getData(), PluginCommandTarget_CURRENT_CHANNEL, NULL, NULL); */ - mumble_userid_t* channelUsers; - size_t userCount; + mumble_userid_t* channelUsers = nullptr; + size_t userCount = 0U; mumble_channelid_t currentChannel; mumAPI.getChannelOfUser(pluginID, activeConnection, CEngine::getInstance()->getSelf()->getId(), ¤tChannel); mumAPI.getUsersInChannel(pluginID, activeConnection, currentChannel, &channelUsers, &userCount); @@ -54,7 +54,7 @@ acre::Result CMumbleCommandServer::handleMessage(unsigned char* data) { acre::Result CMumbleCommandServer::handleMessage(unsigned char* data, size_t length) { CTextMessage* msg = nullptr; //TRACE("recv: [%s]", data); - msg = new CTextMessage((char*)data, length); + msg = new (std::nothrow) CTextMessage((char*)data, length); if (CEngine::getInstance()->getRpcEngine() && (msg != nullptr)) { CEngine::getInstance()->getRpcEngine()->runProcedure((IServer*)this, (IMessage*)msg); } @@ -78,7 +78,3 @@ CMumbleCommandServer::CMumbleCommandServer(void) { this->setCommandId(0); this->setConnected(true); } - -CMumbleCommandServer::~CMumbleCommandServer() { - -} diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.h b/extensions/src/ACRE2Mumble/MumbleCommandServer.h index 99d67ca05..ec7b02d71 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.h +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.h @@ -16,20 +16,20 @@ class CMumbleCommandServer : public IServer, public CLockable public: CMumbleCommandServer(void); CMumbleCommandServer(const acre::id_t id); - ~CMumbleCommandServer(void); + ~CMumbleCommandServer(void) final = default; - acre::Result initialize(void); - acre::Result shutdown(void); + acre::Result initialize(void) final; + acre::Result shutdown(void) final; - acre::Result sendMessage(IMessage *msg); - acre::Result handleMessage(unsigned char* msg); - acre::Result handleMessage(unsigned char* msg, size_t length); + acre::Result sendMessage(IMessage *msg) final; + acre::Result handleMessage(unsigned char* msg) final; + acre::Result handleMessage(unsigned char* msg, size_t length) final; - acre::Result release(void); + acre::Result release(void) final; - inline void setCommandId(plugin_id_t value) { m_commandId = value; } - inline plugin_id_t getCommandId() const { return m_commandId; } + inline void setCommandId(plugin_id_t value) noexcept { m_commandId = value; } + inline plugin_id_t getCommandId() const noexcept { return m_commandId; } inline void setConnected(const bool value) final { m_connected = value; } inline bool getConnected() const final { return m_connected; } @@ -37,7 +37,7 @@ class CMumbleCommandServer : public IServer, public CLockable inline void setId(const acre::id_t value) final { m_id = value; } inline acre::id_t getId() const final { return m_id; } -protected: +private: acre::id_t m_id; bool m_connected; plugin_id_t m_commandId; diff --git a/extensions/src/ACRE2Shared/IServer.h b/extensions/src/ACRE2Shared/IServer.h index 31f75b39d..71aba4bde 100644 --- a/extensions/src/ACRE2Shared/IServer.h +++ b/extensions/src/ACRE2Shared/IServer.h @@ -9,7 +9,7 @@ class IServer { public: - virtual ~IServer(){} + virtual ~IServer() = default; virtual acre::Result initialize(void) = 0; virtual acre::Result shutdown(void) = 0; From a7fabb40153eae1884a0f1da2109bdad9b0eb164 Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Sun, 10 May 2020 16:57:39 -0700 Subject: [PATCH 012/104] Mumble test plugin. --- extensions/CMakeLists.txt | 2 + extensions/src/MumbleTest/CMakeLists.txt | 14 + extensions/src/MumbleTest/MumbleAPI.h | 237 ++++++++++++ extensions/src/MumbleTest/MumblePlugin.h | 354 +++++++++++++++++ extensions/src/MumbleTest/PluginComponents.h | 313 +++++++++++++++ .../src/MumbleTest/testPlugin/testPlugin.cpp | 364 ++++++++++++++++++ .../src/MumbleTest/testPlugin/testPlugin.pro | 9 + 7 files changed, 1293 insertions(+) create mode 100644 extensions/src/MumbleTest/CMakeLists.txt create mode 100644 extensions/src/MumbleTest/MumbleAPI.h create mode 100644 extensions/src/MumbleTest/MumblePlugin.h create mode 100644 extensions/src/MumbleTest/PluginComponents.h create mode 100644 extensions/src/MumbleTest/testPlugin/testPlugin.cpp create mode 100644 extensions/src/MumbleTest/testPlugin/testPlugin.pro diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index deb3e89d5..18385e677 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -74,3 +74,5 @@ add_subdirectory(src/ACRE2Mumble) #Extras add_subdirectory(src/Wav2B64) add_subdirectory(src/ACRE2DistortionTestPlugin) +add_subdirectory(src/MumbleTest) + diff --git a/extensions/src/MumbleTest/CMakeLists.txt b/extensions/src/MumbleTest/CMakeLists.txt new file mode 100644 index 000000000..da29f28cc --- /dev/null +++ b/extensions/src/MumbleTest/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required (VERSION 3.0) + +set(ACRE_NAME "MumbleTest") + +acre_set_build_output() +acre_set_linker_options() + +enable_language(ASM_MASM) +file(GLOB_RECURSE SOURCES *.h *.hpp *.c *.cpp *.asm testPlugin/*) + +include_directories(testPlugin) + +add_library( ${ACRE_NAME} MODULE ${SOURCES} ${GLOBAL_SOURCES}) +set_target_properties(${ACRE_NAME} PROPERTIES FOLDER Extras LINK_FLAGS -SAFESEH:NO) diff --git a/extensions/src/MumbleTest/MumbleAPI.h b/extensions/src/MumbleTest/MumbleAPI.h new file mode 100644 index 000000000..1ef62eaa6 --- /dev/null +++ b/extensions/src/MumbleTest/MumbleAPI.h @@ -0,0 +1,237 @@ +// Copyright 2019-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file contains the definition of Mumble's API + +#ifndef MUMBLE_PLUGIN_API_H_ +#define MUMBLE_PLUGIN_API_H_ + +#include "PluginComponents.h" +#include + +// API version +const int32_t MUMBLE_PLUGIN_API_MAJOR = 1; +const int32_t MUMBLE_PLUGIN_API_MINOR = 0; +const int32_t MUMBLE_PLUGIN_API_PATCH = 0; +const version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PLUGIN_API_MINOR, MUMBLE_PLUGIN_API_PATCH }; + + +struct MumbleAPI { + // -------- Memory management -------- + + /// Frees the given pointer. + /// + /// @param callerID The ID of the plugin calling this function + /// @param pointer The pointer to free + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *freeMemory)(plugin_id_t callerID, void *pointer); + + + + // -------- Getter functions -------- + + /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] connection A pointer to the memory location the ID should be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the + /// value of the provided pointer + mumble_error_t (PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t *connection); + + /// Fills in the information about the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID); + + /// Fills in the information about the given user's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The user's ID whose name should be obtained + /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getUserName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, char **userName); + + /// Fills in the information about the given channel's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The channel's ID whose name should be obtained + /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, char **channelName); + + /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter + /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the + /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users, + size_t *userCount); + + /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent + /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the + /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t **channels, size_t *channelCount); + + /// Gets the ID of the channel the given user is currently connected to. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the ID of the channel shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t *channel); + + /// Gets an array of all users in the specified channel. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The ID of the channel whose users shall be retrieved + /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has + /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function + /// returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, mumble_userid_t **userList, size_t *userCount); + + /// Gets the current transmission mode of the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t *transmissionMode); + + + + // -------- Request functions -------- + + /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set + /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of + /// restoring the previous state afterwards. + /// + /// @param callerID The ID of the plugin calling this function + /// @param transmissionMode The requested transmission mode + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); + + /// Requests Mumble to move the given user into the given channel + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param channelID The ID of the channel to move the user to + /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a + /// password for entering + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t channelID, const char *password); + + /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen + /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again + /// once it is no longer required + /// + /// @param callerID The ID of the plugin calling this function + /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); + + + + // -------- Find functions -------- + + /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userName The respective user's name + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t (PLUGIN_CALLING_CONVENTION *findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char *userName, + mumble_userid_t *userID); + + /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelName The respective channel's name + /// @param[out] channelID A pointer to the memory the channel's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t (PLUGIN_CALLING_CONVENTION *findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, + const char *channelName, mumble_channelid_t *channelID); + + + + // -------- Miscellaneous -------- + + /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active + /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data + /// must not contain sensitive information or anything else that shouldn't be known by others. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to send the data through (the server the given users are on) + /// @param users An array of user IDs to send the data to + /// @param userCount The size of the provided user-array + /// @param data The data that shall be sent as a String + /// @param dataLength The length of the data-string + /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with + /// the data + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *users, + size_t userCount, const char *data, size_t dataLength, const char *dataID); + + /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. + /// + /// @param callerID The ID of the plugin calling this function + /// @param message The message to log + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *log)(plugin_id_t callerID, const char *message); + + /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it + /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). + /// + /// @param callerID The ID of the plugin calling this function + /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *playSample)(plugin_id_t callerID, const char *samplePath); +}; + +#endif diff --git a/extensions/src/MumbleTest/MumblePlugin.h b/extensions/src/MumbleTest/MumblePlugin.h new file mode 100644 index 000000000..c6c82393d --- /dev/null +++ b/extensions/src/MumbleTest/MumblePlugin.h @@ -0,0 +1,354 @@ +// Copyright 2019-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file specifies the Mumble plugin interface + +#ifndef EXTERNAL_MUMBLE_PLUGIN_H_ +#define EXTERNAL_MUMBLE_PLUGIN_H_ + +#include "PluginComponents.h" +#include "MumbleAPI.h" +#include +#include +#include + +#if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems + #define PLUGIN_EXPORT __attribute__((visibility("default"))) +#elif defined(_MSC_VER) + #define PLUGIN_EXPORT __declspec(dllexport) +#elif defined(__MINGW32__) + #define PLUGIN_EXPORT __attribute__((dllexport)) +#else + #error No PLUGIN_EXPORT definition available +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Gets called right after loading the plugin in order to let the plugin initialize. + /// + /// @param connection The ID of the server-connection this event is connected to, or its default value. + /// @returns The status of the initialization. If everything went fine, return STATUS_OK + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_connection_t connection); + + /// Gets called when unloading the plugin in order to allow it to clean up after itself. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); + + /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied + /// for further usage though. + /// + /// @returns A pointer to the plugin name (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); + + /// Gets the Version of the plugin-API this plugin intends to use. + /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. + /// + /// @return The respective API Version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); + + /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used + /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use + /// of it at some point. + /// + /// @param api The MumbleAPI struct + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); + + + + ////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Tells the plugin some basic information about the Mumble client loading it. + /// This function will be the first one that is being called on this plugin - even before it is decided whether to load + /// the plugin at all. + /// + /// @param mumbleVersion The Version of the Mumble client + /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with + /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); + + /// Gets the Version of this plugin + /// + /// @returns The plugin's version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); + + /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the author(s) name(s) (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); + + /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the description (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); + + /// Registers the ID of this plugin. This is the ID Mumble will reference this plugin with and by which this plugin + /// can identify itself when communicating with Mumble. + /// + /// @param id The ID for this plugin + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerPluginID(uint32_t id); + + /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum + /// together. + /// + /// @returns The feature set of this plugin + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); + + /// Requests this plugin to deactivate the given (sub)set of provided features. + /// If this is not possible, the features that can't be deactivated shall be returned by this function. + /// + /// Example (check if FEATURE_POSITIONAL shall be deactivated): + /// @code + /// if (features & FEATURE_POSITIONAL) { + /// // positional shall be deactivated + /// }; + /// @endcode + /// + /// @param features The feature set that shall be deactivated + /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return + /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); + + + + ////////////////////////////////////////////////////////////////////////////////// + //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // If this plugin wants to provide positional audio, all functions of this category + // have to be implemented + + /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently + /// able to do so and allocate memory that is needed for that process. + /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i + /// belongs to a program whose name is listed at index i in the "name-array". + /// + /// @param programNames An array of pointers to the program names + /// @param programPIDs An array of the corresponding program PIDs + /// @param programCount The length of programNames and programPIDs + /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently + /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) + /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be + /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. + PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); + + /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. + /// + /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it + /// is facing). + /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One + /// unit represents one meter of distance. + /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it + /// is facing). + /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit + /// represents one meter of distance. + /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data + /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical + /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function + /// or until shutdownPositionalData is called. + /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can + /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid + /// until the next invokation of this function or until shutdownPositionalData is called. + /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will + /// be called. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, + float *cameraAxis, const char **context, const char **identity); + + /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should + /// be freed at this point. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Called when connecting to a server. + /// + /// @param connection The ID of the newly established server-connection + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); + + /// Called when disconnecting from a server. + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); + + /// Called when the client has finished synchronizing with the server + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); + + /// Called whenever any user on the server enters a channel + /// This function will also be called when freshly connecting to a server as each user on that + /// server needs to be "added" to the respective channel as far as the local client is concerned. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user this event has been triggered for + /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user + /// freshly connected to the server) or the channel isn't available because of any other reason. + /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means + /// that the ID is invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, + mumble_channelid_t newChannelID); + + /// Called whenever a user leaves a channel. + /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user that left the channel + /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is + /// invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); + + /// Called when any user changes his/her talking state. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user whose talking state has been changed + /// @param talkingState The new TalkingState the user has switched to. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); + + /// Called whenever there is audio input. + /// + /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) + /// @returns Whether this callback has modified the audio input-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); + + /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). + /// The provided audio buffer is the raw buffer without any processing applied to it yet. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) + /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, + /// the content of this parameter is unspecified and should not be accessed + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); + + /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). + /// Note that this happens immediately before Mumble clips the audio buffer. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); + + /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the + /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended + /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. + /// + /// @param connection The ID of the server-connection the data is coming from + /// @param sender The ID of the user whose client's plugin has sent the data + /// @param data The sent data represented as a string + /// @param dataLength The length of data + /// @param dataID The ID of this data + /// @return Whether the given data has been processed by this plugin + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, + const char *dataID); + + /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the + /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this + /// method will be called for every client already on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been added + + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the + /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this + /// method will be called for every client on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local + /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been added + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local + /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also + /// considered renaming). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been renamed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a key has been pressed or released while Mumble has keyboard focus. + /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard + /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to + /// enable that. + /// + /// @param keyCode The key code of the respective key. The character codes are defined + /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform + /// to the ASCII code-page with the only difference that case is not distinguished. Therefore + /// always the upper-case letter code will be used for letters. + /// @param wasPres Whether the respective key has been pressed (instead of released) + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// This function is used to determine whether the plugin can find an update for itself that is available for download. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @return Whether the plugin was able to find an update for itself + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); + + /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. + /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure + /// though that you don't forget about the trailing null byte. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into + /// @param bufferSize The size of the buffer + /// @param offset The offset in the URL from which this functions should start writing it to the buffer + /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called + /// again with a modified offset until the URL has been completely transferred. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/extensions/src/MumbleTest/PluginComponents.h b/extensions/src/MumbleTest/PluginComponents.h new file mode 100644 index 000000000..b203eb1b7 --- /dev/null +++ b/extensions/src/MumbleTest/PluginComponents.h @@ -0,0 +1,313 @@ +// Copyright 2019-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file contains definitions of types and other components used in Mumble's plugin system + +#ifndef MUMBLE_PLUGINCOMPONENT_H_ +#define MUMBLE_PLUGINCOMPONENT_H_ + +#include +#include +#include + +#ifdef QT_VERSION + #include +#endif + +// define the calling convention macro based on the compiler being used +#if defined(_MSC_VER) + #define PLUGIN_CALLING_CONVENTION __cdecl +#elif defined(__MINGW32__) + #define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) +#else + #define PLUGIN_CALLING_CONVENTION +#endif + + +/// A macro holding the exit status of a successful operation +#define STATUS_OK EC_OK +/// A macro holding the version object that is considered to correspond to an unknown version +#define VERSION_UNKNOWN Version({0,0,0}) + + +/// This enum's values correspond to special feature sets a plugin may provide. +/// They are meant to be or'ed together to represent the total feature set of a plugin. +enum PluginFeature { + /// None of the below + FEATURE_NONE = 0, + /// The plugin provides positional data from a game + FEATURE_POSITIONAL = 1 << 0, + /// The plugin modifies the input/output audio itself + FEATURE_AUDIO = 1 << 1 +}; + +/// This enum's values represent talking states a user can be in when using Mumble. +enum TalkingState { + INVALID=-1, + PASSIVE=0, + TALKING, + WHISPERING, + SHOUTING +}; + +/// This enum's values represent transmission modes a user might have configured. Transmission mode +/// in this context is referring to a method that determines when a user is speaking and thus when +/// to transmit audio packets. +enum TransmissionMode { + TM_CONTINOUS, + TM_VOICE_ACTIVATION, + TM_PUSH_TO_TALK +}; + +/// This enum's values represent the error codes that are being used by the MumbleAPI. +/// You can get a string-representation for each error code via the errorMessage function. +enum ErrorCode { + EC_GENERIC_ERROR = -1, + EC_OK = 0, + EC_POINTER_NOT_FOUND, + EC_NO_ACTIVE_CONNECTION, + EC_USER_NOT_FOUND, + EC_CHANNEL_NOT_FOUND, + EC_CONNECTION_NOT_FOUND, + EC_UNKNOWN_TRANSMISSION_MODE, + EC_AUDIO_NOT_AVAILABLE, + EC_INVALID_SAMPLE, + EC_INVALID_PLUGIN_ID +}; + +/// This enum's values represent error codes specific to the framework of handling positional data +/// gathering (needed for Mumble's positional audio feature). +enum PositionalDataErrorCode { + /// Positional data has been initialized properly + PDEC_OK = 0, + /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be + /// at another point in time. + PDEC_ERROR_TEMP, + /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). + PDEC_ERROR_PERM +}; + +/// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. +enum KeyCode { + KC_INVALID = -1, + + // Non-printable characters first + KC_NULL = 0, + KC_END = 1, + KC_LEFT = 2, + KC_RIGHT = 4, + KC_UP = 5, + KC_DOWN = 6, + KC_DELETE = 7, + KC_BACKSPACE = 8, + KC_TAB = 9, + KC_ENTER = 10, // == '\n' + KC_ESCAPE = 27, + KC_PAGE_UP = 11, + KC_PAGE_DOWN = 12, + KC_SHIFT = 13, + KC_CONTROL = 14, + KC_META = 15, + KC_ALT = 16, + KC_ALT_GR = 17, + KC_CAPSLOCK = 18, + KC_NUMLOCK = 19, + KC_SUPER = 20, // == windows key + KC_HOME = 21, // == Pos1 + KC_PRINT = 22, + KC_SCROLLLOCK = 23, + + // Printable characters are assigned to their ASCII code + KC_SPACE = ' ', + KC_EXCLAMATION_MARK = '!', + KC_DOUBLE_QUOTE = '"', + KC_HASHTAG = '#', + KC_DOLLAR = '$', + KC_PERCENT = '%', + KC_AMPERSAND = '&', + KC_SINGLE_QUOTE = '\'', + KC_OPEN_PARENTHESIS = '(', + KC_CLOSE_PARENTHESIS = ')', + KC_ASTERISK = '*', + KC_PLUS = '+', + KC_COMMA = ',', + KC_MINUS = '-', + KC_PERIOD = '.', + KC_SLASH = '/', + KC_0 = '0', + KC_1 = '1', + KC_2 = '2', + KC_3 = '3', + KC_4 = '4', + KC_5 = '5', + KC_6 = '6', + KC_7 = '7', + KC_8 = '8', + KC_9 = '9', + KC_COLON = ':', + KC_SEMICOLON = ';', + KC_LESS_THAN = '<', + KC_EQUALS = '=', + KC_GREATER_THAN = '>', + KC_QUESTION_MARK = '?', + KC_AT_SYMBOL = '@', + KC_A = 'A', + KC_B = 'B', + KC_C = 'C', + KC_D = 'D', + KC_E = 'E', + KC_F = 'F', + KC_G = 'G', + KC_H = 'H', + KC_I = 'I', + KC_J = 'J', + KC_K = 'K', + KC_L = 'L', + KC_M = 'M', + KC_N = 'N', + KC_O = 'O', + KC_P = 'P', + KC_Q = 'Q', + KC_R = 'R', + KC_S = 'S', + KC_T = 'T', + KC_U = 'U', + KC_V = 'V', + KC_W = 'W', + KC_X = 'X', + KC_Y = 'Y', + KC_Z = 'Z', + // leave out lowercase letters (for now) + KC_OPEN_BRACKET = '[', + KC_BACKSLASH = '\\', + KC_CLOSE_BRACKET = ']', + KC_CIRCUMFLEX = '^', + KC_UNDERSCORE = '_', + KC_GRAVE_AKCENT = '`', + KC_OPEN_BRACE = '{', + KC_VERTICAL_BAR = '|', + KC_CLOSE_BRACE = '}', + KC_TILDE = '~', + + // Some characters from the extended ASCII code + KC_DEGREE_SIGN = 176, + + + + // F-keys + // Start at a value of 256 as extended ASCII codes range up to 256 + KC_F1 = 256, + KC_F2 = 257, + KC_F3 = 258, + KC_F4 = 259, + KC_F5 = 260, + KC_F6 = 261, + KC_F7 = 262, + KC_F8 = 263, + KC_F9 = 264, + KC_F10 = 265, + KC_F11 = 266, + KC_F12 = 267, + KC_F13 = 268, + KC_F14 = 269, + KC_F15 = 270, + KC_F16 = 271, + KC_F17 = 272, + KC_F18 = 273, + KC_F19 = 274, +}; + +/// A struct for representing a version of the form major.minor.patch +struct Version { + int32_t major; + int32_t minor; + int32_t patch; +#ifdef __cplusplus + bool operator<(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; + } + + bool operator>(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; + } + + bool operator>=(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; + } + + bool operator<=(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; + } + + bool operator==(const Version& other) const { + return this->major == other.major && this->minor == other.minor && this->patch == other.patch; + } + + operator std::string() const { + return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); + } + +#ifdef QT_VERSION + operator QString() const { + return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); + } +#endif +#endif +}; + +/// @param errorCode The error code to get a message for +/// @returns The error message coresponding to the given error code. The message +/// is encoded as a C-string and are static meaning that it is safe to use the +/// returned pointer in your code. +inline const char* errorMessage(int16_t errorCode) { + switch (errorCode) { + case EC_GENERIC_ERROR: + return "Generic error"; + case EC_OK: + return "Ok - this is not an error"; + case EC_POINTER_NOT_FOUND: + return "Can't find the passed pointer"; + case EC_NO_ACTIVE_CONNECTION: + return "There is currently no active connection to a server"; + case EC_USER_NOT_FOUND: + return "Can't find the requested user"; + case EC_CHANNEL_NOT_FOUND: + return "Can't find the requested channel"; + case EC_CONNECTION_NOT_FOUND: + return "Can't identify the requested connection"; + case EC_UNKNOWN_TRANSMISSION_MODE: + return "Unknown transmission mode encountered"; + case EC_AUDIO_NOT_AVAILABLE: + return "There is currently no audio output available"; + case EC_INVALID_SAMPLE: + return "Attempted to use invalid sample (can't play it)"; + case EC_INVALID_PLUGIN_ID: + return "Used an invalid plugin ID"; + default: + return "Unknown error code"; + } +} + + +/// Typedef for the type of a talking state +typedef enum TalkingState talking_state_t; +/// Typedef for the type of a transmission mode +typedef enum TransmissionMode transmission_mode_t; +/// Typedef for the type of a version +typedef struct Version version_t; +/// Typedef for the type of a connection +typedef int32_t mumble_connection_t; +/// Typedef for the type of a user +typedef uint32_t mumble_userid_t; +/// Typedef for the type of a channel +typedef int32_t mumble_channelid_t; +/// Typedef for the type of an error (code) +typedef enum ErrorCode mumble_error_t; +/// Typedef for the type of a plugin ID +typedef uint32_t plugin_id_t; +/// Typedef for the type of a key-code +typedef KeyCode keycode_t; + +#endif // MUMBLE_PLUGINCOMPONENT_H_ diff --git a/extensions/src/MumbleTest/testPlugin/testPlugin.cpp b/extensions/src/MumbleTest/testPlugin/testPlugin.cpp new file mode 100644 index 000000000..6cb2ad535 --- /dev/null +++ b/extensions/src/MumbleTest/testPlugin/testPlugin.cpp @@ -0,0 +1,364 @@ +// Copyright 2019-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +// Include the definitions of the plugin functions +// Not that this will also include ../PluginComponents.h +#include "../MumblePlugin.h" +#include "../MumbleAPI.h" + +#include +#include + +// These are just some utility functions facilitating writing logs and the like +// The actual implementation of the plugin is further down +std::ostream& pLog() { + std::cout << "TestPlugin: "; + return std::cout; +} + +template +void pluginLog(T log) { + pLog() << log << std::endl; +} + +std::ostream& operator<<(std::ostream& stream, const version_t version) { + stream << "v" << version.major << "." << version.minor << "." << version.patch; + return stream; +} + + +////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////// +//////////////////// PLUGIN IMPLEMENTATION /////////////////// +////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////// + +MumbleAPI mumAPI; +mumble_connection_t activeConnection; +plugin_id_t ownID; + +////////////////////////////////////////////////////////////// +//////////////////// OBLIGATORY FUNCTIONS //////////////////// +////////////////////////////////////////////////////////////// +// All of the following function must be implemented in order for Mumble to load the plugin + +mumble_error_t mumble_init(mumble_connection_t connection) { + pluginLog("Initialized plugin"); + + // Print the connection ID at initialization. If not connected to a server it should be -1. + pLog() << "Connection ID at initialization: " << connection << std::endl; + + // STATUS_OK is a macro set to the appropriate status flag (ErrorCode) + // If you need to return any other status have a look at the ErrorCode enum + // inside PluginComponents.h and use one of its values + return STATUS_OK; +} + +void mumble_shutdown() { + pluginLog("Shutdown plugin"); + + mumAPI.log(ownID, "Shutdown"); +} + +const char* mumble_getName() { + // The pointer returned by this functions has to remain valid forever and it must be able to return + // one even if the plugin hasn't loaded (yet). Thus it may not require any variables that are only set + // once the plugin is initialized + // For most cases returning a hard-coded String-literal should be what you aim for + return "TestPlugin"; +} + +version_t mumble_getAPIVersion() { + // MUMBLE_PLUGIN_API_VERSION will always contain the API version of the used header file (the one used to build + // this plugin against). Thus you should always return that here in order to no have to worry about it. + return MUMBLE_PLUGIN_API_VERSION; +} + +void mumble_registerAPIFunctions(MumbleAPI api) { + // In this function the plugin is presented with a struct of function pointers that can be used + // to interact with Mumble. Thus you should store it somewhere safe for later usage. + mumAPI = api; + + pluginLog("Registered Mumble's API functions"); + + mumAPI.log(ownID, "Received API functions"); +} + + +////////////////////////////////////////////////////////////// +///////////////////// OPTIONAL FUNCTIONS ///////////////////// +////////////////////////////////////////////////////////////// +// The implementation of below functions is optional. If you don't need them, don't include them in your +// plugin + +void mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion) { + // this function will always be the first one to be called. Even before init() + // In here you can get info about the Mumble version this plugin is about to run in. + pLog() << "Mumble version: " << mumbleVersion << "; Mumble API-Version: " << mumbleAPIVersion << "; Minimal expected API-Version: " + << minimalExpectedAPIVersion << std::endl; +} + +version_t mumble_getVersion() { + // Mumble uses semantic versioning (see https://semver.org/) + // { major, minor, patch } + return { 1, 0, 0 }; +} + +const char* mumble_getAuthor() { + // For the returned pointer the same rules as for getName() apply + // In short: in the vast majority of cases you'll want to return a hard-coded String-literal + return "MumbleDevelopers"; +} + +const char* mumble_getDescription() { + // For the returned pointer the same rules as for getName() apply + // In short: in the vast majority of cases you'll want to return a hard-coded String-literal + return "This plugin is merely a reference implementation without any real functionality. It shouldn't be included in the release build of Mumble"; +} + +void mumble_registerPluginID(plugin_id_t id) { + // This ID serves as an identifier for this plugin as far as Mumble is concerned + // It might be a good idea to store it somewhere for later use + pLog() << "Registered ID: " << id << std::endl; + + ownID = id; +} + +uint32_t mumble_getFeatures() { + // Tells Mumble whether this plugin delivers some known common functionality. See the PluginFeature enum in + // PluginComponents.h for what is available. + // If you want your plugin to deliver positional data, you'll want to return FEATURE_POSITIONAL + return FEATURE_NONE; +} + +uint32_t mumble_deactivateFeatures(uint32_t features) { + pLog() << "Asked to deactivate feature set " << features << std::endl; + + // All features that can't be deactivated should be returned + return features; +} + +uint8_t mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount) { + std::ostream& stream = pLog() << "Got " << programCount << " programs to init positional data."; + + if (programCount > 0) { + stream << " The first name is " << programNames[0] << " and has PID " << programPIDs[0]; + } + + stream << std::endl; + + // As this plugin doesn't provide PD, we return PDEC_ERROR_PERM to indicate that even in the future we won't do so + // If your plugin is indeed delivering positional data but is only temporarily unaible to do so, return PDEC_ERROR_TEMP + // and if you deliver PD and succeeded initializing return PDEC_OK. + return PDEC_ERROR_PERM; +} + +#define SET_TO_ZERO(name) name[0] = 0.0f; name[1] = 0.0f; name[2] = 0.0f +bool mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, + float *cameraAxis, const char **context, const char **identity) { + pluginLog("Has been asked to deliver positional data"); + + // If unable to provide positional data, this function should return false and reset all given values to 0/empty Strings + SET_TO_ZERO(avatarPos); + SET_TO_ZERO(avatarDir); + SET_TO_ZERO(avatarAxis); + SET_TO_ZERO(cameraPos); + SET_TO_ZERO(cameraDir); + SET_TO_ZERO(cameraAxis); + *context = ""; + *identity = ""; + + // This function returns whether it can continue to deliver positional data + return false; +} + +void mumble_shutdownPositionalData() { + pluginLog("Shutting down positional data"); +} + +void mumble_onServerConnected(mumble_connection_t connection) { + activeConnection = connection; + + pLog() << "Established server-connection with ID " << connection << std::endl; +} + +void mumble_onServerDisconnected(mumble_connection_t connection) { + activeConnection = -1; + + pLog() << "Disconnected from server-connection with ID " << connection << std::endl; +} + +void mumble_onServerSynchronized(mumble_connection_t connection) { + // The client has finished synchronizing with the server. Thus we can now obtain a list of all users on this server + pLog() << "Server has finished synchronizing (ServerConnection: " << connection << ")" << std::endl ; + + size_t userCount; + mumble_userid_t *userIDs; + + if (mumAPI.getAllUsers(ownID, activeConnection, &userIDs, &userCount) != STATUS_OK) { + pluginLog("[ERROR]: Can't obtain user list"); + return; + } + + pLog() << "There are " << userCount << " users on this server. Their names are:" << std::endl; + + for(size_t i=0; i= 0) { + stream << " He came from channel with ID " << previousChannelID << "."; + } + + stream << " (ServerConnection: " << connection << ")" << std::endl; +} + +void mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID) { + pLog() << "User with ID " << userID << " has left channel with ID " << channelID << ". (ServerConnection: " << connection << ")" << std::endl; +} + +void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState) { + std::ostream& stream = pLog() << "User with ID " << userID << " changed his talking state to "; + + // The possible values are contained in the TalkingState enum inside PluginComponent.h + switch(talkingState) { + case INVALID: + stream << "Invalid"; + break; + case PASSIVE: + stream << "Passive"; + break; + case TALKING: + stream << "Talking"; + break; + case WHISPERING: + stream << "Whispering"; + break; + case SHOUTING: + stream << "Shouting"; + break; + default: + stream << "Unknown (" << talkingState << ")"; + } + + stream << ". (ServerConnection: " << connection << ")" << std::endl; +} + +bool mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech) { + pLog() << "Audio input with " << channelCount << " channels and " << sampleCount << " samples per channel encountered. IsSpeech: " + << isSpeech << std::endl; + + // mark inputPCM as unused + (void) inputPCM; + + // This function returns whether it has modified the audio stream + return false; +} + +bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID) { + std::ostream& stream = pLog() << "Audio output source with " << channelCount << " channels and " << sampleCount << " samples per channel fetched."; + + if (isSpeech) { + stream << " The output is speech from user with ID " << userID << "."; + } + + stream << std::endl; + + // Mark ouputPCM as unused + (void) outputPCM; + + // This function returns whether it has modified the audio stream + return false; +} + +bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount) { + pLog() << "The resulting audio output has " << channelCount << " channels with " << sampleCount << " samples per channel" << std::endl; + + // mark outputPCM as unused + (void) outputPCM; + + // This function returns whether it has modified the audio stream + return false; +} + +bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, const char *dataID) { + pLog() << "Received data with ID \"" << dataID << "\" from user with ID " << sender << ". Its length is " << dataLength + << ". (ServerConnection:" << connection << ")" << std::endl; + + if (std::strcmp(dataID, "testMsg") == 0) { + pLog() << "The received data: " << data << std::endl; + } + + // This function returns whether it has processed the data (preventing further plugins from seeing it) + return false; +} + +void mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID) { + pLog() << "Added user with ID " << userID << " (ServerConnection: " << connection << ")" << std::endl; +} + +void mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID) { + pLog() << "Removed user with ID " << userID << " (ServerConnection: " << connection << ")" << std::endl; +} + +void mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID) { + pLog() << "Added channel with ID " << channelID << " (ServerConnection: " << connection << ")" << std::endl; +} + +void mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID) { + pLog() << "Removed channel with ID " << channelID << " (ServerConnection: " << connection << ")" << std::endl; +} + +void mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID) { + pLog() << "Renamed channel with ID " << channelID << " (ServerConnection: " << connection << ")" << std::endl; +} + +void mumble_onKeyEvent(uint32_t keyCode, bool wasPress) { + pLog() << "Encountered key " << (wasPress ? "press" : "release") << " of key with code " << keyCode << std::endl; +} + +bool mumble_hasUpdate() { + // This plugin never has an update + return false; +} + +bool mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset) { + static std::string url = "https://i.dont.exist/testplugin.zip"; + + size_t writtenChars = url.copy(buffer, bufferSize, offset); + + if (writtenChars < bufferSize) { + // URL has fit into the buffer -> append null byte and be done with it + buffer[writtenChars] = '\0'; + return true; + } else { + std::cout << "Overflow" << std::endl; + return false; + } +} diff --git a/extensions/src/MumbleTest/testPlugin/testPlugin.pro b/extensions/src/MumbleTest/testPlugin/testPlugin.pro new file mode 100644 index 000000000..55c306d3f --- /dev/null +++ b/extensions/src/MumbleTest/testPlugin/testPlugin.pro @@ -0,0 +1,9 @@ +# Copyright 2019-2020 The Mumble Developers. All rights reserved. +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file at the root of the +# Mumble source tree or at . + +include(../plugins.pri) + +TARGET = testPlugin +SOURCES = testPlugin.cpp From 9f082c0b7341a765d7083fa4e06584253436c2c7 Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Sun, 10 May 2020 16:58:20 -0700 Subject: [PATCH 013/104] Tweaks and fixes to Mumble plugin. --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 37 ++++++++++--------- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 8 ++-- .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 6 +-- .../ACRE2Mumble/MumbleCallbacks_static.cpp | 4 +- extensions/src/ACRE2Mumble/MumbleClient.cpp | 4 -- .../src/ACRE2Mumble/MumbleCommandServer.cpp | 25 +++++++++++-- .../mumble_includes/MumblePlugin.h | 3 +- 7 files changed, 53 insertions(+), 34 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index ded0ffcb7..383e08f30 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -8,8 +8,8 @@ #include "MumbleFunctions.h" -#define FROM_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_fromMumble" -#define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toMumble" +#define FROM_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_fromTS" +#define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toTS" extern MumbleAPI mumAPI; mumble_connection_t activeConnection = -1; @@ -44,11 +44,6 @@ void ts3plugin_setFunctionPointers(const struct TS3Functions funcs) { void mumble_registerPluginID(plugin_id_t id) { pluginID = id; - if (CEngine::getInstance() != NULL) { - if (((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer()) != NULL) { - ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); - } - } } uint32_t mumble_getFeatures() { @@ -57,27 +52,33 @@ uint32_t mumble_getFeatures() { void mumble_registerAPIFunctions(struct MumbleAPI api) { mumAPI = api; + CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); + if (CEngine::getInstance() != NULL) { + if (((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer()) != NULL) { + ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); + } + if (pluginID != -1) ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); + if (activeConnection != -1) { + // we are activating while connected, call it + // virtualize a connect event + mumble_onServerSynchronized(activeConnection); + } + } } // // Init // -mumble_error_t mumble_init() { - CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); - - // if PluginID was already loaded. - if (pluginID != -1) ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); - if (activeConnection != -1) { - // we are activating while connected, call it - // virtualize a connect event - mumble_onServerConnected(activeConnection); +mumble_error_t mumble_init(mumble_connection_t connection) { + if (connection != -1) { + activeConnection = connection; } return STATUS_OK; } -void mumble_onServerConnected(mumble_connection_t connection) { +void mumble_onServerSynchronized(mumble_connection_t connection) { activeConnection = connection; // @@ -86,6 +87,8 @@ void mumble_onServerConnected(mumble_connection_t connection) { //ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), (anyID*)& clientId); mumAPI.getLocalUserID(pluginID, activeConnection, (mumble_userid_t*)& clientId); CEngine::getInstance()->getSelf()->setId(clientId); + CEngine::getInstance()->getExternalServer()->setId(clientId); + // subscribe to all channels to receive event //ts3Functions.requestChannelSubscribeAll(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 6448d7874..f9957d8c7 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -49,10 +49,10 @@ bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_ for (int c = 0; c <= mixdownSampleLength - 1; ++c) { float mixedSample; if (mixdownSamples[c] > 0) { - mixedSample = static_cast(mixdownSamples[c] * LIMITER::max()); + mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); } else { - mixedSample = -static_cast(mixdownSamples[c] * LIMITER::min()); + mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); } outputPCM[c] = mixedSample; } @@ -92,10 +92,10 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin for (int c = 0; c <= mixdownSampleLength - 1; ++c) { float mixedSample; if (mixdownSamples[c] > 0) { - mixedSample = static_cast(mixdownSamples[c] * LIMITER::max()); + mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); } else { - mixedSample = -static_cast(mixdownSamples[c] * LIMITER::min()); + mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); } outputPCM[c] = mixedSample; } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index e1ca69abb..16f3696a4 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -14,7 +14,7 @@ // TS3 Speaking callbacks // void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t status) { - + LOG("mumble_onUserTalkingStateChanged ENTER: %d", status); if (static_cast(userID) != CEngine::getInstance()->getSelf()->getId()) { return; } else if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { @@ -37,7 +37,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use if (status != TalkingState::PASSIVE && status != TalkingState::INVALID) { if (!CEngine::getInstance()->getClient()->getRadioPTTDown()) { CEngine::getInstance()->getClient()->setOnRadio(false); - } else { + } /*else { if (!CEngine::getInstance()->getClient()->getDirectFirst()) { CEngine::getInstance()->getClient()->microphoneOpen(true); } else { @@ -46,7 +46,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use CEngine::getInstance()->getClient()->microphoneOpen(true); } } - } + }*/ } return; } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp index c995d8c8f..61ec5b5d7 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -21,4 +21,6 @@ version_t mumble_getAPIVersion() { return MUMBLE_PLUGIN_API_VERSION; } - +version_t mumble_getVersion() { + return version_t{ ACRE_VERSION_MAJOR, ACRE_VERSION_MINOR, ACRE_VERSION_SUBMINOR }; +} diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 679cf04d5..386213caa 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -170,10 +170,6 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } } - if (!this->getVAD() && speakingType_ == acre::Speaking::direct) { - this->microphoneOpen(true); - } - if (stopDirectSpeaking) { CEngine::getInstance()->localStopSpeaking(); } diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index 612266828..03ea24175 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -35,10 +35,27 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ mumble_userid_t* channelUsers; size_t userCount; mumble_channelid_t currentChannel; - mumAPI.getChannelOfUser(pluginID, activeConnection, CEngine::getInstance()->getSelf()->getId(), ¤tChannel); - mumAPI.getUsersInChannel(pluginID, activeConnection, currentChannel, &channelUsers, &userCount); - mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const char*)msg->getData(), msg->getLength(), "ACRE2"); - mumAPI.freeMemory(pluginID, (void *)&channelUsers); + mumble_error_t err; + err = mumAPI.getChannelOfUser(pluginID, activeConnection, this->getId(), ¤tChannel); + if (err != ErrorCode::EC_OK) { + LOG("ERROR, UNABLE TO GET CHANNEL OF USER: %d", err); + return acre::Result::error; + } + err = mumAPI.getUsersInChannel(pluginID, activeConnection, currentChannel, &channelUsers, &userCount); + if (err != ErrorCode::EC_OK) { + LOG("ERROR, UNABLE TO GET USERS IN CHANNEL: %d", err); + return acre::Result::error; + } + err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const char*)msg->getData(), msg->getLength(), "ACRE2"); + if (err != ErrorCode::EC_OK) { + LOG("ERROR, UNABLE TO SEND MESSAGE DATA: %d", err); + return acre::Result::error; + } + err = mumAPI.freeMemory(pluginID, (void *)channelUsers); + if (err != ErrorCode::EC_OK) { + LOG("ERROR, UNABLE TO FREE CHANNEL USER LIST: %d", err); + return acre::Result::error; + } delete msg; diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h index 002ede54c..c6c82393d 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h @@ -34,8 +34,9 @@ extern "C" { /// Gets called right after loading the plugin in order to let the plugin initialize. /// + /// @param connection The ID of the server-connection this event is connected to, or its default value. /// @returns The status of the initialization. If everything went fine, return STATUS_OK - PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(); + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_connection_t connection); /// Gets called when unloading the plugin in order to allow it to clean up after itself. PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); From b98757847db8f7fabb85c8162f36d9cea29ddefe Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Tue, 12 May 2020 13:53:25 -0700 Subject: [PATCH 014/104] Scale samples correctly, fix inverted logic in speaking status. --- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 18 ++++++++++++++++-- .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index dfff37bc4..83e416ff0 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -44,7 +44,14 @@ bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_ //} for (std::int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { - mixdownSamples[c] = static_cast(outputPCM[c] / LIMITER::max()); + float sample = outputPCM[c]; + if (sample > 1.0) { + sample = 1.0; + } + else if (sample < -1.0) { + sample = -1.0; + } + mixdownSamples[c] = static_cast(sample * LIMITER::max()); } CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent(static_cast(userID), mixdownSamples, sampleCount, channelCount); @@ -91,7 +98,14 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin //} for (int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { - mixdownSamples[c] = static_cast(outputPCM[c] / LIMITER::max()); + float sample = outputPCM[c]; + if (sample > 1.0) { + sample = 1.0; + } + else if (sample < -1.0) { + sample = -1.0; + } + mixdownSamples[c] = static_cast(sample * LIMITER::max()); } CEngine::getInstance()->getSoundEngine()->onEditMixedPlaybackVoiceDataEvent(mixdownSamples, sampleCount, channelCount, speakerMask); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index fd10610b3..d184cf726 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -44,7 +44,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use if (CEngine::getInstance()->getClient()->getVAD()) { return; } else { - if (status != TalkingState::PASSIVE && status != TalkingState::INVALID) { + if (status == TalkingState::PASSIVE || status == TalkingState::INVALID) { if (!CEngine::getInstance()->getClient()->getRadioPTTDown()) { CEngine::getInstance()->getClient()->setOnRadio(false); } From 426dc87dbe8df2c9aeb76f186cdd6b580506e6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Thu, 14 May 2020 19:05:06 +0200 Subject: [PATCH 015/104] Rewrite auto-plugin copy --- extensions/src/ACRE2Steam/CMakeLists.txt | 3 +- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 599 +++++------------- extensions/src/ACRE2Steam/mumble_plugin.hpp | 61 ++ extensions/src/ACRE2Steam/ts3_plugin.hpp | 72 +++ extensions/src/ACRE2Steam/voip_base_class.cpp | 192 ++++++ extensions/src/ACRE2Steam/voip_base_class.hpp | 86 +++ 6 files changed, 583 insertions(+), 430 deletions(-) create mode 100644 extensions/src/ACRE2Steam/mumble_plugin.hpp create mode 100644 extensions/src/ACRE2Steam/ts3_plugin.hpp create mode 100644 extensions/src/ACRE2Steam/voip_base_class.cpp create mode 100644 extensions/src/ACRE2Steam/voip_base_class.hpp diff --git a/extensions/src/ACRE2Steam/CMakeLists.txt b/extensions/src/ACRE2Steam/CMakeLists.txt index eedfc3f0f..e6ce77e2c 100644 --- a/extensions/src/ACRE2Steam/CMakeLists.txt +++ b/extensions/src/ACRE2Steam/CMakeLists.txt @@ -9,7 +9,8 @@ file(GLOB_RECURSE SOURCES *.h *.hpp *.c *.cpp) add_library( ${ACRE_NAME} MODULE ${SOURCES} ${GLOBAL_SOURCES}) set_target_properties(${ACRE_NAME} PROPERTIES FOLDER ACRE2) - +target_compile_features(${ACRE_NAME} PRIVATE cxx_std_17) +#set_target_properties(${ACRE_NAME} PRIVATE LINKER_LANGUAGE CXX) # Copy and rename if(USE_64BIT_BUILD) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 705307d30..a4309fe4f 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -1,227 +1,79 @@ +/** + * @author Ferran Obón Santacana (Magnetar) + * @author James Smith (snippers) + * + * @copyright Copyright (c) 2020 International Development & Integration Systems LLC + * + * Voice over IP auto-plugin copy functionality. + */ + #include "compat.h" //#include "Log.h" #include "Macros.h" -#include -#include -#include -#include -#include -#include -#include "shlobj.h" #include "Shlwapi.h" +#include "mumble_plugin.hpp" +#include "shlobj.h" +#include "ts3_plugin.hpp" + #include -#include #include +#include +#include +#include #include +#include +#include +#include #pragma comment(lib, "shlwapi.lib") -enum class SteamCommand : uint8_t { - Check, - GetPath, - DoCopy -}; +enum class SteamCommand : uint8_t { check, get_path, do_copy }; void ClosePipe(); extern "C" { - __declspec (dllexport) void __stdcall RVExtensionVersion(char *output, int outputSize); - __declspec(dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function); +__declspec(dllexport) void __stdcall RVExtensionVersion(char *output, int outputSize); +__declspec(dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function); }; void __stdcall RVExtensionVersion(char *output, int outputSize) { sprintf_s(output, outputSize - 1, "%s", ACRE_VERSION); } -inline std::string get_path() { - char moduleName[MAX_PATH]; - GetModuleFileNameA(nullptr, moduleName, MAX_PATH); - return std::string(moduleName); -} - inline std::string get_cmdline() { return std::string(GetCommandLineA()); } -inline std::string get_path(const std::string &filepath) { - char drive[_MAX_DRIVE]; - char dir [_MAX_DIR]; - - _splitpath( - filepath.c_str(), - drive, - dir, - nullptr, - nullptr - ); - - return (std::string(drive) + std::string(dir)); -} - -inline std::string get_quoted(std::string &text) { - std::string found_text = ""; - - std::string::size_type start_position = text.find("\""); - if (start_position != std::string::npos) { - ++start_position; // start after the double quotes. - // look for end position; - std::string::size_type end_position = text.find("\""); - if (end_position != std::string::npos) { - found_text = text.substr(start_position, end_position - start_position); - } - } - return found_text; -} -EXTERN_C IMAGE_DOS_HEADER __ImageBase; - -inline std::string find_mod_folder() { - char module_path[MAX_PATH]; - GetModuleFileNameA((HINSTANCE)&__ImageBase, module_path, MAX_PATH); - - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - - _splitpath( - module_path, - drive, - dir, - NULL, - NULL - ); - - return (std::string(drive) + std::string(dir)); +bool skip_plugin_copy() { + return std::string::npos != get_cmdline().find("-skipAcrePluginCopy"); } -inline std::string find_mod_file(const std::string &filename) { - std::string path = find_mod_folder() + filename; - if (!PathFileExistsA(path.c_str())) { - // No mod path was set, it means they used the mod config. It *DOES* mean it relative to a folder in our path at least. - // So, we just search all the local folders - - WIN32_FIND_DATAA data; - std::string path(""); - HANDLE hFile = FindFirstFileA(path.c_str(), &data); - - if (hFile == INVALID_HANDLE_VALUE) - return ""; - - while ((FindNextFile(hFile, &data) != 0) || (GetLastError() != ERROR_NO_MORE_FILES)) { - if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - const std::string fullpath = std::string(data.cFileName) + filename; - if (PathFileExistsA(fullpath.c_str())) { - path = fullpath; - break; - } - } - } - } - return path; +bool skip_ts_plugin_copy() { + return std::string::npos != get_cmdline().find("-skipAcreTSPluginCopy"); } -std::string ReadRegValue(HKEY root, const std::string &key, const std::string &name) { - HKEY hkey; - if (RegOpenKeyExA(root, key.c_str(), 0, KEY_READ, &hkey) != ERROR_SUCCESS) { - return ""; - } - - DWORD type; - DWORD cbData; - if (RegQueryValueExA(hkey, name.c_str(), nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { - RegCloseKey(hkey); - return ""; - } - - if (type != REG_SZ) { - RegCloseKey(hkey); - return ""; - } - - std::string value(cbData / sizeof(char), '\0'); - if (RegQueryValueExA(hkey, name.c_str(), nullptr, nullptr, reinterpret_cast(&value[0]), &cbData) != ERROR_SUCCESS) { - RegCloseKey(hkey); - return ""; - } - - RegCloseKey(hkey); - - size_t firstNull = value.find_first_of('\0'); - if (firstNull != std::string::npos) { - value.resize(firstNull); - } - - return value; +bool skip_mumble_plugin_copy() { + return std::string::npos != get_cmdline().find("-skipAcreMumblePluginCopy"); } -std::string ReadRegValue64(HKEY root, const std::string &key, const std::string &name) { - HKEY hkey; - if (RegOpenKeyExA(root, key.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hkey) != ERROR_SUCCESS) - return ""; - - DWORD type; - DWORD cbData; - if (RegQueryValueExA(hkey, name.c_str(), nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { - RegCloseKey(hkey); - return ""; - } - - if (type != REG_SZ) { - RegCloseKey(hkey); - return ""; - } - - std::string value(cbData / sizeof(char), '\0'); - if (RegQueryValueExA(hkey, name.c_str(), nullptr, nullptr, reinterpret_cast(&value[0]), &cbData) != ERROR_SUCCESS) { - RegCloseKey(hkey); +std::string mumble_install_path() { + const std::string option = "-mumblePath="; + size_t pos = get_cmdline().find(option); + if (pos == std::string::npos) { return ""; } + size_t end_path_pos = get_cmdline().find_first_of(' ', pos); + if (end_path_pos == std::string::npos) { + // Check for end of line - RegCloseKey(hkey); + end_path_pos = get_cmdline().find_first_of('\n', pos); - size_t firstNull = value.find_first_of('\0'); - if (firstNull != std::string::npos) - value.resize(firstNull); - - return value; -} - -bool compare_file(const std::string &pathA, const std::string &pathB) { - - // Open both files ath the end to check their size - std::ifstream fileA(pathA, std::ifstream::ate | std::ifstream::binary); - std::ifstream fileB(pathB, std::ifstream::ate | std::ifstream::binary); - - if (fileA.tellg() != fileB.tellg()) { - return false; - } - - // Files are of the same size. Rewind and compare file contents - fileA.seekg(0); - fileB.seekg(0); - - std::istreambuf_iterator beginA(fileA); - std::istreambuf_iterator beginB(fileB); - - return std::equal(beginA, std::istreambuf_iterator(), beginB); -} - -bool skip_plugin_copy() { - if (std::string::npos != get_cmdline().find("-skipAcrePluginCopy")) { - return true; - } - return false; -} - -void checkTsLocations(const std::string &appData, const std::string &rootkey, const HKEY key, std::vector &tsLocations, std::vector &tsDeleteLocations) { - if (rootkey != "") { - const std::string configLocation = ReadRegValue64(key, "SOFTWARE\\TeamSpeak 3 Client", "ConfigLocation"); - if (configLocation == "0") { - tsLocations.push_back(appData); - tsDeleteLocations.push_back(rootkey); - } else { - tsLocations.push_back(rootkey); - tsDeleteLocations.push_back(rootkey + "\\config"); + if (end_path_pos == std::string::npos) { + return ""; } } + pos += option.length(); + return get_cmdline().substr(pos, end_path_pos - pos); } void __stdcall RVExtension(char *output, int outputSize, const char *function) { @@ -240,277 +92,166 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { params = functionStr.substr(id_length, functionStr.length() - id_length); } - const SteamCommand command = static_cast(std::atoi(id.c_str())); + const auto command = static_cast(std::atoi(id.c_str())); if (skip_plugin_copy()) { return; } - switch(command) { - case SteamCommand::Check: { - strncpy(output, "1", outputSize); - return; - } - case SteamCommand::GetPath: { - std::string path = find_mod_file("ACRE2Steam.dll"); - path = ReadRegValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\TeamSpeak 3 Client", ""); - strncpy(output, path.c_str(), outputSize); - return; + const bool skip_ts_plugin = skip_ts_plugin_copy(); + const bool skip_mumble_plugin = skip_mumble_plugin_copy(); + + idi::acre::TS3_plugin ts3_plugin(skip_ts_plugin); + idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, mumble_install_path()); + + switch (command) { + case SteamCommand::check: { + strncpy(output, "1", outputSize); + return; + } + case SteamCommand::get_path: { + std::string path; + if (skip_ts_plugin) { + path = ts3_plugin.read_reg_value(HKEY_LOCAL_MACHINE, ts3_plugin.get_registry_key().c_str(), "", false); } - case SteamCommand::DoCopy: { - std::string current_version = params; - - const std::string path_x86 = find_mod_file("plugin\\acre2_win32.dll"); - const std::string path_x64 = find_mod_file("plugin\\acre2_win64.dll"); - if ((path_x86 == "") || (path_x64 == "")) { - const std::string message_string = "ACRE2 was unable to find TeamSpeak 3 plugin file.\n\nMissing file: " + find_mod_folder() + "plugin\\acre2_win32.dll\n\nThe ACRE2 installation is likely corrupted. Please reinstall."; - const int32_t result = MessageBoxA(nullptr, (LPCSTR) message_string.c_str(), "ACRE2 Installation Error", MB_OK | MB_ICONERROR); - //strncpy(output, "[-1]", outputSize); - TerminateProcess(GetCurrentProcess(), 0); - return; - } - std::vector ts_locations; // Locations to copy the TS dll to. - std::vector ts_delete_locations; // Locations to remove the TS dll from. - - // Teamspeak 3.1 location - Default location - Roaming Appdata. - wchar_t *appDataRoaming = nullptr; - SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &appDataRoaming); - - std::wstringstream ssAppData; - ssAppData << appDataRoaming; - const std::wstring ws = ssAppData.str(); - std::string appData(ws.begin(), ws.end()); - appData += "\\TS3Client"; - CoTaskMemFree(appDataRoaming); //Free it up. - - /* 32 Bit - Machine */ - std::string rootkey = ReadRegValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\TeamSpeak 3 Client", ""); - checkTsLocations(appData, rootkey, HKEY_LOCAL_MACHINE, ts_locations, ts_delete_locations); - - /* 64 Bit - Machine */ - rootkey = ReadRegValue64(HKEY_LOCAL_MACHINE, "SOFTWARE\\TeamSpeak 3 Client", ""); - checkTsLocations(appData, rootkey, HKEY_LOCAL_MACHINE, ts_locations, ts_delete_locations); - - /* 32 Bit - User */ - rootkey = ReadRegValue(HKEY_CURRENT_USER, "Software\\TeamSpeak 3 Client", ""); - checkTsLocations(appData, rootkey, HKEY_CURRENT_USER, ts_locations, ts_delete_locations); - - /* 64 Bit - User */ - rootkey = ReadRegValue64(HKEY_CURRENT_USER, "Software\\TeamSpeak 3 Client", ""); - checkTsLocations(appData, rootkey, HKEY_CURRENT_USER, ts_locations, ts_delete_locations); - - // Remove duplicates - std::vector unique_ts_locations; - std::vector unique_delete_ts_locations; - for (auto location : ts_delete_locations) { - if (location != "") { - bool found = false; - for (auto unique_ts : unique_delete_ts_locations) { - if (location == unique_ts) { - found = true; - break; - } - } - if (!found) { - unique_delete_ts_locations.push_back(location); - } - } + if (skip_mumble_plugin) { + path.append("\n" + mumble_plugin.read_reg_value(HKEY_LOCAL_MACHINE, mumble_plugin.get_registry_key().c_str(), "", false)); + } + strncpy(output, path.c_str(), outputSize); + return; + } + case SteamCommand::do_copy: { + std::string current_version = params; + + // Check ACRE2 installation + if (!ts3_plugin.check_acre_installation() || !mumble_plugin.check_acre_installation()) { + std::vector missing_plugins = ts3_plugin.get_missing_acre_plugins(); + missing_plugins.insert(missing_plugins.end(), std::begin(mumble_plugin.get_missing_acre_plugins()), + std::end(mumble_plugin.get_missing_acre_plugins())); + + std::ostringstream oss; + oss << "ACRE2 was unable to find ACRE 2 plugin files.\n\n"; + for (const auto &missing : missing_plugins) { + oss << "\t" << missing << "\n"; } + oss << "\n\n" + << "The ACRE2 installation is likely corrupted. Please reinstall."; - for (auto location : ts_locations) { - if (location != "") { - bool found = false; - for (auto unique_ts : unique_ts_locations) { - if (location == unique_ts) { - found = true; - break; - } - } - if (!found) { - unique_ts_locations.push_back(location); - - // If we are going to copy to a folder do not remove from the plugin from it. - std::remove(unique_delete_ts_locations.begin(), unique_delete_ts_locations.end(), location); - } - } - } + const std::int32_t result = MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_OK | MB_ICONERROR); + TerminateProcess(GetCurrentProcess(), 0); + return; + } - // No locations to copy to. - if (unique_ts_locations.size() == 0) { - const int32_t result = MessageBoxA(nullptr, "ACRE2 was unable to find a TeamSpeak 3 installation. If you do have an installation please copy the plugins yourself or reinstall TeamSpeak 3. \n\n If you are sure you have TeamSpeak 3 installed and wish to prevent this message from appearing again remove ACRE2Steam.dll and ACRE2Steam_x64.dll from your @acre2 folder.\n\nContinue anyway?", "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); - if (result == IDYES) { - strncpy(output, "[-3,true]", outputSize); - return; - } else { - TerminateProcess(GetCurrentProcess(), 0); - return; - } + const bool ts3_locations_success = ts3_plugin.collect_plugin_locations(); + const bool mumble_locations_success = mumble_plugin.collect_plugin_locations(); + + if (!ts3_locations_success && !mumble_locations_success) { + const std::int32_t result = MessageBoxA(nullptr, + "ACRE2 was unable to find a TeamSpeak 3 or a Mumble installation. If you do have an installation please copy the plugins " + "yourself or reinstall TeamSpeak 3. \n\n If you are sure you have TeamSpeak 3 installed and wish to prevent this message " + "from appearing again remove ACRE2Steam.dll and ACRE2Steam_x64.dll from your @acre2 folder.\n\nContinue anyway?", + "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); + if (result == IDYES) { + strncpy(output, "[-3,true]", outputSize); + return; } - bool updateRequired = false; - std::string found_paths = ""; - for (auto location : unique_ts_locations) { - bool try_copy = true; - - // Skip directory if the folder the plugins folder should be in does not exist. - DWORD location_folder_attr = GetFileAttributes(location.c_str()); - if (location_folder_attr == INVALID_FILE_ATTRIBUTES) { continue; } - if (!(location_folder_attr & FILE_ATTRIBUTE_DIRECTORY)) { continue; } - - const std::string plugin_folder = location + "\\plugins"; - - // If plugins folder does not exist - create it - CreateDirectory(plugin_folder.c_str(), nullptr); // This will silently fail if it exists - Exactly what we want. - - const std::string ts_path_x86 = plugin_folder + "\\acre2_win32.dll"; - const std::string ts_path_x64 = plugin_folder + "\\acre2_win64.dll"; - if (!compare_file(ts_path_x86, path_x86) || !compare_file(ts_path_x64, path_x64)) { // Only copy if files don't match. - updateRequired = true; - do { - if (!CopyFileA((LPCSTR)path_x86.c_str(), (LPCSTR)ts_path_x86.c_str(), false) || !CopyFileA((LPCSTR)path_x64.c_str(), (LPCSTR)ts_path_x64.c_str(), false)) { - DWORD last_error = GetLastError(); - if (last_error == 32) { - const int32_t result = MessageBoxA(nullptr, "ACRE2 was unable to copy the TeamSpeak 3 plugin due to it being in use. Please close any instances of TeamSpeak 3 and click \"Try Again\".\n\nIf you would like to close Arma 3, click Cancel. Press Continue to launch Arma 3 regardless.", "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); - if (result == IDCANCEL) { - TerminateProcess(GetCurrentProcess(), 0); - return; - } else if (result == IDCONTINUE) { - sprintf(output, "[-4,true,%d]", last_error); - return; - } - } else { // Not error 32 - const int32_t result = MessageBoxA(nullptr, "ACRE2 was unable to copy the TeamSpeak 3 plugin. This is most likely because Steam is not running with admin privileges. Please restart Steam as administrator (right click on the shortcut -> run as administrator) and relaunch Arma 3 with ACRE2 loaded. You only need to do this when ACRE2 is updated. \n\nWould you like to run Arma 3 anyway?", "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); - if (result == IDNO) { - TerminateProcess(GetCurrentProcess(), 0); - return; - } else { // Result is yes continue - sprintf(output, "[-5,true,%d]", last_error); - return; - } - } - } else { - found_paths += location + "\n"; - try_copy = false; - } - } while (try_copy); - } - } + TerminateProcess(GetCurrentProcess(), 0); + return; + } - std::string remove_paths = ""; - for (auto location : unique_delete_ts_locations) { - const std::string plugin_folder = location + "\\plugins"; - - // Skip directory if the plugins folder does not exist. - DWORD plugin_folder_attr = GetFileAttributes(plugin_folder.c_str()); - if (plugin_folder_attr == INVALID_FILE_ATTRIBUTES) { continue; } - if (!(plugin_folder_attr & FILE_ATTRIBUTE_DIRECTORY)) { continue; } - - std::vector files; - const std::string ts_path_x64 = plugin_folder + "\\acre2_win64.dll"; - files.push_back(ts_path_x64); - const std::string ts_path_x86 = plugin_folder + "\\acre2_win32.dll"; - files.push_back(ts_path_x86); - - bool popupLocationNotify = false; - for (auto file : files) { - bool try_delete = true; - { - if (!DeleteFileA(file.c_str())) { - DWORD last_error = GetLastError(); - if (last_error != ERROR_FILE_NOT_FOUND) { - updateRequired = true; - if (last_error == FILE_SHARE_DELETE) { // File in use - const int32_t result = MessageBoxA(nullptr, "ACRE2 is unable to copy the TeamSpeak 3 plugin due to it being in use. Please close any instances of TeamSpeak 3 and click \"Try Again\".\n\nIf you would like to close Arma 3, click Cancel. Press Continue to launch Arma 3 regardless.", "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); - if (result == IDCANCEL) { - TerminateProcess(GetCurrentProcess(), 0); - return; - } else if (result == IDCONTINUE) { - sprintf(output, "[-4,true,%d]", last_error); - return; - } - } else { - // ERROR_ACCESS_DENIED. - const std::string message = "ACRE2 was unable to remove an old version of the TeamSpeak 3 plugin. You have two options:\n\n1) Manually delete the following file: \n" + file + "\n\n2) Restart Steam and Arma 3 as administrator (right click on the shortcut -> run as administrator) and relaunch Arma 3 with ACRE2 loaded. \n\nWould you like to run Arma 3 anyway?"; - const int32_t result = MessageBoxA(nullptr, (LPCSTR)message.c_str(), "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); - if (result == IDNO) { - TerminateProcess(GetCurrentProcess(), 0); - return; - } else { //result is yes continue - sprintf(output, "[-5,true,%d]", last_error); - return; - } - } - } else { - // The dll was already removed, exit the loop. - try_delete = false; - } - } else { - // Successfully deleted the dll. - updateRequired = true; - try_delete = false; - if (!popupLocationNotify) { - // Prevent the location from being outputted to the pop-up twice. - remove_paths += location + "\n"; - popupLocationNotify = true; - } - } - } while (try_delete); - } - } + const idi::acre::Update_code update_ts3 = ts3_plugin.handle_update_plugin(); + std::string error_msg; + const bool update_ts3_ok = (update_ts3 != idi::acre::Update_code::update_failed) && (update_ts3 != idi::acre::Update_code::other); + if (!update_ts3_ok) { + error_msg = ts3_plugin.get_last_error_message(); + } + const idi::acre::Update_code update_mumble = mumble_plugin.handle_update_plugin(); + const bool update_mumble_ok = + (update_mumble != idi::acre::Update_code::update_failed) && (update_mumble != idi::acre::Update_code::other); + if (!update_mumble_ok) { + error_msg = mumble_plugin.get_last_error_message(); + } - if (!updateRequired) { // No update was copied etc. - strncpy(output, "[0]", outputSize); + if (!update_ts3_ok || !update_mumble_ok) { + std::ostringstream oss; + oss << "ACRE2 was unable to copy the TeamSpeak 3 plugin. Please check if you have write access to the plugin folder, " + << "close any instances of TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you would like to close Arma 3 " + << "click Cancel. Press Continue to launch Arma 3 regardless.\n\n" + << error_msg; + const int32_t result = + MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); + if (result == IDCANCEL) { + TerminateProcess(GetCurrentProcess(), 0); + return; + } else if (result == IDCONTINUE) { + sprintf(output, "[-4,true,%d %d]", ts3_plugin.get_last_error(), mumble_plugin.get_last_error()); return; } + } - std::stringstream ss; - ss << "A new version of ACRE2 (" << current_version << ") has been installed!\n"; - ss << "\n"; - if (found_paths != "") { - ss << "The TeamSpeak 3 plugins have been copied to the following location(s):\n" << found_paths; - ss << "\n"; - } - if (remove_paths != "") { - ss << "The TeamSpeak 3 plugin has been removed from the following location(s):\n" << remove_paths << "\n"; - if (found_paths == "") { - ss << "An update to version is already in:\n" << unique_ts_locations.at(0) << "\n"; - ss << "\n"; - } - } - ss << "If this is NOT valid, please uninstall all versions of TeamSpeak 3 and reinstall both it and ACRE2 or copy the plugins manually to your correct installation.\n"; - ss << "\n"; - ss << "If this appears to be the correct folder(s) please remember to enable the plugin in TeamSpeak 3!"; - const int32_t result = MessageBoxA(nullptr, (LPCSTR)ss.str().c_str(), "ACRE2 Installation Success", MB_OK | MB_ICONINFORMATION); - - sprintf(output, "[1,\"%s\"]", found_paths.c_str()); + // Update was not necessary. + if ((update_ts3 == idi::acre::Update_code::update_not_necessary) && + (update_mumble == idi::acre::Update_code::update_not_necessary)) { // No update was copied etc. + strncpy(output, "[0]", outputSize); return; } - default: - return; - } -} + std::ostringstream oss; + oss << "A new version of ACRE2 (" << current_version << ") has been installed!\n\n"; + std::string found_paths; + if (!ts3_plugin.get_updated_paths().empty()) { + oss << "The TeamSpeak 3 plugins have been copied to the following location(s):\n"; + for (const auto &path : ts3_plugin.get_updated_paths()) { + oss << path << "\n"; + found_paths.append(path + "\n"); + } + } + if (!mumble_plugin.get_updated_paths().empty()) { + oss << "The Mumble plugins have been copied to the following location(s):\n"; + for (const auto &path : mumble_plugin.get_updated_paths()) { + oss << path << "\n"; + found_paths.append(path + "\n"); + } + } -void Init(void) { + if (!ts3_plugin.get_removed_paths().empty()) { + oss << "The TeamSpeak 3 plugin has been removed from the following location(s):\n"; + for (const auto &path : ts3_plugin.get_removed_paths()) { + oss << path << "\n"; + } + } -} + if (!mumble_plugin.get_removed_paths().empty()) { + oss << "The Mumble plugin has been removed from the following location(s):\n"; + for (const auto &path : mumble_plugin.get_removed_paths()) { + oss << path << "\n"; + } + } -void Cleanup(void) { + oss << "If this is NOT valid, please uninstall all versions of TeamSpeak 3 and reinstall both it and ACRE2 or copy the plugins " + << "manually to your correct installation.\n\n"; + oss << "If this appears to be the correct folder(s) please remember to enable the plugin in TeamSpeak 3 and/or Mumble!"; + const int32_t result = MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Success", MB_OK | MB_ICONINFORMATION); + sprintf(output, "[1,\"%s\"]", found_paths.c_str()); + return; + } + default: + return; + } } +void Init(void) {} + +void Cleanup(void) {} -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - switch (ul_reason_for_call) - { +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: Init(); break; diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp new file mode 100644 index 000000000..e882b4504 --- /dev/null +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -0,0 +1,61 @@ +/** + * @author Ferran Obón Santacana (Magnetar) + * + * @copyright Copyright (c) 2020 International Development & Integration Systems LLC + * + * Mumble auto-plugin copy functionality. + */ +#pragma once +#include "voip_base_class.hpp" + +#include +#include +#include +#include + + +namespace idi::acre { + class Mumble_plugin final : public VOIP_server { + public: + explicit Mumble_plugin(bool skip_plugin_, std::string mumble_path_ = "") noexcept + : VOIP_server(skip_plugin_, "SOFTWARE\\Mumble\\Mumble", "plugin/acre2_win32.dll", "plugin/acre2_win64.dll"), + mumble_path(std::move(mumble_path_)) {} + ~Mumble_plugin() noexcept final = default; + + bool collect_plugin_locations() noexcept final { + if (get_skip_plugin()) { + return true; + } + + if (!mumble_path.empty()) { + check_plugin_locations(mumble_path); + } else { + std::array folder_ids = {FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64}; + for (const auto folder : folder_ids) { + wchar_t *app_data_roaming = nullptr; + SHGetKnownFolderPath(folder, 0, nullptr, &app_data_roaming); + + if (app_data_roaming == nullptr) { + return false; + } + + // TODO: Substitude it with WideCharToMultiByte from "Windows.h" + std::wstring_convert> conv; + std::string app_data = conv.to_bytes(app_data_roaming); + + app_data.append("\\Mumble"); + check_plugin_locations(app_data); + + // Now do the same for x64 + CoTaskMemFree(app_data_roaming); // Free it up. + } + } + + // No locations to copy to. + return !get_plugin_locations().empty(); + } + + private: + std::string mumble_path; + }; +} // namespace idi::acre \ No newline at end of file diff --git a/extensions/src/ACRE2Steam/ts3_plugin.hpp b/extensions/src/ACRE2Steam/ts3_plugin.hpp new file mode 100644 index 000000000..5f6674591 --- /dev/null +++ b/extensions/src/ACRE2Steam/ts3_plugin.hpp @@ -0,0 +1,72 @@ +/** + * @author Ferran Obón Santacana (Magnetar) + * @author Cliff Foster (Nou) + * @author James Smith (Snippers) + * + * @copyright Copyright (c) 2020 International Development & Integration Systems LLC + * + * TeamSpeak 3 auto-plugin copy functionality. + */ +#include "voip_base_class.hpp" + +#include +#include +#include + + +namespace idi::acre { + class TS3_plugin final : public VOIP_server { + public: + explicit TS3_plugin(bool skip_plugin_) noexcept + : VOIP_server(skip_plugin_, "SOFTWARE\\TeamSpeak 3 Client", "plugin/acre2_win32.dll", "plugin/acre2_win64.dll") {} + ~TS3_plugin() noexcept final = default; + + bool collect_plugin_locations() noexcept final { + if (get_skip_plugin()) { + return true; + } + + // Teamspeak 3 location - Default location - Roaming Appdata. + wchar_t *app_data_roaming = nullptr; + SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &app_data_roaming); + + if (app_data_roaming == nullptr) { + return false; + } + + // TODO: Substitude it with WideCharToMultiByte from "Windows.h" + std::wstring_convert> conv; + std::string app_data = conv.to_bytes(app_data_roaming); + + app_data.append("\\TS3Client"); + CoTaskMemFree(app_data_roaming); // Free it up. + + // 32 Bit - Machine + std::string rootkey = read_reg_value(HKEY_LOCAL_MACHINE, get_registry_key().c_str(), "", false); + check_plugin_locations(app_data, rootkey, HKEY_LOCAL_MACHINE); + + // 64 Bit - Machine + rootkey = read_reg_value(HKEY_LOCAL_MACHINE, get_registry_key().c_str(), "", true); + check_plugin_locations(app_data, rootkey, HKEY_LOCAL_MACHINE); + + // 32 Bit - User + rootkey = read_reg_value(HKEY_CURRENT_USER, get_registry_key().c_str(), "", false); + check_plugin_locations(app_data, rootkey, HKEY_CURRENT_USER); + + // 64 Bit - User + rootkey = read_reg_value(HKEY_CURRENT_USER, get_registry_key().c_str(), "", true); + check_plugin_locations(app_data, rootkey, HKEY_CURRENT_USER); + + // Do not delete if we need to copy it + std::vector ts3_locations = get_plugin_locations(); + std::vector ts3_delete_locations = get_plugin_delete_locations(); + + for (const auto &location : ts3_locations) { + (void) std::remove(ts3_delete_locations.begin(), ts3_delete_locations.end(), location); + } + + // No locations to copy to. + return !get_plugin_locations().empty(); + } + }; +} // namespace idi::acre \ No newline at end of file diff --git a/extensions/src/ACRE2Steam/voip_base_class.cpp b/extensions/src/ACRE2Steam/voip_base_class.cpp new file mode 100644 index 000000000..130fc433d --- /dev/null +++ b/extensions/src/ACRE2Steam/voip_base_class.cpp @@ -0,0 +1,192 @@ +/** + * @author Ferran Obón Santacana (Magnetar) + * @author Cliff Foster (Nou) + * @author James Smith (Snippers) + * + * @copyright Copyright (c) 2020 International Development & Integration Systems LLC + * + * Voice over IP auto-plugin copy functionality. + */ + +#include "voip_base_class.hpp" + +#include +#include +#include +#include + +using ::idi::acre::VOIP_server; + +std::string VOIP_server::read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, const bool use_x64_) noexcept { + REGSAM sam_key; + + if (use_x64_) { + sam_key = KEY_READ | KEY_WOW64_64KEY; + } else { + sam_key = KEY_READ; + } + + HKEY hkey; + if (RegOpenKeyExA(root_, key_.c_str(), 0, sam_key, &hkey) != ERROR_SUCCESS) { + return ""; + } + + DWORD type; + DWORD cbData; + if (RegQueryValueExA(hkey, name_.c_str(), nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { + RegCloseKey(hkey); + return ""; + } + + if (type != REG_SZ) { + RegCloseKey(hkey); + return ""; + } + + std::string value(cbData / sizeof(char), '\0'); + if (RegQueryValueExA(hkey, name_.c_str(), nullptr, nullptr, reinterpret_cast(&value[0]), &cbData) != ERROR_SUCCESS) { + RegCloseKey(hkey); + return ""; + } + + RegCloseKey(hkey); + + size_t firstNull = value.find_first_of('\0'); + if (firstNull != std::string::npos) { + value.resize(firstNull); + } + + return value; +} + +bool VOIP_server::compare_file(const std::string &path_a_, const std::string &path_b_) noexcept { + // Open both files ath the end to check their size + std::ifstream fileA(path_a_, std::ifstream::ate | std::ifstream::binary); + std::ifstream fileB(path_b_, std::ifstream::ate | std::ifstream::binary); + + if (fileA.tellg() != fileB.tellg()) { + return false; + } + + // Files are of the same size. Rewind and compare file contents + fileA.seekg(0); + fileB.seekg(0); + + std::istreambuf_iterator beginA(fileA); + std::istreambuf_iterator beginB(fileB); + + return std::equal(beginA, std::istreambuf_iterator(), beginB); +} + +void VOIP_server::check_plugin_locations(const std::string &app_data_) noexcept { + if (std::filesystem::exists(app_data_)) { + plugin_locations.emplace_back(app_data_); + } +} + +void VOIP_server::check_plugin_locations(const std::string &app_data_, const std::string &root_key_, const HKEY key_) noexcept { + if (root_key_.empty()) { + return; + } + + const std::string config_location = read_reg_value(key_, registry_key, "ConfigLocation", true); + if (config_location == "0") { + if (plugin_locations.end() == std::find(plugin_locations.cbegin(), plugin_locations.cend(), app_data_)) { + plugin_locations.push_back(app_data_); + } + + if (plugin_delete_locations.end() == std::find(plugin_delete_locations.cbegin(), plugin_delete_locations.cend(), root_key_)) { + plugin_delete_locations.push_back(root_key_); + } + } else { + if (plugin_locations.end() == std::find(plugin_locations.cbegin(), plugin_locations.cend(), root_key_)) { + plugin_locations.push_back(root_key_); + } + + if (plugin_delete_locations.end() == + std::find(plugin_delete_locations.cbegin(), plugin_delete_locations.cend(), root_key_ + "/config")) { + plugin_delete_locations.push_back(root_key_ + "/config"); + } + } +} + +bool VOIP_server::check_acre_installation() noexcept { + const bool x32_plugin_exist = std::filesystem::exists(x32_acre_plugin); + const bool x64_plugin_exist = std::filesystem::exists(x64_acre_plugin); + + if (!x32_plugin_exist) { + missing_acre_plugins.emplace_back(x32_acre_plugin.filename().string()); + } + + if (!x64_plugin_exist) { + missing_acre_plugins.emplace_back(x64_acre_plugin.filename().string()); + } + + return x32_plugin_exist && x64_plugin_exist; +} + +idi::acre::Update_code VOIP_server::handle_update_plugin() noexcept { + if (skip_plugin) { + return Update_code::update_not_necessary; + } + + Update_code update_status = Update_code::update_not_necessary; + + for (const auto &location : plugin_locations) { + std::filesystem::path plugin_folder(location + "/plugins"); + + std::error_code err_code; + if (!std::filesystem::exists(plugin_folder) && !std::filesystem::create_directory(plugin_folder, err_code)) { + last_error_msg.append(err_code.message()); + last_error = err_code; + + return Update_code::other; + } + + std::array, 2> plugin_paths_array = { + std::make_pair(plugin_folder / "acre2_win32.dll", x32_acre_plugin), + std::make_pair(plugin_folder / "acre2_win64.dll", x64_acre_plugin)}; + + for (const auto &path : plugin_paths_array) { + if (!compare_file(path.first.string(), path.second.string())) { + bool copy_ok = + std::filesystem::copy_file(path.second, path.first, std::filesystem::copy_options::overwrite_existing, err_code); + if (!copy_ok) { + last_error_msg.append(err_code.message()); + last_error = err_code; + + return Update_code::update_failed; + } + + updated_paths.emplace_back(location); + update_status = Update_code::update_ok; + } + } + } + + for (const auto &location : plugin_delete_locations) { + std::filesystem::path plugin_folder(location + "plugins"); + + if (!std::filesystem::exists(plugin_folder)) { + continue; + } + + std::array plugin_paths_array = {plugin_folder / "acre2_win32.dll", plugin_folder / "acre2_win64.dll"}; + + for (const auto &path : plugin_paths_array) { + std::error_code err_code; + bool remove_ok = std::filesystem::remove(path, err_code); + if (!remove_ok) { + last_error_msg.append(err_code.message()); + last_error = err_code; + + return Update_code::update_failed; + } + + removed_paths.emplace_back(location); + update_status = Update_code::update_ok; + } + } + + return update_status; +} \ No newline at end of file diff --git a/extensions/src/ACRE2Steam/voip_base_class.hpp b/extensions/src/ACRE2Steam/voip_base_class.hpp new file mode 100644 index 000000000..f5be995c1 --- /dev/null +++ b/extensions/src/ACRE2Steam/voip_base_class.hpp @@ -0,0 +1,86 @@ +/** + * @author Ferran Obón Santacana (Magnetar) + * @author Cliff Foster (Nou) + * @author James Smith (Snippers) + * + * + * @copyright Copyright (c) 2020 International Development & Integration Systems LLC + * + * Voice over IP auto-plugin copy functionality. + */ +#pragma once + +#include "Shlwapi.h" +#include "shlobj.h" + +#include +#include +#include + + +namespace idi::acre { + + enum class Update_code : std::uint8_t { update_not_necessary, update_ok, update_failed, other }; + + class VOIP_server { + public: + explicit VOIP_server(bool skip_plugin_, + std::string registry_key_, + const std::string &x32_plugin_path_, + const std::string &x64_plugin_path_) noexcept + : skip_plugin(skip_plugin_), registry_key(std::move(registry_key_)), x32_acre_plugin(x32_plugin_path_), + x64_acre_plugin(x64_plugin_path_) {} + + virtual ~VOIP_server() noexcept = default; + + bool check_acre_installation() noexcept; + + std::string get_registry_key() const noexcept { return registry_key; } + + const std::string &get_last_error_message() const noexcept { return last_error_msg; } + std::int32_t get_last_error() const noexcept { return last_error.value(); } + + const std::vector &get_missing_acre_plugins() const noexcept { return missing_acre_plugins; } + + virtual bool collect_plugin_locations() noexcept = 0; + + Update_code handle_update_plugin() noexcept; + + const std::vector &get_updated_paths() const noexcept { return updated_paths; } + const std::vector &get_removed_paths() const noexcept { return removed_paths; } + + std::string read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, bool use_x64_) noexcept; + + protected: + bool get_skip_plugin() const noexcept { return skip_plugin; } + + + + bool compare_file(const std::string &path_a_, const std::string &path_b_) noexcept; + + void check_plugin_locations(const std::string &app_data_) noexcept; + void check_plugin_locations(const std::string &appData, const std::string &rootkey, const HKEY key) noexcept; + + std::vector &get_plugin_locations() noexcept { return plugin_locations; } + void set_plugin_locations(const std::vector locations_) { plugin_locations = locations_; } + + std::vector &get_plugin_delete_locations() noexcept { return plugin_delete_locations; } + void set_plugin_delete_locations(const std::vector locations_) { plugin_delete_locations = locations_; } + + private: + bool skip_plugin = false; + std::string registry_key; + std::string last_error_msg; + std::error_code last_error; + + std::vector plugin_locations; // Locations to copy the TS dll to. + std::vector plugin_delete_locations; // Locations to remove the TS dll from. + + std::vector updated_paths; + std::vector removed_paths; + + std::filesystem::path x32_acre_plugin; + std::filesystem::path x64_acre_plugin; + std::vector missing_acre_plugins; + }; +} // namespace idi::acre \ No newline at end of file From e23c0d8e58b0b08cc6a1160a1a316554e0daca2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Thu, 14 May 2020 22:08:56 +0200 Subject: [PATCH 016/104] Fix paths --- extensions/src/ACRE2Steam/mumble_plugin.hpp | 4 +- extensions/src/ACRE2Steam/ts3_plugin.hpp | 4 +- extensions/src/ACRE2Steam/voip_base_class.cpp | 46 ++++++++++++++++++- extensions/src/ACRE2Steam/voip_base_class.hpp | 11 +++-- extensions/src/ACRE2TS/CMakeLists.txt | 2 +- 5 files changed, 58 insertions(+), 9 deletions(-) diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index e882b4504..d81e1b057 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -18,7 +18,7 @@ namespace idi::acre { class Mumble_plugin final : public VOIP_server { public: explicit Mumble_plugin(bool skip_plugin_, std::string mumble_path_ = "") noexcept - : VOIP_server(skip_plugin_, "SOFTWARE\\Mumble\\Mumble", "plugin/acre2_win32.dll", "plugin/acre2_win64.dll"), + : VOIP_server(skip_plugin_, "SOFTWARE\\Mumble\\Mumble", find_mod_file("plugin/mumble/acre2_win32.dll"), find_mod_file("plugin/mumble/acre2_win64.dll")), mumble_path(std::move(mumble_path_)) {} ~Mumble_plugin() noexcept final = default; @@ -58,4 +58,4 @@ namespace idi::acre { private: std::string mumble_path; }; -} // namespace idi::acre \ No newline at end of file +} // namespace idi::acre diff --git a/extensions/src/ACRE2Steam/ts3_plugin.hpp b/extensions/src/ACRE2Steam/ts3_plugin.hpp index 5f6674591..5ab9f1077 100644 --- a/extensions/src/ACRE2Steam/ts3_plugin.hpp +++ b/extensions/src/ACRE2Steam/ts3_plugin.hpp @@ -18,7 +18,7 @@ namespace idi::acre { class TS3_plugin final : public VOIP_server { public: explicit TS3_plugin(bool skip_plugin_) noexcept - : VOIP_server(skip_plugin_, "SOFTWARE\\TeamSpeak 3 Client", "plugin/acre2_win32.dll", "plugin/acre2_win64.dll") {} + : VOIP_server(skip_plugin_, "SOFTWARE\\TeamSpeak 3 Client", find_mod_file("plugin/ts3/acre2_win32.dll"), find_mod_file("plugin/ts3/acre2_win64.dll")) {} ~TS3_plugin() noexcept final = default; bool collect_plugin_locations() noexcept final { @@ -69,4 +69,4 @@ namespace idi::acre { return !get_plugin_locations().empty(); } }; -} // namespace idi::acre \ No newline at end of file +} // namespace idi::acre diff --git a/extensions/src/ACRE2Steam/voip_base_class.cpp b/extensions/src/ACRE2Steam/voip_base_class.cpp index 130fc433d..755ad6a20 100644 --- a/extensions/src/ACRE2Steam/voip_base_class.cpp +++ b/extensions/src/ACRE2Steam/voip_base_class.cpp @@ -17,6 +17,50 @@ using ::idi::acre::VOIP_server; +std::string idi::acre::find_mod_folder() { + char module_path[MAX_PATH]; + GetModuleFileNameA((HINSTANCE)&__ImageBase, module_path, MAX_PATH); + + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + + _splitpath( + module_path, + drive, + dir, + NULL, + NULL + ); + + return (std::string(drive) + std::string(dir)); +} + +std::string idi::acre::find_mod_file(const std::string& filename) { + std::string path = find_mod_folder() + filename; + if (!PathFileExistsA(path.c_str())) { + // No mod path was set, it means they used the mod config. It *DOES* mean it relative to a folder in our path at least. + // So, we just search all the local folders + + WIN32_FIND_DATAA data; + std::string path(""); + HANDLE hFile = FindFirstFileA(path.c_str(), &data); + + if (hFile == INVALID_HANDLE_VALUE) + return ""; + + while ((FindNextFile(hFile, &data) != 0) || (GetLastError() != ERROR_NO_MORE_FILES)) { + if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + const std::string fullpath = std::string(data.cFileName) + filename; + if (PathFileExistsA(fullpath.c_str())) { + path = fullpath; + break; + } + } + } + } + return path; +} + std::string VOIP_server::read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, const bool use_x64_) noexcept { REGSAM sam_key; @@ -189,4 +233,4 @@ idi::acre::Update_code VOIP_server::handle_update_plugin() noexcept { } return update_status; -} \ No newline at end of file +} diff --git a/extensions/src/ACRE2Steam/voip_base_class.hpp b/extensions/src/ACRE2Steam/voip_base_class.hpp index f5be995c1..188775577 100644 --- a/extensions/src/ACRE2Steam/voip_base_class.hpp +++ b/extensions/src/ACRE2Steam/voip_base_class.hpp @@ -20,6 +20,12 @@ namespace idi::acre { + EXTERN_C IMAGE_DOS_HEADER __ImageBase; + + std::string find_mod_folder(); + + std::string find_mod_file(const std::string& filename); + enum class Update_code : std::uint8_t { update_not_necessary, update_ok, update_failed, other }; class VOIP_server { @@ -52,9 +58,8 @@ namespace idi::acre { std::string read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, bool use_x64_) noexcept; protected: - bool get_skip_plugin() const noexcept { return skip_plugin; } - + bool get_skip_plugin() const noexcept { return skip_plugin; } bool compare_file(const std::string &path_a_, const std::string &path_b_) noexcept; @@ -83,4 +88,4 @@ namespace idi::acre { std::filesystem::path x64_acre_plugin; std::vector missing_acre_plugins; }; -} // namespace idi::acre \ No newline at end of file +} // namespace idi::acre diff --git a/extensions/src/ACRE2TS/CMakeLists.txt b/extensions/src/ACRE2TS/CMakeLists.txt index 3623f1b99..bfbb0e4c0 100644 --- a/extensions/src/ACRE2TS/CMakeLists.txt +++ b/extensions/src/ACRE2TS/CMakeLists.txt @@ -25,7 +25,7 @@ endif() add_custom_command(TARGET ${ACRE_NAME} POST_BUILD # Copy DLL to plugins - COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_SOURCE_DIR}/../plugin/${FINAL_DLL_NAME} + COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_SOURCE_DIR}/../plugin/ts3/${FINAL_DLL_NAME} # Copy PDB to symbols COMMAND ${CMAKE_COMMAND} -E copy $/${ACRE_NAME}.pdb ${PROJECT_SOURCE_DIR}/../symbols/${ACRE_ARCH}/${ACRE_NAME}.pdb ) From 55b61e4acf90b7afeba089a686c271057714dc0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Thu, 14 May 2020 22:16:11 +0200 Subject: [PATCH 017/104] Use more c++17 --- extensions/src/ACRE2Steam/voip_base_class.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/extensions/src/ACRE2Steam/voip_base_class.cpp b/extensions/src/ACRE2Steam/voip_base_class.cpp index 755ad6a20..f1fbefe3a 100644 --- a/extensions/src/ACRE2Steam/voip_base_class.cpp +++ b/extensions/src/ACRE2Steam/voip_base_class.cpp @@ -28,8 +28,8 @@ std::string idi::acre::find_mod_folder() { module_path, drive, dir, - NULL, - NULL + nullptr, + nullptr ); return (std::string(drive) + std::string(dir)); @@ -37,7 +37,7 @@ std::string idi::acre::find_mod_folder() { std::string idi::acre::find_mod_file(const std::string& filename) { std::string path = find_mod_folder() + filename; - if (!PathFileExistsA(path.c_str())) { + if (!std::filesystem::exists(path)) { // No mod path was set, it means they used the mod config. It *DOES* mean it relative to a folder in our path at least. // So, we just search all the local folders @@ -45,13 +45,14 @@ std::string idi::acre::find_mod_file(const std::string& filename) { std::string path(""); HANDLE hFile = FindFirstFileA(path.c_str(), &data); - if (hFile == INVALID_HANDLE_VALUE) + if (hFile == INVALID_HANDLE_VALUE) { return ""; + } while ((FindNextFile(hFile, &data) != 0) || (GetLastError() != ERROR_NO_MORE_FILES)) { if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { const std::string fullpath = std::string(data.cFileName) + filename; - if (PathFileExistsA(fullpath.c_str())) { + if (std::filesystem::exists(fullpath)) { path = fullpath; break; } From d437636f80386e72829313954c9f5d32572f6e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Fri, 15 May 2020 21:11:26 +0200 Subject: [PATCH 018/104] Renamed classes --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 14 ++++----- extensions/src/ACRE2Steam/mumble_plugin.hpp | 6 ++-- extensions/src/ACRE2Steam/ts3_plugin.hpp | 10 +++---- .../{voip_base_class.cpp => voip_plugin.cpp} | 30 +++++++++---------- .../{voip_base_class.hpp => voip_plugin.hpp} | 10 +++---- 5 files changed, 35 insertions(+), 35 deletions(-) rename extensions/src/ACRE2Steam/{voip_base_class.cpp => voip_plugin.cpp} (87%) rename extensions/src/ACRE2Steam/{voip_base_class.hpp => voip_plugin.hpp} (92%) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index a4309fe4f..4c9e21f48 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -101,7 +101,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { const bool skip_ts_plugin = skip_ts_plugin_copy(); const bool skip_mumble_plugin = skip_mumble_plugin_copy(); - idi::acre::TS3_plugin ts3_plugin(skip_ts_plugin); + idi::acre::TS3Plugin ts3_plugin(skip_ts_plugin); idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, mumble_install_path()); switch (command) { @@ -161,16 +161,16 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { return; } - const idi::acre::Update_code update_ts3 = ts3_plugin.handle_update_plugin(); + const idi::acre::UpdateCode update_ts3 = ts3_plugin.handle_update_plugin(); std::string error_msg; - const bool update_ts3_ok = (update_ts3 != idi::acre::Update_code::update_failed) && (update_ts3 != idi::acre::Update_code::other); + const bool update_ts3_ok = (update_ts3 != idi::acre::UpdateCode::update_failed) && (update_ts3 != idi::acre::UpdateCode::other); if (!update_ts3_ok) { error_msg = ts3_plugin.get_last_error_message(); } - const idi::acre::Update_code update_mumble = mumble_plugin.handle_update_plugin(); + const idi::acre::UpdateCode update_mumble = mumble_plugin.handle_update_plugin(); const bool update_mumble_ok = - (update_mumble != idi::acre::Update_code::update_failed) && (update_mumble != idi::acre::Update_code::other); + (update_mumble != idi::acre::UpdateCode::update_failed) && (update_mumble != idi::acre::UpdateCode::other); if (!update_mumble_ok) { error_msg = mumble_plugin.get_last_error_message(); } @@ -193,8 +193,8 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { } // Update was not necessary. - if ((update_ts3 == idi::acre::Update_code::update_not_necessary) && - (update_mumble == idi::acre::Update_code::update_not_necessary)) { // No update was copied etc. + if ((update_ts3 == idi::acre::UpdateCode::update_not_necessary) && + (update_mumble == idi::acre::UpdateCode::update_not_necessary)) { // No update was copied etc. strncpy(output, "[0]", outputSize); return; } diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index d81e1b057..8a58cf1ce 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -6,7 +6,7 @@ * Mumble auto-plugin copy functionality. */ #pragma once -#include "voip_base_class.hpp" +#include "voip_plugin.hpp" #include #include @@ -15,10 +15,10 @@ namespace idi::acre { - class Mumble_plugin final : public VOIP_server { + class Mumble_plugin final : public VOIPPlugin { public: explicit Mumble_plugin(bool skip_plugin_, std::string mumble_path_ = "") noexcept - : VOIP_server(skip_plugin_, "SOFTWARE\\Mumble\\Mumble", find_mod_file("plugin/mumble/acre2_win32.dll"), find_mod_file("plugin/mumble/acre2_win64.dll")), + : VOIPPlugin(skip_plugin_, "SOFTWARE\\Mumble\\Mumble", find_mod_file("plugin/mumble/acre2_win32.dll"), find_mod_file("plugin/mumble/acre2_win64.dll")), mumble_path(std::move(mumble_path_)) {} ~Mumble_plugin() noexcept final = default; diff --git a/extensions/src/ACRE2Steam/ts3_plugin.hpp b/extensions/src/ACRE2Steam/ts3_plugin.hpp index 5ab9f1077..f6c1c0d0c 100644 --- a/extensions/src/ACRE2Steam/ts3_plugin.hpp +++ b/extensions/src/ACRE2Steam/ts3_plugin.hpp @@ -7,7 +7,7 @@ * * TeamSpeak 3 auto-plugin copy functionality. */ -#include "voip_base_class.hpp" +#include "voip_plugin.hpp" #include #include @@ -15,11 +15,11 @@ namespace idi::acre { - class TS3_plugin final : public VOIP_server { + class TS3Plugin final : public VOIPPlugin { public: - explicit TS3_plugin(bool skip_plugin_) noexcept - : VOIP_server(skip_plugin_, "SOFTWARE\\TeamSpeak 3 Client", find_mod_file("plugin/ts3/acre2_win32.dll"), find_mod_file("plugin/ts3/acre2_win64.dll")) {} - ~TS3_plugin() noexcept final = default; + explicit TS3Plugin(bool skip_plugin_) noexcept + : VOIPPlugin(skip_plugin_, "SOFTWARE\\TeamSpeak 3 Client", find_mod_file("plugin/ts3/acre2_win32.dll"), find_mod_file("plugin/ts3/acre2_win64.dll")) {} + ~TS3Plugin() noexcept final = default; bool collect_plugin_locations() noexcept final { if (get_skip_plugin()) { diff --git a/extensions/src/ACRE2Steam/voip_base_class.cpp b/extensions/src/ACRE2Steam/voip_plugin.cpp similarity index 87% rename from extensions/src/ACRE2Steam/voip_base_class.cpp rename to extensions/src/ACRE2Steam/voip_plugin.cpp index f1fbefe3a..4b1da9c46 100644 --- a/extensions/src/ACRE2Steam/voip_base_class.cpp +++ b/extensions/src/ACRE2Steam/voip_plugin.cpp @@ -8,14 +8,14 @@ * Voice over IP auto-plugin copy functionality. */ -#include "voip_base_class.hpp" +#include "voip_plugin.hpp" #include #include #include #include -using ::idi::acre::VOIP_server; +using ::idi::acre::VOIPPlugin; std::string idi::acre::find_mod_folder() { char module_path[MAX_PATH]; @@ -62,7 +62,7 @@ std::string idi::acre::find_mod_file(const std::string& filename) { return path; } -std::string VOIP_server::read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, const bool use_x64_) noexcept { +std::string VOIPPlugin::read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, const bool use_x64_) noexcept { REGSAM sam_key; if (use_x64_) { @@ -104,7 +104,7 @@ std::string VOIP_server::read_reg_value(HKEY root_, const std::string &key_, con return value; } -bool VOIP_server::compare_file(const std::string &path_a_, const std::string &path_b_) noexcept { +bool VOIPPlugin::compare_file(const std::string &path_a_, const std::string &path_b_) noexcept { // Open both files ath the end to check their size std::ifstream fileA(path_a_, std::ifstream::ate | std::ifstream::binary); std::ifstream fileB(path_b_, std::ifstream::ate | std::ifstream::binary); @@ -123,13 +123,13 @@ bool VOIP_server::compare_file(const std::string &path_a_, const std::string &pa return std::equal(beginA, std::istreambuf_iterator(), beginB); } -void VOIP_server::check_plugin_locations(const std::string &app_data_) noexcept { +void VOIPPlugin::check_plugin_locations(const std::string &app_data_) noexcept { if (std::filesystem::exists(app_data_)) { plugin_locations.emplace_back(app_data_); } } -void VOIP_server::check_plugin_locations(const std::string &app_data_, const std::string &root_key_, const HKEY key_) noexcept { +void VOIPPlugin::check_plugin_locations(const std::string &app_data_, const std::string &root_key_, const HKEY key_) noexcept { if (root_key_.empty()) { return; } @@ -155,7 +155,7 @@ void VOIP_server::check_plugin_locations(const std::string &app_data_, const std } } -bool VOIP_server::check_acre_installation() noexcept { +bool VOIPPlugin::check_acre_installation() noexcept { const bool x32_plugin_exist = std::filesystem::exists(x32_acre_plugin); const bool x64_plugin_exist = std::filesystem::exists(x64_acre_plugin); @@ -170,12 +170,12 @@ bool VOIP_server::check_acre_installation() noexcept { return x32_plugin_exist && x64_plugin_exist; } -idi::acre::Update_code VOIP_server::handle_update_plugin() noexcept { +idi::acre::UpdateCode VOIPPlugin::handle_update_plugin() noexcept { if (skip_plugin) { - return Update_code::update_not_necessary; + return UpdateCode::update_not_necessary; } - Update_code update_status = Update_code::update_not_necessary; + UpdateCode update_status = UpdateCode::update_not_necessary; for (const auto &location : plugin_locations) { std::filesystem::path plugin_folder(location + "/plugins"); @@ -185,7 +185,7 @@ idi::acre::Update_code VOIP_server::handle_update_plugin() noexcept { last_error_msg.append(err_code.message()); last_error = err_code; - return Update_code::other; + return UpdateCode::other; } std::array, 2> plugin_paths_array = { @@ -200,11 +200,11 @@ idi::acre::Update_code VOIP_server::handle_update_plugin() noexcept { last_error_msg.append(err_code.message()); last_error = err_code; - return Update_code::update_failed; + return UpdateCode::update_failed; } updated_paths.emplace_back(location); - update_status = Update_code::update_ok; + update_status = UpdateCode::update_ok; } } } @@ -225,11 +225,11 @@ idi::acre::Update_code VOIP_server::handle_update_plugin() noexcept { last_error_msg.append(err_code.message()); last_error = err_code; - return Update_code::update_failed; + return UpdateCode::update_failed; } removed_paths.emplace_back(location); - update_status = Update_code::update_ok; + update_status = UpdateCode::update_ok; } } diff --git a/extensions/src/ACRE2Steam/voip_base_class.hpp b/extensions/src/ACRE2Steam/voip_plugin.hpp similarity index 92% rename from extensions/src/ACRE2Steam/voip_base_class.hpp rename to extensions/src/ACRE2Steam/voip_plugin.hpp index 188775577..8cb079299 100644 --- a/extensions/src/ACRE2Steam/voip_base_class.hpp +++ b/extensions/src/ACRE2Steam/voip_plugin.hpp @@ -26,18 +26,18 @@ namespace idi::acre { std::string find_mod_file(const std::string& filename); - enum class Update_code : std::uint8_t { update_not_necessary, update_ok, update_failed, other }; + enum class UpdateCode : std::uint8_t { update_not_necessary, update_ok, update_failed, other }; - class VOIP_server { + class VOIPPlugin { public: - explicit VOIP_server(bool skip_plugin_, + explicit VOIPPlugin(bool skip_plugin_, std::string registry_key_, const std::string &x32_plugin_path_, const std::string &x64_plugin_path_) noexcept : skip_plugin(skip_plugin_), registry_key(std::move(registry_key_)), x32_acre_plugin(x32_plugin_path_), x64_acre_plugin(x64_plugin_path_) {} - virtual ~VOIP_server() noexcept = default; + virtual ~VOIPPlugin() noexcept = default; bool check_acre_installation() noexcept; @@ -50,7 +50,7 @@ namespace idi::acre { virtual bool collect_plugin_locations() noexcept = 0; - Update_code handle_update_plugin() noexcept; + UpdateCode handle_update_plugin() noexcept; const std::vector &get_updated_paths() const noexcept { return updated_paths; } const std::vector &get_removed_paths() const noexcept { return removed_paths; } From edcd4dd34b817d1aafc53ab59d2be7a792a92f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sat, 16 May 2020 00:19:39 +0200 Subject: [PATCH 019/104] Channel moving --- extensions/src/ACRE2Core/Engine.cpp | 2 +- extensions/src/ACRE2Core/setSetting.h | 2 +- extensions/src/ACRE2Core/setTs3ChannelDetails.h | 2 +- extensions/src/ACRE2Mumble/MumbleClient.cpp | 6 +++--- extensions/src/ACRE2Shared/IClient.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/src/ACRE2Core/Engine.cpp b/extensions/src/ACRE2Core/Engine.cpp index b9d12f68a..ef9dd3840 100644 --- a/extensions/src/ACRE2Core/Engine.cpp +++ b/extensions/src/ACRE2Core/Engine.cpp @@ -74,7 +74,7 @@ acre::Result CEngine::initialize(IClient *client, IServer *externalServer, std:: this->getRpcEngine()->addProcedure(new updateSelf()); this->getRpcEngine()->addProcedure(new setSelectableVoiceCurve()); this->getRpcEngine()->addProcedure(new setSetting()); - this->getRpcEngine()->addProcedure(new setChannelDetails()); + this->getRpcEngine()->addProcedure(new setTs3ChannelDetails()); // Initialize the client, because it never was derp this->getClient()->initialize(); diff --git a/extensions/src/ACRE2Core/setSetting.h b/extensions/src/ACRE2Core/setSetting.h index 237f87479..6761b3045 100644 --- a/extensions/src/ACRE2Core/setSetting.h +++ b/extensions/src/ACRE2Core/setSetting.h @@ -21,7 +21,7 @@ RPC_FUNCTION(setSetting) { if (CAcreSettings::getInstance()->getDisableUnmuteClients() != (value != 1)) { CAcreSettings::getInstance()->setDisableUnmuteClients(value != 1); } - } else if (name == "disableChannelSwitch") { + } else if (name == "disableTS3ChannelSwitch") { if (CAcreSettings::getInstance()->getDisableChannelSwitch() != (value != 1)) { CAcreSettings::getInstance()->setDisableChannelSwitch(value != 1); } diff --git a/extensions/src/ACRE2Core/setTs3ChannelDetails.h b/extensions/src/ACRE2Core/setTs3ChannelDetails.h index 404312ac1..0beee7911 100644 --- a/extensions/src/ACRE2Core/setTs3ChannelDetails.h +++ b/extensions/src/ACRE2Core/setTs3ChannelDetails.h @@ -7,7 +7,7 @@ #include -RPC_FUNCTION(setChannelDetails) { +RPC_FUNCTION(setTs3ChannelDetails) { const std::vector details = { std::string((char *)vMessage->getParameter(0)), std::string((char *)vMessage->getParameter(1)), diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 7070ee037..1ce77fa6b 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -294,7 +294,7 @@ acre::Result CMumbleClient::unMuteAll( void ) { } acre::Result CMumbleClient::moveToServerChannel() { - + LOG("moveToServerChannel ENTER"); if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { mumble_userid_t clientId; std::vector details = getChannelDetails(); @@ -326,7 +326,7 @@ acre::Result CMumbleClient::moveToServerChannel() { } acre::Result CMumbleClient::moveToPreviousChannel() { - + LOG("moveToPreviousChannel ENTER"); if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { mumble_userid_t clientId = -1; //if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { @@ -348,7 +348,7 @@ acre::Result CMumbleClient::moveToPreviousChannel() { } uint64_t CMumbleClient::findChannelByNames(std::vector details_) { - + LOG("findChannelByNames ENTER"); mumble_channelid_t*channelList = nullptr; std::size_t channelCount = 0U; //if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { diff --git a/extensions/src/ACRE2Shared/IClient.h b/extensions/src/ACRE2Shared/IClient.h index 7898a7bda..2255847f7 100644 --- a/extensions/src/ACRE2Shared/IClient.h +++ b/extensions/src/ACRE2Shared/IClient.h @@ -181,7 +181,7 @@ class IClient { std::uint64_t previous_channel = 0LU; std::vector channel_details; - bool should_switch_channel = false; + bool should_switch_channel = true; acre::State state = acre::State::stopped; }; From 2e7302f1bf2b35ab7c9b9c8b5ed282d1cbd987f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sat, 16 May 2020 00:44:15 +0200 Subject: [PATCH 020/104] Arma3 RPC functions adjustments --- addons/sys_core/initSettings.sqf | 20 +++--- addons/sys_core/stringtable.xml | 68 +++++++++---------- addons/sys_io/XEH_PREP.hpp | 2 +- addons/sys_io/fnc_missionDisplayLoad.sqf | 2 +- addons/sys_io/fnc_server.sqf | 2 +- addons/sys_io/fnc_ts3ChannelMove.sqf | 20 ------ addons/sys_io/fnc_voipChannelMove.sqf | 20 ++++++ extensions/src/ACRE2Core/Engine.cpp | 2 +- .../src/ACRE2Core/setTs3ChannelDetails.h | 2 +- 9 files changed, 69 insertions(+), 69 deletions(-) delete mode 100644 addons/sys_io/fnc_ts3ChannelMove.sqf create mode 100644 addons/sys_io/fnc_voipChannelMove.sqf diff --git a/addons/sys_core/initSettings.sqf b/addons/sys_core/initSettings.sqf index b9f6ab7bf..8c72e87d5 100644 --- a/addons/sys_core/initSettings.sqf +++ b/addons/sys_core/initSettings.sqf @@ -46,38 +46,38 @@ {["disableUnmuteClients", _this] call FUNC(setPluginSetting)} ] call CBA_fnc_addSetting; -// Teamspeak Channel Switching +// Mumble/Teamspeak Channel Switching // Switch channels [ - QGVAR(ts3ChannelSwitch), + QGVAR(voipChannelSwitch), "CHECKBOX", - localize LSTRING(ts3ChannelSwitch_displayName), + localize LSTRING(voipChannelSwitch_displayName), "ACRE2", true, false, - {["disableTS3ChannelSwitch", _this] call FUNC(setPluginSetting)} + {["disablevoipChannelSwitch", _this] call FUNC(setPluginSetting)} ] call CBA_fnc_addSetting; // Channel Name [ - QGVAR(ts3ChannelName), + QGVAR(voipChannelName), "EDITBOX", - localize LSTRING(ts3ChannelName_displayName), + localize LSTRING(voipChannelName_displayName), "ACRE2", "", true, - {if (!isNull (findDisplay 46)) then {call EFUNC(sys_io,ts3ChannelMove)};} + {if (!isNull (findDisplay 46)) then {call EFUNC(sys_io,voipChannelMove)};} ] call CBA_fnc_addSetting; // Channel Password [ - QGVAR(ts3ChannelPassword), + QGVAR(voipChannelPassword), "EDITBOX", - localize LSTRING(ts3ChannelPassword_displayName), + localize LSTRING(voipChannelPassword_displayName), "ACRE2", ["", true], true, - {if (!isNull (findDisplay 46)) then {call EFUNC(sys_io,ts3ChannelMove)};} + {if (!isNull (findDisplay 46)) then {call EFUNC(sys_io,voipChannelMove)};} ] call CBA_fnc_addSetting; // Difficulty settings diff --git a/addons/sys_core/stringtable.xml b/addons/sys_core/stringtable.xml index c32b64256..9566b3ede 100644 --- a/addons/sys_core/stringtable.xml +++ b/addons/sys_core/stringtable.xml @@ -82,45 +82,45 @@ 客户端取消禁音 Desmutar Clientes - - TeamSpeak Channel Switch + + Mumble/TeamSpeak Channel Switch Смена ТимСпик канала - TeamSpeak チャンネル切り替え - Teamspeak頻道切換 - Teamspeak频道切换 + Mumble/TeamSpeak チャンネル切り替え + Mumble/Teamspeak頻道切換 + Mumble/Teamspeak频道切换 팀스피크 채널 변경 - Trocar de Canal do TeamSpeak - Zmiana kanału TeamSpeak - Cambio canale TeamSpeak - Cambio de canal de TeamSpeak - Changer de canal TeamSpeak - TeamSpeak Kanalwechsel - - - TeamSpeak Channel Name - TeamSpeak チャンネル名 - Teamspeak頻道名稱 - Teamspeak频道名称 + Trocar de Canal do Mumble/TeamSpeak + Zmiana kanału Mumble/TeamSpeak + Cambio canale Mumble/TeamSpeak + Cambio de canal de Mumble/TeamSpeak + Changer de canal Mumble/TeamSpeak + Mumble/TeamSpeak Kanalwechsel + + + Mumble/TeamSpeak Channel Name + Mumble/TeamSpeak チャンネル名 + Mumble/Teamspeak頻道名稱 + Mumble/Teamspeak频道名称 팀스피크 채널 이름 - Nome do Canal do TeamSpeak - Nazwa kanału TeamSpeak - Nome canale Teamspeak - Nombre de canal de TeamSpeak - Nom du canal TeamSpeak - TeamSpeak Kanalname + Nome do Canal do Mumble/TeamSpeak + Nazwa kanału Mumble/TeamSpeak + Nome canale Mumble/Teamspeak + Nombre de canal de Mumble/TeamSpeak + Nom du canal Mumble/TeamSpeak + Mumble/TeamSpeak Kanalname Имя ТимСпик канала - - TeamSpeak Channel Password - Teamspeak頻道密碼 - Teamspeak频道密码 - Senha do Canal do TeamSpeak - Hasło kanału TeamSpeak - Password canale Teamspeak - TeamSpeak チャンネルのパスワード - Contraseña del canal de TeamSpeak - Mot de passe du canal TeamSpeak - TeamSpeak Kanalpasswort + + Mumble/TeamSpeak Channel Password + Mumble/Teamspeak頻道密碼 + Mumble/Teamspeak频道密码 + Senha do Canal do Mumble/TeamSpeak + Hasło kanału Mumble/TeamSpeak + Password canale Mumble/Teamspeak + Mumble/TeamSpeak チャンネルのパスワード + Contraseña del canal de Mumble/TeamSpeak + Mot de passe du canal Mumble/TeamSpeak + Mumble/TeamSpeak Kanalpasswort Пароль ТимСпик канала diff --git a/addons/sys_io/XEH_PREP.hpp b/addons/sys_io/XEH_PREP.hpp index f2e9aff20..d58df89b0 100644 --- a/addons/sys_io/XEH_PREP.hpp +++ b/addons/sys_io/XEH_PREP.hpp @@ -4,4 +4,4 @@ PREP(startServer); PREP(serverReadLoop); PREP(server); PREP(ping); -PREP(ts3ChannelMove); +PREP(voipChannelMove); diff --git a/addons/sys_io/fnc_missionDisplayLoad.sqf b/addons/sys_io/fnc_missionDisplayLoad.sqf index 06d353a34..7fab94f11 100644 --- a/addons/sys_io/fnc_missionDisplayLoad.sqf +++ b/addons/sys_io/fnc_missionDisplayLoad.sqf @@ -17,5 +17,5 @@ if (GVAR(serverStarted) && {isMultiplayer}) then { // Move TeamSpeak 3 channel on display 46 (main display) initialization - call FUNC(ts3ChannelMove); + call FUNC(voipChannelMove); }; diff --git a/addons/sys_io/fnc_server.sqf b/addons/sys_io/fnc_server.sqf index a55218efa..c4bb27a59 100644 --- a/addons/sys_io/fnc_server.sqf +++ b/addons/sys_io/fnc_server.sqf @@ -56,7 +56,7 @@ DFUNC(connectionFnc) = { // Move TeamSpeak 3 channel if already in-game (otherwise display XEH will take care of it) if (!isNull (findDisplay 46)) then { - call FUNC(ts3ChannelMove); + call FUNC(voipChannelMove); }; }; }; diff --git a/addons/sys_io/fnc_ts3ChannelMove.sqf b/addons/sys_io/fnc_ts3ChannelMove.sqf deleted file mode 100644 index 2175908e7..000000000 --- a/addons/sys_io/fnc_ts3ChannelMove.sqf +++ /dev/null @@ -1,20 +0,0 @@ -#include "script_component.hpp" -/* - * Author: Tim Beswick - * Sends configured channel name and server name to TS plugin, triggering TeamSpeak 3 channel move. - * - * Arguments: - * None - * - * Return Value: - * None - * - * Example: - * [] call acre_sys_io_fnc_teamspeakChannelCheck - * - * Public: No - */ - -private _ts3ChannelDetails = format ["%1,%2,%3", EGVAR(sys_core,ts3ChannelName), EGVAR(sys_core,ts3ChannelPassword), serverName]; -TRACE_1("Moving TS3 Channel",_ts3ChannelDetails); -CALL_RPC("setTs3ChannelDetails",_ts3ChannelDetails); diff --git a/addons/sys_io/fnc_voipChannelMove.sqf b/addons/sys_io/fnc_voipChannelMove.sqf new file mode 100644 index 000000000..198d62fd2 --- /dev/null +++ b/addons/sys_io/fnc_voipChannelMove.sqf @@ -0,0 +1,20 @@ +#include "script_component.hpp" +/* + * Author: Tim Beswick + * Sends configured channel name and server name to Mumble/TS plugin, triggering Mumble/TeamSpeak 3 channel move. + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * [] call acre_sys_io_fnc_teamspeakChannelCheck + * + * Public: No + */ + +private _channelDetails = format ["%1,%2,%3", EGVAR(sys_core,voipChannelName), EGVAR(sys_core,voipChannelPassword), serverName]; +TRACE_1("Moving Mumble/TS3 Channel",_channelDetails); +CALL_RPC("setChannelDetails",_channelDetails); diff --git a/extensions/src/ACRE2Core/Engine.cpp b/extensions/src/ACRE2Core/Engine.cpp index ef9dd3840..b9d12f68a 100644 --- a/extensions/src/ACRE2Core/Engine.cpp +++ b/extensions/src/ACRE2Core/Engine.cpp @@ -74,7 +74,7 @@ acre::Result CEngine::initialize(IClient *client, IServer *externalServer, std:: this->getRpcEngine()->addProcedure(new updateSelf()); this->getRpcEngine()->addProcedure(new setSelectableVoiceCurve()); this->getRpcEngine()->addProcedure(new setSetting()); - this->getRpcEngine()->addProcedure(new setTs3ChannelDetails()); + this->getRpcEngine()->addProcedure(new setChannelDetails()); // Initialize the client, because it never was derp this->getClient()->initialize(); diff --git a/extensions/src/ACRE2Core/setTs3ChannelDetails.h b/extensions/src/ACRE2Core/setTs3ChannelDetails.h index 0beee7911..404312ac1 100644 --- a/extensions/src/ACRE2Core/setTs3ChannelDetails.h +++ b/extensions/src/ACRE2Core/setTs3ChannelDetails.h @@ -7,7 +7,7 @@ #include -RPC_FUNCTION(setTs3ChannelDetails) { +RPC_FUNCTION(setChannelDetails) { const std::vector details = { std::string((char *)vMessage->getParameter(0)), std::string((char *)vMessage->getParameter(1)), From b87312fe2f0579d3038e21079f1f30be1e11d6da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sat, 16 May 2020 18:31:31 +0200 Subject: [PATCH 021/104] Additional TS strings --- addons/main/script_macros.hpp | 2 +- addons/sys_core/XEH_postInit.sqf | 4 +-- addons/sys_core/XEH_preInit.sqf | 4 +-- addons/sys_core/fnc_coreInitPFH.sqf | 4 +-- addons/sys_core/fnc_cycleLanguage.sqf | 2 +- addons/sys_core/fnc_getAlive.sqf | 4 +-- addons/sys_core/fnc_getClientIdLoop.sqf | 2 +- addons/sys_core/fnc_handleGetClientID.sqf | 32 +++++++++---------- addons/sys_core/fnc_handleGetHeadVector.sqf | 2 +- .../sys_core/fnc_handleGetPluginVersion.sqf | 6 ++-- addons/sys_core/fnc_isMuted.sqf | 2 +- addons/sys_core/fnc_localStartSpeaking.sqf | 2 +- addons/sys_core/fnc_localStopSpeaking.sqf | 2 +- addons/sys_core/fnc_muting.sqf | 23 ++++++------- addons/sys_core/fnc_pong.sqf | 3 +- addons/sys_core/fnc_processDirectSpeaker.sqf | 6 ++-- addons/sys_core/fnc_processRadioSpeaker.sqf | 4 +-- addons/sys_core/fnc_remoteStartSpeaking.sqf | 18 +++++------ addons/sys_core/fnc_remoteStopSpeaking.sqf | 4 +-- addons/sys_core/fnc_setPluginSetting.sqf | 2 +- addons/sys_core/fnc_speaking.sqf | 8 ++--- addons/sys_core/fnc_spectatorOff.sqf | 2 +- addons/sys_core/fnc_spectatorOn.sqf | 2 +- ...3idToPlayer.sqf => fnc_voipIdToPlayer.sqf} | 6 ++-- addons/sys_core/initSettings.sqf | 2 +- .../sys_intercom/fnc_handleBroadcasting.sqf | 2 +- .../fnc_handleIntercomActivation.sqf | 2 +- addons/sys_io/fnc_missionDisplayLoad.sqf | 4 +-- addons/sys_io/fnc_ping.sqf | 4 +-- addons/sys_io/fnc_sendMessage.sqf | 2 +- addons/sys_io/fnc_server.sqf | 4 +-- addons/sys_io/fnc_serverReadLoop.sqf | 2 +- addons/sys_io/fnc_startServer.sqf | 2 +- addons/sys_io/fnc_voipChannelMove.sqf | 2 +- addons/sys_io/stringtable.xml | 16 +++++----- addons/sys_rpc/fnc_addProcedure.sqf | 3 +- addons/sys_rpc/fnc_callRemoteProcedure.sqf | 2 +- addons/sys_rpc/fnc_handleData.sqf | 2 +- addons/sys_server/XEH_postInitServer.sqf | 2 +- addons/sys_server/XEH_preInitServer.sqf | 2 +- addons/sys_server/fnc_setSpectator.sqf | 12 +++---- addons/sys_sounds/fnc_handleLoadedSound.sqf | 3 +- addons/sys_sounds/fnc_loadSound.sqf | 8 ++--- addons/sys_sounds/fnc_playSound.sqf | 2 +- 44 files changed, 114 insertions(+), 110 deletions(-) rename addons/sys_core/{fnc_ts3idToPlayer.sqf => fnc_voipIdToPlayer.sqf} (70%) diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index 0fc03532f..7e6c7268b 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -98,7 +98,7 @@ Antenna Defines #define SCRATCH_GET(radioId, key) ([radioId, key] call EFUNC(sys_data,getScratchData)) #define SCRATCH_GET_DEF(radioId, key, defaultVal) ([radioId, key, defaultVal] call EFUNC(sys_data,getScratchData)) -#define GET_TS3ID(object) (object call { private _ret = (_this getVariable [QGVAR(ts3id), -1]); if (_ret == -1) then { WARNING_1("%1 has no TS3 ID",_this); }; _ret }) +#define GET_VOIPID(object) (object call { private _ret = (_this getVariable [QGVAR(voipId), -1]); if (_ret == -1) then { WARNING_1("%1 has no Mumble/TS3 ID",_this); }; _ret }) #define IS_HASH(hash) (hash isEqualType locationNull && {(type hash) isEqualTo "ACRE_FastHashNamespaceDummy"}) diff --git a/addons/sys_core/XEH_postInit.sqf b/addons/sys_core/XEH_postInit.sqf index 2bd17b389..babe93c1a 100644 --- a/addons/sys_core/XEH_postInit.sqf +++ b/addons/sys_core/XEH_postInit.sqf @@ -5,7 +5,7 @@ if (!hasInterface) exitWith {}; -// Ensure the TeamSpeak plugin handler code is initialized first +// Ensure the Mumble/TeamSpeak plugin handler code is initialized first [] call EFUNC(sys_io,startServer); ["handleGetClientID", FUNC(handleGetClientID)] call EFUNC(sys_rpc,addProcedure); @@ -144,7 +144,7 @@ if (getClientStateNumber < 10) then { // Check before game has started (in brief ["setSoundSystemMasterOverride", [0]] call EFUNC(sys_rpc,callRemoteProcedure); [_this select 1] call CBA_fnc_removePerFrameHandler; } else { - // Keep calling incase ACRE is not connected to TeamSpeak + // Keep calling incase ACRE is not connected to Mumble/TeamSpeak ["setSoundSystemMasterOverride", [1]] call EFUNC(sys_rpc,callRemoteProcedure); }; }, 0, []] call CBA_fnc_addPerFrameHandler; diff --git a/addons/sys_core/XEH_preInit.sqf b/addons/sys_core/XEH_preInit.sqf index 5a73ba3b5..831ba9a28 100644 --- a/addons/sys_core/XEH_preInit.sqf +++ b/addons/sys_core/XEH_preInit.sqf @@ -25,13 +25,13 @@ DGVAR(lowered) = false; DGVAR(muting) = []; DGVAR(speakers) = []; DGVAR(enableDistanceMuting) = true; -DGVAR(ts3id) = -1; +DGVAR(voipId) = -1; DGVAR(keyedMicRadios) = []; DGVAR(keyedRadioIds) = HASH_CREATE; DGVAR(globalVolume) = 1.0; DGVAR(maxVolume) = 1.0; DGVAR(playerList) = []; // Paired array: [TS_ID, Object] -//DGVAR(ts3IdPlayerList) = []; +//DGVAR(voipIdPlayerList) = []; DGVAR(isDeaf) = false; //DGVAR(playerListHash) = HASH_CREATE; DGVAR(spectatorSpeakers) = []; diff --git a/addons/sys_core/fnc_coreInitPFH.sqf b/addons/sys_core/fnc_coreInitPFH.sqf index 17e6d6e00..0a0ed4156 100644 --- a/addons/sys_core/fnc_coreInitPFH.sqf +++ b/addons/sys_core/fnc_coreInitPFH.sqf @@ -19,9 +19,9 @@ if (isNull player) exitWith {}; acre_player = player; -if (!ACRE_MAP_LOADED || {!ACRE_DATA_SYNCED} || {GVAR(ts3id) == -1}) exitWith {}; +if (!ACRE_MAP_LOADED || {!ACRE_DATA_SYNCED} || {GVAR(voipId) == -1}) exitWith {}; -TRACE_1("GOT TS3 ID", GVAR(ts3id)); +TRACE_1("GOT Mumble/TS3 ID", GVAR(voipId)); [] call FUNC(utilityFunction); // OK [] call FUNC(muting); diff --git a/addons/sys_core/fnc_cycleLanguage.sqf b/addons/sys_core/fnc_cycleLanguage.sqf index 07aa901d0..cefbfd4bc 100644 --- a/addons/sys_core/fnc_cycleLanguage.sqf +++ b/addons/sys_core/fnc_cycleLanguage.sqf @@ -28,7 +28,7 @@ if (_numSpokenLanguages > 1) then { [_languageName, "Now speaking", "", 1, EGVAR(sys_list,LanguageColor)] call EFUNC(sys_list,displayHint); [] call FUNC(updateSelf); if (ACRE_LOCAL_SPEAKING) then { - //@TODO: This is an uber hack, should probably be set up as a TS event. + //@TODO: This is an uber hack, should probably be set up as a Mumble/TS event. //Basically we update globally a locally set object variable from the //start speaking event when they cycle languages while talking. acre_player setVariable [QGVAR(languageId), _languageId, true]; diff --git a/addons/sys_core/fnc_getAlive.sqf b/addons/sys_core/fnc_getAlive.sqf index d54978208..59bdfc600 100644 --- a/addons/sys_core/fnc_getAlive.sqf +++ b/addons/sys_core/fnc_getAlive.sqf @@ -24,8 +24,8 @@ if (_unit isEqualTo acre_player) then { }; } else { if (!isNull _unit) then { - private _ts3id = GET_TS3ID(_unit); - if ((alive _unit && {!(_ts3id in ACRE_SPECTATORS_LIST)}) || {(ACRE_IS_SPECTATOR && {!ACRE_MUTE_SPECTATORS} && {_ts3id in ACRE_SPECTATORS_LIST})}) then { + private _voipId = GET_VOIPID(_unit); + if ((alive _unit && {!(_voipId in ACRE_SPECTATORS_LIST)}) || {(ACRE_IS_SPECTATOR && {!ACRE_MUTE_SPECTATORS} && {_voipId in ACRE_SPECTATORS_LIST})}) then { _ret = 1; }; }; diff --git a/addons/sys_core/fnc_getClientIdLoop.sqf b/addons/sys_core/fnc_getClientIdLoop.sqf index f4bd66395..9e7c256f1 100644 --- a/addons/sys_core/fnc_getClientIdLoop.sqf +++ b/addons/sys_core/fnc_getClientIdLoop.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * This function exists to setup the process for sending our object and player ID to other clients to associate with our TeamSpeak ID. + * This function exists to setup the process for sending our object and player ID to other clients to associate with our Mumble/TeamSpeak ID. * * Arguments: * None diff --git a/addons/sys_core/fnc_handleGetClientID.sqf b/addons/sys_core/fnc_handleGetClientID.sqf index 3096e7b43..4739efa0c 100644 --- a/addons/sys_core/fnc_handleGetClientID.sqf +++ b/addons/sys_core/fnc_handleGetClientID.sqf @@ -1,11 +1,11 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handles receipt of TS client ID alongside its objects network ID. + * Handles receipt of Mumble/TS client ID alongside its objects network ID. * * Arguments: - * 0: TS client ID - * 1: Net ID of object for TS client ID + * 0: Mumble/TS client ID + * 1: Net ID of object for Mumble/TS client ID * * Return Value: * Handled @@ -16,47 +16,47 @@ * Public: No */ -params ["_newTs3Id","_netId"]; +params ["_newVoipId", "_netId"]; -_newTs3Id = parseNumber _newTs3Id; +_newVoipId = parseNumber _newVoipId; private _playerObject = objectFromNetId _netId; TRACE_1("got client ID", _this); if (_playerObject == acre_player) then { private _resendSpectator = false; - if (_newTs3Id != GVAR(ts3id)) then { + if (_newVoipId != GVAR(voipId)) then { if (ACRE_IS_SPECTATOR) then { [] call FUNC(spectatorOff); _resendSpectator = true; }; }; - GVAR(ts3id) = _newTs3Id; + GVAR(voipId) = _newVoipId; if (_resendSpectator) then { [] call FUNC(spectatorOn) }; - TRACE_1("SETTING TS3ID",GVAR(ts3id)); + TRACE_1("SETTING VOIPID",GVAR(voipId)); } else { - _playerObject setVariable [QGVAR(ts3id), _newTs3Id, false]; + _playerObject setVariable [QGVAR(voipId), _newVoipId, false]; }; -//Ensure the incoming TS ID is pointing to the correct unit. +// Ensure the incoming Mumble/TS ID is pointing to the correct unit. private _found = false; { - _x params ["_remoteTs3Id","_remoteUser"]; - if (_remoteTs3Id == _newTs3Id) exitWith { + _x params ["_remoteVoipId", "_remoteUser"]; + if (_remoteVoipId == _newVoipId) exitWith { _found = true; if (_playerObject != _remoteUser) then { - GVAR(playerList) set [_forEachIndex, [_newTs3Id, _playerObject]]; + GVAR(playerList) set [_forEachIndex, [_newVoipId, _playerObject]]; //If changed remove. REM(GVAR(speakers),_remoteUser); - REM(GVAR(spectatorSpeakers),_remoteTs3Id); + REM(GVAR(spectatorSpeakers),_remoteVoipId); REM(GVAR(keyedMicRadios),_remoteUser); }; - // Case where objects dont match but we found our TS ID. + // Case where objects dont match but we found our Mumble/TS ID. }; } forEach (GVAR(playerList)); if (!_found) then { - GVAR(playerList) pushBack [_newTs3Id,_playerObject]; + GVAR(playerList) pushBack [_newVoipId,_playerObject]; }; true diff --git a/addons/sys_core/fnc_handleGetHeadVector.sqf b/addons/sys_core/fnc_handleGetHeadVector.sqf index 9d8d4e9b6..f016810b3 100644 --- a/addons/sys_core/fnc_handleGetHeadVector.sqf +++ b/addons/sys_core/fnc_handleGetHeadVector.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Sends the current head direction vector to the TeamSpeak plugin. + * Sends the current head direction vector to the Mumble/TeamSpeak plugin. * * Arguments: * None diff --git a/addons/sys_core/fnc_handleGetPluginVersion.sqf b/addons/sys_core/fnc_handleGetPluginVersion.sqf index 59cd6a1f9..b47822234 100644 --- a/addons/sys_core/fnc_handleGetPluginVersion.sqf +++ b/addons/sys_core/fnc_handleGetPluginVersion.sqf @@ -1,10 +1,10 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handles the return of the current plugin version from TeamSpeak. Displays messages to the player if any of the versions do not match. + * Handles the return of the current plugin version from Mumble/TeamSpeak. Displays messages to the player if any of the versions do not match. * * Arguments: - * 0: TeamSpeak plugin version + * 0: Mumble/TeamSpeak plugin version * * Return Value: * Handled @@ -35,7 +35,7 @@ if (!ACRE_SPIT_VERSION && {!isNil "ACRE_FULL_SERVER_VERSION"}) then { if (_warn) then { ACRE_HAS_WARNED = true; - ERROR_WITH_TITLE_3("Mismatched TeamSpeak plugin or mod versions!","\nTeamSpeak plugin version: %1\nYour version: %2\nServer version: %3",GVAR(pluginVersion),QUOTE(VERSION_STR),ACRE_FULL_SERVER_VERSION); + ERROR_WITH_TITLE_3("Mismatched Mumble/TeamSpeak plugin or mod versions!","\nMumble/TeamSpeak plugin version: %1\nYour version: %2\nServer version: %3",GVAR(pluginVersion),QUOTE(VERSION_STR),ACRE_FULL_SERVER_VERSION); } else { if (ACRE_HAS_WARNED) then { ACRE_HAS_WARNED = false; diff --git a/addons/sys_core/fnc_isMuted.sqf b/addons/sys_core/fnc_isMuted.sqf index 93286bd6b..3e0b8837b 100644 --- a/addons/sys_core/fnc_isMuted.sqf +++ b/addons/sys_core/fnc_isMuted.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * This function determines is used to check if the unit should be muted on TeamSpeak or not. + * This function determines is used to check if the unit should be muted on Mumble/TeamSpeak or not. * * Arguments: * 0: unit diff --git a/addons/sys_core/fnc_localStartSpeaking.sqf b/addons/sys_core/fnc_localStartSpeaking.sqf index fd8e9c5b2..1d52e3e42 100644 --- a/addons/sys_core/fnc_localStartSpeaking.sqf +++ b/addons/sys_core/fnc_localStartSpeaking.sqf @@ -45,7 +45,7 @@ if (!GVAR(fullDuplex) && {ACRE_BROADCASTING_RADIOID != ""}) then { private _unit = _x select 0; if (!isNull _unit && {_unit != acre_player}) then { private _canUnderstand = [_unit] call FUNC(canUnderstand); - private _paramArray = ["r", GET_TS3ID(_unit), !_canUnderstand,1,0,1,0,false,[0,0,0]]; + private _paramArray = ["r", GET_VOIPID(_unit), !_canUnderstand,1,0,1,0,false,[0,0,0]]; CALL_RPC("updateSpeakingData", _paramArray); }; } forEach (_sources select _forEachIndex); diff --git a/addons/sys_core/fnc_localStopSpeaking.sqf b/addons/sys_core/fnc_localStopSpeaking.sqf index 1c52f82bf..47176f314 100644 --- a/addons/sys_core/fnc_localStopSpeaking.sqf +++ b/addons/sys_core/fnc_localStopSpeaking.sqf @@ -29,6 +29,6 @@ if (isNil "ACRE_CustomVolumeControl") then { EGVAR(sys_gui,volumeLevel) call EFUNC(sys_gui,setVoiceCurveLevel); }; -//[str GVAR(ts3id), netId acre_player] call FUNC(remoteStopSpeaking); +//[str GVAR(voipId), netId acre_player] call FUNC(remoteStopSpeaking); true diff --git a/addons/sys_core/fnc_muting.sqf b/addons/sys_core/fnc_muting.sqf index 76912e8a3..4bae1f969 100644 --- a/addons/sys_core/fnc_muting.sqf +++ b/addons/sys_core/fnc_muting.sqf @@ -1,7 +1,8 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Sets up the per frame event handler to mute and unmute clients on TeamSpeak. The muting occurs to optimize TeamSpeak bandwidth as voice data is not sent for muted clients. + * Sets up the per frame event handler to mute and unmute clients on Mumble/TeamSpeak. The muting occurs to optimize Mumble/TeamSpeak + * bandwidth as voice data is not sent for muted clients. * * Arguments: * None @@ -39,15 +40,15 @@ DFUNC(mutingPFHLoop) = { _dynamicPos = positionCameraToWorld [0, 0, 0]; }; { - _x params ["_remoteTs3Id","_remoteUser"]; + _x params ["_remoteVoipId", "_remoteUser"]; if (_remoteUser != acre_player) then { private _muted = 0; - //private _remoteTs3Id = (_remoteUser getVariable QGVAR(ts3id)); - //if (!(isNil "_remoteTs3Id")) then { - if !(_remoteTs3Id in ACRE_SPECTATORS_LIST) then { + //private _remoteVoipId = (_remoteUser getVariable QGVAR(voipId)); + //if (!(isNil "_remoteVoipId")) then { + if !(_remoteVoipId in ACRE_SPECTATORS_LIST) then { private _isRemotePlayerAlive = [_remoteUser] call FUNC(getAlive); if (_isRemotePlayerAlive == 1) then { - //_playerIdList pushBack _remoteTs3Id; + //_playerIdList pushBack _remoteVoipId; // private _radioListRemote = [_remoteUser] call EFUNC(sys_data,getRemoteRadioList); // private _radioListLocal = [] call EFUNC(sys_data,getPlayerRadioList); @@ -61,10 +62,10 @@ DFUNC(mutingPFHLoop) = { }; if (GVAR(fullListTime)) then { - _mutingParams = _mutingParams + format ["%1,%2,", _remoteTs3Id, _muted]; + _mutingParams = _mutingParams + format ["%1,%2,", _remoteVoipId, _muted]; } else { if ((_muted == 0 && {_remoteUser in GVAR(muting)}) || {(_muted == 1 && {!(_remoteUser in GVAR(muting))})}) then { - _mutingParams = _mutingParams + format ["%1,%2,", _remoteTs3Id, _muted]; + _mutingParams = _mutingParams + format ["%1,%2,", _remoteVoipId, _muted]; }; }; }; @@ -82,7 +83,7 @@ DFUNC(mutingPFHLoop) = { }; if !(_newSpectators isEqualTo []) then { { - if (_x != GVAR(ts3id)) then { + if (_x != GVAR(voipId)) then { _mutingParams = _mutingParams + format ["%1,1,", _x]; }; } forEach _newSpectators; @@ -94,7 +95,7 @@ DFUNC(mutingPFHLoop) = { if ((str ACRE_IS_SPECTATOR) != (str GVAR(lastSpectate))) then { if (ACRE_IS_SPECTATOR) then { { - if (_x != GVAR(ts3id)) then { + if (_x != GVAR(voipId)) then { _mutingParams = _mutingParams + format ["%1,0,", _x]; }; } forEach ACRE_SPECTATORS_LIST; @@ -105,7 +106,7 @@ DFUNC(mutingPFHLoop) = { if (ACRE_IS_SPECTATOR && {GVAR(fullListTime)}) then { { - if (_x != GVAR(ts3id)) then { + if (_x != GVAR(voipId)) then { _mutingParams = _mutingParams + format ["%1,0,", _x]; }; } forEach ACRE_SPECTATORS_LIST; diff --git a/addons/sys_core/fnc_pong.sqf b/addons/sys_core/fnc_pong.sqf index 5a801c980..f5eb187c3 100644 --- a/addons/sys_core/fnc_pong.sqf +++ b/addons/sys_core/fnc_pong.sqf @@ -1,7 +1,8 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handler for recieving pong messages from the TeamSpeak plugin. This is called periodically as it provides a simple check to make sure TeamSpeak isis still connected to the game. + * Handler for recieving pong messages from the Mumble/TeamSpeak plugin. This is called periodically as it provides a + * simple check to make sure Mumble/TeamSpeak is still connected to the game. * * Arguments: * None diff --git a/addons/sys_core/fnc_processDirectSpeaker.sqf b/addons/sys_core/fnc_processDirectSpeaker.sqf index 031d40c8d..e4d559817 100644 --- a/addons/sys_core/fnc_processDirectSpeaker.sqf +++ b/addons/sys_core/fnc_processDirectSpeaker.sqf @@ -1,13 +1,13 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Calculates the information required by TeamSpeak for a direct speech speaker. + * Calculates the information required by Mumble/TeamSpeak for a direct speech speaker. * * Arguments: * 0: Unit * * Return Value: - * Parameters to send to TeamSpeak + * Parameters to send to Mumble/TeamSpeak * * Example: * [unit] call acre_sys_core_fnc_processDirectSpeaker @@ -18,7 +18,7 @@ private ["_emitterPos", "_emitterDir"]; params ["_unit"]; -private _id = GET_TS3ID(_unit); +private _id = GET_VOIPID(_unit); private _bothSpectating = false; private _isIntercomAttenuate = false; diff --git a/addons/sys_core/fnc_processRadioSpeaker.sqf b/addons/sys_core/fnc_processRadioSpeaker.sqf index ed498f37b..31909c149 100644 --- a/addons/sys_core/fnc_processRadioSpeaker.sqf +++ b/addons/sys_core/fnc_processRadioSpeaker.sqf @@ -1,14 +1,14 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Calculates the information required by TeamSpeak for a radio speaker. + * Calculates the information required by Mumble/TeamSpeak for a radio speaker. * * Arguments: * 0: Unit to process * 1: List of radio classnames * * Return Value: - * Parameters to send to TeamSpeak + * Parameters to send to Mumble/TeamSpeak * * Example: * [unit,["ACRE_PRC343_ID_1"]] call acre_sys_core_fnc_processRadioSpeaker diff --git a/addons/sys_core/fnc_remoteStartSpeaking.sqf b/addons/sys_core/fnc_remoteStartSpeaking.sqf index efc083160..a5041db25 100644 --- a/addons/sys_core/fnc_remoteStartSpeaking.sqf +++ b/addons/sys_core/fnc_remoteStartSpeaking.sqf @@ -4,7 +4,7 @@ * Handles the event of other (remote) players starting to speaking. * * Arguments: - * 0: TeamSpeak ID of talking player + * 0: Mumble/TeamSpeak ID of talking player * 1: Language ID * 2: Net ID of player object * 3: On radio @@ -33,7 +33,7 @@ CREATE_COUNTER(hearableRadios); // PREP(processRadioSpeaker); TRACE_1("START SPEAKING ENTER", _this); -params ["_speakingId","_languageId","_netId","_onRadio",["_radioId",","]]; +params ["_speakingId", "_languageId", "_netId", "_onRadio", ["_radioId", ","]]; if (!(_speakingId isEqualType 0)) then { _speakingId = parseNumber _speakingId; }; if (!(_languageId isEqualType 0)) then { _languageId = parseNumber _languageId; }; @@ -52,19 +52,19 @@ private _result = false; //Ensure the incoming ID is solid. private _found = false; { - _x params ["_remoteTs3Id","_remoteUser"]; - if (_remoteTs3Id == _speakingId) exitWith { + _x params ["_remoteVoipId","_remoteUser"]; + if (_remoteVoipId == _speakingId) exitWith { _found = true; if (_unit != _remoteUser) then { GVAR(playerList) set [_forEachIndex, [_speakingId, _unit]]; REM(GVAR(speakers),_remoteUser); - REM(GVAR(spectatorSpeakers),_remoteTs3Id); + REM(GVAR(spectatorSpeakers),_remoteVoipId); REM(GVAR(keyedMicRadios),_remoteUser); - /*if (_remoteTs3Id in ACRE_SPECTATORS_LIST) then { - GVAR(spectatorSpeakers) pushBackUnique _remoteTs3Id; + /*if (_remoteVoipId in ACRE_SPECTATORS_LIST) then { + GVAR(spectatorSpeakers) pushBackUnique _remoteVoipId; };*/ }; - // Case where objects dont match but we found our TS ID. + // Case where objects dont match but we found our Mumble/TS ID. }; } forEach (GVAR(playerList)); if (!_found) then { @@ -81,7 +81,7 @@ private _result = false; false }; - _unit setVariable [QGVAR(ts3id), _speakingId]; + _unit setVariable [QGVAR(voipId), _speakingId]; _unit setVariable [QGVAR(languageId), _languageId]; TRACE_1("unit pos", getPosASL _unit); private _isMuted = IS_MUTED(_unit); diff --git a/addons/sys_core/fnc_remoteStopSpeaking.sqf b/addons/sys_core/fnc_remoteStopSpeaking.sqf index 0fbd9b8e9..51fd72c88 100644 --- a/addons/sys_core/fnc_remoteStopSpeaking.sqf +++ b/addons/sys_core/fnc_remoteStopSpeaking.sqf @@ -4,7 +4,7 @@ * Handles the event of other (remote) players stopping speaking. * * Arguments: - * 0: TeamSpeak ID of talking player + * 0: Mumble/TeamSpeak ID of talking player * 1: Net ID of player object * * Return Value: @@ -18,7 +18,7 @@ params ["_speakingId","_netId"]; _speakingId = parseNumber _speakingId; -// if (_speakingId != GVAR(ts3id)) then { +// if (_speakingId != GVAR(voipId)) then { private _found = false; private _unit = objectFromNetId _netId; if (!isNil "_unit") then { diff --git a/addons/sys_core/fnc_setPluginSetting.sqf b/addons/sys_core/fnc_setPluginSetting.sqf index 09393a6de..740f2db34 100644 --- a/addons/sys_core/fnc_setPluginSetting.sqf +++ b/addons/sys_core/fnc_setPluginSetting.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handles setting TeamSpeak plugin settings. Waits for pipe to open and then applies them. + * Handles setting Mumble/TeamSpeak plugin settings. Waits for pipe to open and then applies them. * * Arguments: * 0: Setting Name diff --git a/addons/sys_core/fnc_speaking.sqf b/addons/sys_core/fnc_speaking.sqf index 8bff8f28e..035664450 100644 --- a/addons/sys_core/fnc_speaking.sqf +++ b/addons/sys_core/fnc_speaking.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Sets up the the per frame event handler for processing all the speaking data which in turn will send data to TeamSpeak. + * Sets up the the per frame event handler for processing all the speaking data which in turn will send data to Mumble/TeamSpeak. * * Arguments: * None @@ -215,7 +215,7 @@ if !(GVAR(keyedMicRadios) isEqualTo []) then { _sentMicRadios pushBack _unit; private _params = HASH_GET(_compiledParams, _x); private _canUnderstand = [_unit] call FUNC(canUnderstand); - private _paramArray = ["r", GET_TS3ID(_unit), !_canUnderstand, count _params]; + private _paramArray = ["r", GET_VOIPID(_unit), !_canUnderstand, count _params]; { _paramArray append _x; } forEach _params; @@ -244,13 +244,13 @@ if !(GVAR(keyedMicRadios) isEqualTo []) then { CALL_RPC("updateSpeakingData", _params); } else { if !(_unit in _sentMicRadios) then { - private _params = ['m', GET_TS3ID(_unit), 0]; + private _params = ['m', GET_VOIPID(_unit), 0]; CALL_RPC("updateSpeakingData", _params); }; }; } else { if (_unit != acre_player) then { - private _params = ['m', GET_TS3ID(_unit), 0]; + private _params = ['m', GET_VOIPID(_unit), 0]; CALL_RPC("updateSpeakingData", _params); }; }; diff --git a/addons/sys_core/fnc_spectatorOff.sqf b/addons/sys_core/fnc_spectatorOff.sqf index 7c59c5d65..bb9de2b2d 100644 --- a/addons/sys_core/fnc_spectatorOff.sqf +++ b/addons/sys_core/fnc_spectatorOff.sqf @@ -17,7 +17,7 @@ if (ACRE_IS_SPECTATOR) then { ACRE_IS_SPECTATOR = false; - [QEGVAR(sys_server,onSetSpector), [GVAR(ts3id), 0, clientOwner]] call CALLSTACK(CBA_fnc_serverEvent); + [QEGVAR(sys_server,onSetSpector), [GVAR(voipId), 0, clientOwner]] call CALLSTACK(CBA_fnc_serverEvent); TRACE_1("spectatorOff",ACRE_IS_SPECTATOR); }; diff --git a/addons/sys_core/fnc_spectatorOn.sqf b/addons/sys_core/fnc_spectatorOn.sqf index 9c00a1c0a..0eb69a412 100644 --- a/addons/sys_core/fnc_spectatorOn.sqf +++ b/addons/sys_core/fnc_spectatorOn.sqf @@ -17,7 +17,7 @@ if (!ACRE_IS_SPECTATOR) then { ACRE_IS_SPECTATOR = true; - [QEGVAR(sys_server,onSetSpector), [GVAR(ts3id), 1, clientOwner]] call CALLSTACK(CBA_fnc_serverEvent); + [QEGVAR(sys_server,onSetSpector), [GVAR(voipId), 1, clientOwner]] call CALLSTACK(CBA_fnc_serverEvent); TRACE_1("spectatorOn",ACRE_IS_SPECTATOR); }; diff --git a/addons/sys_core/fnc_ts3idToPlayer.sqf b/addons/sys_core/fnc_voipIdToPlayer.sqf similarity index 70% rename from addons/sys_core/fnc_ts3idToPlayer.sqf rename to addons/sys_core/fnc_voipIdToPlayer.sqf index fe61086b8..2ec38c1a3 100644 --- a/addons/sys_core/fnc_ts3idToPlayer.sqf +++ b/addons/sys_core/fnc_voipIdToPlayer.sqf @@ -1,16 +1,16 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Retrieves the game object of a player from a TeamSpeak ID. + * Retrieves the game object of a player from a Mumble/TeamSpeak ID. * * Arguments: - * 0: TeamSpeak ID + * 0: Mumble/TeamSpeak ID * * Return Value: * Player * * Example: - * ["1"] call acre_sys_core_fnc_ts3idToPlayer + * ["1"] call acre_sys_core_fnc_voipIdToPlayer * * Public: No */ diff --git a/addons/sys_core/initSettings.sqf b/addons/sys_core/initSettings.sqf index 8c72e87d5..798ac4105 100644 --- a/addons/sys_core/initSettings.sqf +++ b/addons/sys_core/initSettings.sqf @@ -46,7 +46,7 @@ {["disableUnmuteClients", _this] call FUNC(setPluginSetting)} ] call CBA_fnc_addSetting; -// Mumble/Teamspeak Channel Switching +// Mumble/TeamSpeak Channel Switching // Switch channels [ QGVAR(voipChannelSwitch), diff --git a/addons/sys_intercom/fnc_handleBroadcasting.sqf b/addons/sys_intercom/fnc_handleBroadcasting.sqf index 6f8e9ea56..00f06281d 100644 --- a/addons/sys_intercom/fnc_handleBroadcasting.sqf +++ b/addons/sys_intercom/fnc_handleBroadcasting.sqf @@ -37,7 +37,7 @@ private _changes = false; // Only broadcast if changes have been made. // TODO: Remove synchronisation once intercom system has been converted to components and unique IDs. -// It will help in reduce the bandwith, since information will be exchanged through the TS plugin. +// It will help in reduce the bandwith, since information will be exchanged through the Mumble/TS plugin. if (_changes) then { [_vehicle, _unit] call FUNC(updateVehicleInfoText); _vehicle setVariable [QGVAR(broadcasting), _broadcastConfig, true]; diff --git a/addons/sys_intercom/fnc_handleIntercomActivation.sqf b/addons/sys_intercom/fnc_handleIntercomActivation.sqf index 6876e7637..4f17086d7 100644 --- a/addons/sys_intercom/fnc_handleIntercomActivation.sqf +++ b/addons/sys_intercom/fnc_handleIntercomActivation.sqf @@ -19,7 +19,7 @@ params ["_unit", "_voiceActivation"]; // TODO: Remove synchronisation once intercom system has been converted to components and unique IDs. -// It will help in reduce the bandwith, since information will be exchanged through the TS plugin. +// It will help in reduce the bandwith, since information will be exchanged through the Mumble/TS plugin. _unit setVariable [QGVAR(intercomPTT), _voiceActivation, true]; GVAR(intercomPttKey) = _voiceActivation; diff --git a/addons/sys_io/fnc_missionDisplayLoad.sqf b/addons/sys_io/fnc_missionDisplayLoad.sqf index 7fab94f11..54f1f7105 100644 --- a/addons/sys_io/fnc_missionDisplayLoad.sqf +++ b/addons/sys_io/fnc_missionDisplayLoad.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Move TeamSpeak 3 channel on main display load. + * Move Mumble/TeamSpeak 3 channel on main display load. * * Arguments: * None @@ -16,6 +16,6 @@ */ if (GVAR(serverStarted) && {isMultiplayer}) then { - // Move TeamSpeak 3 channel on display 46 (main display) initialization + // Move Mumble/TeamSpeak 3 channel on display 46 (main display) initialization call FUNC(voipChannelMove); }; diff --git a/addons/sys_io/fnc_ping.sqf b/addons/sys_io/fnc_ping.sqf index 02475d8b5..65800f550 100644 --- a/addons/sys_io/fnc_ping.sqf +++ b/addons/sys_io/fnc_ping.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Creates a loop to send periodic messages to the TeamSpeak plugin (via the ACRE2Arma extension) to indicate that the game is still connected. + * Creates a loop to send periodic messages to the Mumble/TeamSpeak plugin (via the ACRE2Arma extension) to indicate that the game is still connected. * * Arguments: * None @@ -17,7 +17,7 @@ DFUNC(pingFunc) = { if (GVAR(serverStarted)) then { - LOG("ARMA2 TO TS3: PING!"); + LOG("ARMA3 TO MUMBLE/TS3: PING!"); // diag_log text format["%1 ACRE: ping!", diag_tickTime]; private _ret = "ACRE2Arma" callExtension "2ping:"; if (diag_tickTime - GVAR(pongTime) > 10) then { diff --git a/addons/sys_io/fnc_sendMessage.sqf b/addons/sys_io/fnc_sendMessage.sqf index caf01fe67..31bbacf54 100644 --- a/addons/sys_io/fnc_sendMessage.sqf +++ b/addons/sys_io/fnc_sendMessage.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Sends a message to the TeamSpeak plugin via the ACRE2Arma extension. + * Sends a message to the Mumble/TeamSpeak plugin via the ACRE2Arma extension. * * Arguments: * 0: Message diff --git a/addons/sys_io/fnc_server.sqf b/addons/sys_io/fnc_server.sqf index c4bb27a59..0e7b57912 100644 --- a/addons/sys_io/fnc_server.sqf +++ b/addons/sys_io/fnc_server.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Creates a PFH to monitor the ACRE2Arma extension's connection to the TeamSpeak plugin. + * Creates a PFH to monitor the ACRE2Arma extension's connection to the Mumble/TeamSpeak plugin. * * Arguments: * None @@ -54,7 +54,7 @@ DFUNC(connectionFnc) = { INFO("Pipe opened."); GVAR(serverStarted) = true; - // Move TeamSpeak 3 channel if already in-game (otherwise display XEH will take care of it) + // Move Mumble/TeamSpeak 3 channel if already in-game (otherwise display XEH will take care of it) if (!isNull (findDisplay 46)) then { call FUNC(voipChannelMove); }; diff --git a/addons/sys_io/fnc_serverReadLoop.sqf b/addons/sys_io/fnc_serverReadLoop.sqf index 98f84e5e2..dbb46db7d 100644 --- a/addons/sys_io/fnc_serverReadLoop.sqf +++ b/addons/sys_io/fnc_serverReadLoop.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Checks if the ACRE2Arma extension has any pending messages (typically for return data from the TeamSpeak plugin). This is called on a per frame basis. + * Checks if the ACRE2Arma extension has any pending messages (typically for return data from the Mumble/TeamSpeak plugin). This is called on a per frame basis. * * Arguments: * None diff --git a/addons/sys_io/fnc_startServer.sqf b/addons/sys_io/fnc_startServer.sqf index 132dc2c6d..7c371913a 100644 --- a/addons/sys_io/fnc_startServer.sqf +++ b/addons/sys_io/fnc_startServer.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Starts the SQF code to maintain connectivity to the TeamSpeak plugin via the ACRE2Arma extension. + * Starts the SQF code to maintain connectivity to the Mumble/TeamSpeak plugin via the ACRE2Arma extension. * * Arguments: * None diff --git a/addons/sys_io/fnc_voipChannelMove.sqf b/addons/sys_io/fnc_voipChannelMove.sqf index 198d62fd2..b01938d69 100644 --- a/addons/sys_io/fnc_voipChannelMove.sqf +++ b/addons/sys_io/fnc_voipChannelMove.sqf @@ -10,7 +10,7 @@ * None * * Example: - * [] call acre_sys_io_fnc_teamspeakChannelCheck + * [] call acre_sys_io_fnc_voipChannelCheck * * Public: No */ diff --git a/addons/sys_io/stringtable.xml b/addons/sys_io/stringtable.xml index 7d90b4090..9fca4c4a5 100644 --- a/addons/sys_io/stringtable.xml +++ b/addons/sys_io/stringtable.xml @@ -22,14 +22,14 @@ ACRE 从封闭的通道中恢复! - ACRE is not connected to TeamSpeak! - ACRE no está connectado al TeamSpeak! - ACRE ist nicht mit TeamSpeak verbunden! - ACRE не подключен к TeamSpeak! - ACRE が TeamSpeak に接続されていません! - ACRE 尚未與TeamSpeak連接! - ACRE n'est pas connecté à TeamSpeak ! - ACRE 尚未与TeamSpeak连接! + ACRE is not connected to Mumble/TeamSpeak! + ACRE no está connectado al Mumble/TeamSpeak! + ACRE ist nicht mit Mumble/TeamSpeak verbunden! + ACRE не подключен к Mumble/TeamSpeak! + ACRE が Mumble/TeamSpeak に接続されていません! + ACRE 尚未與Mumble/TeamSpeak連接! + ACRE n'est pas connecté à Mumble/TeamSpeak ! + ACRE 尚未与Mumble/TeamSpeak连接! ACRE connected diff --git a/addons/sys_rpc/fnc_addProcedure.sqf b/addons/sys_rpc/fnc_addProcedure.sqf index 005e04d6e..d850c49a6 100644 --- a/addons/sys_rpc/fnc_addProcedure.sqf +++ b/addons/sys_rpc/fnc_addProcedure.sqf @@ -1,7 +1,8 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Adds a procedure for when a message is received from the teamspeak plugin. Note only one callback exists before procedure this will override any previously setup callbacks for the specified procedure name. + * Adds a procedure for when a message is received from the Mumble/TeamSpeak plugin. Note only one callback exists + * before procedure this will override any previously setup callbacks for the specified procedure name. * * Arguments: * 0: Procedure name diff --git a/addons/sys_rpc/fnc_callRemoteProcedure.sqf b/addons/sys_rpc/fnc_callRemoteProcedure.sqf index 8384cc9b2..9f1fd6112 100644 --- a/addons/sys_rpc/fnc_callRemoteProcedure.sqf +++ b/addons/sys_rpc/fnc_callRemoteProcedure.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Calls a procedure in the teamspeak plugin. + * Calls a procedure in the Mumble/TeamSpeak plugin. * * Arguments: * 0: Procedure name diff --git a/addons/sys_rpc/fnc_handleData.sqf b/addons/sys_rpc/fnc_handleData.sqf index 01a84ac7f..62aeb8baf 100644 --- a/addons/sys_rpc/fnc_handleData.sqf +++ b/addons/sys_rpc/fnc_handleData.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handles the receipt of messages from the teamspeak plugin. Firstly by de-serializing the recieved message. It will then call any procedure handlers. + * Handles the receipt of messages from the Mumble/TeamSpeak plugin. Firstly by de-serializing the recieved message. It will then call any procedure handlers. * * Arguments: * 0: Message diff --git a/addons/sys_server/XEH_postInitServer.sqf b/addons/sys_server/XEH_postInitServer.sqf index 384c09e06..bdb1b9c41 100644 --- a/addons/sys_server/XEH_postInitServer.sqf +++ b/addons/sys_server/XEH_postInitServer.sqf @@ -23,5 +23,5 @@ ACRE_FULL_SERVER_VERSION = QUOTE(VERSION_STR); publicVariable "ACRE_FULL_SERVER_VERSION"; -// Event handler to remove disconnected clients from the spectator TeamSpeak list +// Event handler to remove disconnected clients from the spectator Mumble/TeamSpeak list addMissionEventHandler ["PlayerDisconnected", {_this call FUNC(handlePlayerDisconnected);}]; diff --git a/addons/sys_server/XEH_preInitServer.sqf b/addons/sys_server/XEH_preInitServer.sqf index 815c7a2fd..748a17660 100644 --- a/addons/sys_server/XEH_preInitServer.sqf +++ b/addons/sys_server/XEH_preInitServer.sqf @@ -11,7 +11,7 @@ GVAR(masterIdList) = []; GVAR(markedForGC) = HASH_CREATE; //Entry format key: radioId value: [time_last_recieved,time_last_gc_find,object] -DVAR(ACRE_SPECTATORS_LIST) = []; // TeamSpeak 3 IDs of players spectating +DVAR(ACRE_SPECTATORS_LIST) = []; // Mumble/TeamSpeak 3 IDs of players spectating DVAR(ACRE_SPECTATORS_A3_CLIENT_ID_LIST) = []; // clientOwner IDs of players spectating GVAR(masterIdTable) = HASH_CREATE; diff --git a/addons/sys_server/fnc_setSpectator.sqf b/addons/sys_server/fnc_setSpectator.sqf index ca69e8b1e..f4f06efcc 100644 --- a/addons/sys_server/fnc_setSpectator.sqf +++ b/addons/sys_server/fnc_setSpectator.sqf @@ -4,7 +4,7 @@ * Updates the ACRE_SPECTATORS_LIST global variable. * * Arguments: - * 0: TeamSpeak ID + * 0: Mumble/TeamSpeak ID * 1: Specatator status (1 = on, 0 = off) * 2: Arma 3 Client ID * @@ -18,18 +18,18 @@ */ if (isServer) then { - params ["_ts3Id","_tsStatus","_clientOwner"]; + params ["_voipId", "_voipStatus", "_clientOwner"]; private _preCount = count ACRE_SPECTATORS_LIST; - if (_tsStatus == 1) then { - if (ACRE_SPECTATORS_LIST pushBackUnique _ts3Id != -1) then { + if (_voipStatus == 1) then { + if ((ACRE_SPECTATORS_LIST pushBackUnique _voipId) != -1) then { ACRE_SPECTATORS_A3_CLIENT_ID_LIST pushBack _clientOwner; }; } else { - private _idx = ACRE_SPECTATORS_LIST find _ts3Id; + private _idx = ACRE_SPECTATORS_LIST find _voipId; while {_idx != -1} do { ACRE_SPECTATORS_LIST deleteAt _idx; ACRE_SPECTATORS_A3_CLIENT_ID_LIST deleteAt _idx; - _idx = ACRE_SPECTATORS_LIST find _ts3Id; + _idx = ACRE_SPECTATORS_LIST find _voipId; }; }; // Only call publicVariable if array changes. diff --git a/addons/sys_sounds/fnc_handleLoadedSound.sqf b/addons/sys_sounds/fnc_handleLoadedSound.sqf index 681c7080e..61bb135f1 100644 --- a/addons/sys_sounds/fnc_handleLoadedSound.sqf +++ b/addons/sys_sounds/fnc_handleLoadedSound.sqf @@ -1,7 +1,8 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * This is the callback function for recieving the event "handleLoadedSound" from teamspeak. It just ensures a sound is marked as loaded to prevent it from being loaded again. It will also call the callback function specified in the loadSound function if one exists. + * This is the callback function for recieving the event "handleLoadedSound" from Mumble/TeamSpeak. It just ensures a sound is marked as + * loaded to prevent it from being loaded again. It will also call the callback function specified in the loadSound function if one exists. * * Arguments: * 0: Radio classname diff --git a/addons/sys_sounds/fnc_loadSound.sqf b/addons/sys_sounds/fnc_loadSound.sqf index 65635dc0a..21fdf6341 100644 --- a/addons/sys_sounds/fnc_loadSound.sqf +++ b/addons/sys_sounds/fnc_loadSound.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Function to send a b64 sound to the teamspeak plugin to be loaded. Once loaded the sound will always be available. + * Function to send a b64 sound to the Mumble/TeamSpeak plugin to be loaded. Once loaded the sound will always be available. * * Arguments: * 0: Sound classname (in CfgAcreSounds) @@ -19,8 +19,8 @@ params ["_className",["_returnFunction",nil],["_force",false]]; -// If teamspeak is connected. -if (EGVAR(sys_core,ts3id) != -1) then { +// If Mumble/TeamSpeak is connected. +if (EGVAR(sys_core,voipId) != -1) then { if (!(_className in GVAR(loadedSounds)) && {!_force}) then { private _fileName = getText(configFile >> "CfgAcreSounds" >> _className >> "sound"); if (_fileName != "") then { @@ -42,7 +42,7 @@ if (EGVAR(sys_core,ts3id) != -1) then { //teamspeak is not connected store in a buffer. if (isNil QGVAR(soundLoadBuffer)) then { GVAR(soundLoadBuffer) = [_this]; - [{EGVAR(sys_core,ts3id) != -1}, { + [{EGVAR(sys_core,voipId) != -1}, { { _x call FUNC(loadSound); } forEach (GVAR(soundLoadBuffer)); diff --git a/addons/sys_sounds/fnc_playSound.sqf b/addons/sys_sounds/fnc_playSound.sqf index 5d51ff84a..aba2cf02a 100644 --- a/addons/sys_sounds/fnc_playSound.sqf +++ b/addons/sys_sounds/fnc_playSound.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Plays a loaded sound from teamspeak. + * Plays a loaded sound from Mumble/TeamSpeak. * * Arguments: * 0: Sound classname - Same classname as used in the loadSound function. From 4ac2938dbff332278d39f74db2968464a51bb3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sat, 16 May 2020 19:23:47 +0200 Subject: [PATCH 022/104] Fix RPCs --- addons/sys_core/initSettings.sqf | 2 +- extensions/src/ACRE2Core/setSetting.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sys_core/initSettings.sqf b/addons/sys_core/initSettings.sqf index 798ac4105..b7a049fed 100644 --- a/addons/sys_core/initSettings.sqf +++ b/addons/sys_core/initSettings.sqf @@ -55,7 +55,7 @@ "ACRE2", true, false, - {["disablevoipChannelSwitch", _this] call FUNC(setPluginSetting)} + {["disableVoipChannelSwitch", _this] call FUNC(setPluginSetting)} ] call CBA_fnc_addSetting; // Channel Name diff --git a/extensions/src/ACRE2Core/setSetting.h b/extensions/src/ACRE2Core/setSetting.h index 6761b3045..e248e4960 100644 --- a/extensions/src/ACRE2Core/setSetting.h +++ b/extensions/src/ACRE2Core/setSetting.h @@ -21,7 +21,7 @@ RPC_FUNCTION(setSetting) { if (CAcreSettings::getInstance()->getDisableUnmuteClients() != (value != 1)) { CAcreSettings::getInstance()->setDisableUnmuteClients(value != 1); } - } else if (name == "disableTS3ChannelSwitch") { + } else if (name == "disableVoipChannelSwitch") { if (CAcreSettings::getInstance()->getDisableChannelSwitch() != (value != 1)) { CAcreSettings::getInstance()->setDisableChannelSwitch(value != 1); } From 8205137a82c60f4b490865ae546776912dcd0180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sat, 16 May 2020 19:24:23 +0200 Subject: [PATCH 023/104] Enahnce stability of findChannelByNames function --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 1ce77fa6b..e37a92506 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -360,9 +360,9 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { if (details_.at(0) != "") { name = details_.at(0); } - while (*channelList) { - channelId = *channelList; - channelList++; + + for (std::size_t idx = 0U; idx < channelCount; idx++) { + channelId = *channelList + idx; char* channelName = nullptr; //if (ts3Functions.getChannelVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == STATUS_OK) { From 15c783fae781b8042df90239bf879d5b7b2488e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sat, 16 May 2020 21:57:29 +0200 Subject: [PATCH 024/104] Investigate plugins not copying when launching x32 arma --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 14 +++++++++----- extensions/src/ACRE2Steam/mumble_plugin.hpp | 11 ++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 4c9e21f48..01c060b54 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -149,7 +149,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!ts3_locations_success && !mumble_locations_success) { const std::int32_t result = MessageBoxA(nullptr, "ACRE2 was unable to find a TeamSpeak 3 or a Mumble installation. If you do have an installation please copy the plugins " - "yourself or reinstall TeamSpeak 3. \n\n If you are sure you have TeamSpeak 3 installed and wish to prevent this message " + "yourself or reinstall TeamSpeak 3. \n\n If you are sure you have Mumble and/or TeamSpeak 3 installed and wish to prevent this message " "from appearing again remove ACRE2Steam.dll and ACRE2Steam_x64.dll from your @acre2 folder.\n\nContinue anyway?", "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); if (result == IDYES) { @@ -177,8 +177,8 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!update_ts3_ok || !update_mumble_ok) { std::ostringstream oss; - oss << "ACRE2 was unable to copy the TeamSpeak 3 plugin. Please check if you have write access to the plugin folder, " - << "close any instances of TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you would like to close Arma 3 " + oss << "ACRE2 was unable to copy the Mumble/TeamSpeak 3 plugin. Please check if you have write access to the plugin folder, " + << "close any instances of Mumble and/or TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you would like to close Arma 3 " << "click Cancel. Press Continue to launch Arma 3 regardless.\n\n" << error_msg; const int32_t result = @@ -210,6 +210,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { found_paths.append(path + "\n"); } } + oss << "\n"; if (!mumble_plugin.get_updated_paths().empty()) { oss << "The Mumble plugins have been copied to the following location(s):\n"; @@ -218,6 +219,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { found_paths.append(path + "\n"); } } + oss << "\n"; if (!ts3_plugin.get_removed_paths().empty()) { oss << "The TeamSpeak 3 plugin has been removed from the following location(s):\n"; @@ -225,6 +227,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { oss << path << "\n"; } } + oss << "\n"; if (!mumble_plugin.get_removed_paths().empty()) { oss << "The Mumble plugin has been removed from the following location(s):\n"; @@ -232,10 +235,11 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { oss << path << "\n"; } } + oss << "\n"; - oss << "If this is NOT valid, please uninstall all versions of TeamSpeak 3 and reinstall both it and ACRE2 or copy the plugins " + oss << "If this is NOT valid, please uninstall all versions of Mumble and/or TeamSpeak 3 and reinstall both it and ACRE2 or copy the plugins " << "manually to your correct installation.\n\n"; - oss << "If this appears to be the correct folder(s) please remember to enable the plugin in TeamSpeak 3 and/or Mumble!"; + oss << "If this appears to be the correct folder(s) please remember to enable the plugin in Mumble and/or TeamSpeak 3!"; const int32_t result = MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Success", MB_OK | MB_ICONINFORMATION); sprintf(output, "[1,\"%s\"]", found_paths.c_str()); diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index 8a58cf1ce..3ad67f02d 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -30,24 +30,25 @@ namespace idi::acre { if (!mumble_path.empty()) { check_plugin_locations(mumble_path); } else { + // TODO: 32 bits applications will not recognise FOLDERID_ProgramFilesX64 std::array folder_ids = {FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64}; for (const auto folder : folder_ids) { - wchar_t *app_data_roaming = nullptr; - SHGetKnownFolderPath(folder, 0, nullptr, &app_data_roaming); + wchar_t *folder_path = nullptr; + SHGetKnownFolderPath(folder, 0, nullptr, &folder_path); - if (app_data_roaming == nullptr) { + if (folder_path == nullptr) { return false; } // TODO: Substitude it with WideCharToMultiByte from "Windows.h" std::wstring_convert> conv; - std::string app_data = conv.to_bytes(app_data_roaming); + std::string app_data = conv.to_bytes(folder_path); app_data.append("\\Mumble"); check_plugin_locations(app_data); // Now do the same for x64 - CoTaskMemFree(app_data_roaming); // Free it up. + CoTaskMemFree(folder_path); // Free it up. } } From 4129885a7355cc8ac94884bd9a11e8f57186e012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Mon, 18 May 2020 21:55:06 +0200 Subject: [PATCH 025/104] Change Mumble/TS references to VOIP --- addons/main/script_macros.hpp | 2 +- addons/sys_core/XEH_postInit.sqf | 4 ++-- addons/sys_core/fnc_coreInitPFH.sqf | 2 +- addons/sys_core/fnc_getClientIdLoop.sqf | 2 +- addons/sys_core/fnc_handleGetHeadVector.sqf | 2 +- addons/sys_core/fnc_handleGetPluginVersion.sqf | 6 +++--- addons/sys_core/fnc_isMuted.sqf | 2 +- addons/sys_core/fnc_muting.sqf | 2 +- addons/sys_core/fnc_pong.sqf | 4 ++-- addons/sys_core/fnc_processDirectSpeaker.sqf | 4 ++-- addons/sys_core/fnc_processRadioSpeaker.sqf | 4 ++-- addons/sys_core/fnc_remoteStartSpeaking.sqf | 2 +- addons/sys_core/fnc_remoteStopSpeaking.sqf | 2 +- addons/sys_core/fnc_setPluginSetting.sqf | 2 +- addons/sys_core/fnc_speaking.sqf | 2 +- addons/sys_core/fnc_voipIdToPlayer.sqf | 4 ++-- addons/sys_core/initSettings.sqf | 2 +- addons/sys_io/fnc_missionDisplayLoad.sqf | 4 ++-- addons/sys_io/fnc_ping.sqf | 4 ++-- addons/sys_io/fnc_sendMessage.sqf | 2 +- addons/sys_io/fnc_server.sqf | 4 ++-- addons/sys_io/fnc_serverReadLoop.sqf | 2 +- addons/sys_io/fnc_startServer.sqf | 2 +- addons/sys_io/fnc_voipChannelMove.sqf | 4 ++-- addons/sys_rpc/fnc_addProcedure.sqf | 2 +- addons/sys_rpc/fnc_callRemoteProcedure.sqf | 2 +- addons/sys_rpc/fnc_handleData.sqf | 2 +- addons/sys_server/XEH_postInitServer.sqf | 2 +- addons/sys_server/XEH_preInitServer.sqf | 2 +- addons/sys_server/fnc_setSpectator.sqf | 2 +- addons/sys_sounds/fnc_handleLoadedSound.sqf | 2 +- addons/sys_sounds/fnc_loadSound.sqf | 4 ++-- addons/sys_sounds/fnc_playSound.sqf | 2 +- 33 files changed, 45 insertions(+), 45 deletions(-) diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index 7e6c7268b..a433a6a4e 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -98,7 +98,7 @@ Antenna Defines #define SCRATCH_GET(radioId, key) ([radioId, key] call EFUNC(sys_data,getScratchData)) #define SCRATCH_GET_DEF(radioId, key, defaultVal) ([radioId, key, defaultVal] call EFUNC(sys_data,getScratchData)) -#define GET_VOIPID(object) (object call { private _ret = (_this getVariable [QGVAR(voipId), -1]); if (_ret == -1) then { WARNING_1("%1 has no Mumble/TS3 ID",_this); }; _ret }) +#define GET_VOIPID(object) (object call { private _ret = (_this getVariable [QGVAR(voipId), -1]); if (_ret == -1) then { WARNING_1("%1 has no VOIP ID",_this); }; _ret }) #define IS_HASH(hash) (hash isEqualType locationNull && {(type hash) isEqualTo "ACRE_FastHashNamespaceDummy"}) diff --git a/addons/sys_core/XEH_postInit.sqf b/addons/sys_core/XEH_postInit.sqf index babe93c1a..a78fefa72 100644 --- a/addons/sys_core/XEH_postInit.sqf +++ b/addons/sys_core/XEH_postInit.sqf @@ -5,7 +5,7 @@ if (!hasInterface) exitWith {}; -// Ensure the Mumble/TeamSpeak plugin handler code is initialized first +// Ensure the VOIP plugin handler code is initialized first [] call EFUNC(sys_io,startServer); ["handleGetClientID", FUNC(handleGetClientID)] call EFUNC(sys_rpc,addProcedure); @@ -144,7 +144,7 @@ if (getClientStateNumber < 10) then { // Check before game has started (in brief ["setSoundSystemMasterOverride", [0]] call EFUNC(sys_rpc,callRemoteProcedure); [_this select 1] call CBA_fnc_removePerFrameHandler; } else { - // Keep calling incase ACRE is not connected to Mumble/TeamSpeak + // Keep calling incase ACRE is not connected to VOIP solution ["setSoundSystemMasterOverride", [1]] call EFUNC(sys_rpc,callRemoteProcedure); }; }, 0, []] call CBA_fnc_addPerFrameHandler; diff --git a/addons/sys_core/fnc_coreInitPFH.sqf b/addons/sys_core/fnc_coreInitPFH.sqf index 0a0ed4156..a70c84c7e 100644 --- a/addons/sys_core/fnc_coreInitPFH.sqf +++ b/addons/sys_core/fnc_coreInitPFH.sqf @@ -21,7 +21,7 @@ acre_player = player; if (!ACRE_MAP_LOADED || {!ACRE_DATA_SYNCED} || {GVAR(voipId) == -1}) exitWith {}; -TRACE_1("GOT Mumble/TS3 ID", GVAR(voipId)); +TRACE_1("GOT VOIP ID", GVAR(voipId)); [] call FUNC(utilityFunction); // OK [] call FUNC(muting); diff --git a/addons/sys_core/fnc_getClientIdLoop.sqf b/addons/sys_core/fnc_getClientIdLoop.sqf index 9e7c256f1..8790e3849 100644 --- a/addons/sys_core/fnc_getClientIdLoop.sqf +++ b/addons/sys_core/fnc_getClientIdLoop.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * This function exists to setup the process for sending our object and player ID to other clients to associate with our Mumble/TeamSpeak ID. + * This function exists to setup the process for sending our object and player ID to other clients to associate with our VOIP ID. * * Arguments: * None diff --git a/addons/sys_core/fnc_handleGetHeadVector.sqf b/addons/sys_core/fnc_handleGetHeadVector.sqf index f016810b3..e93502de7 100644 --- a/addons/sys_core/fnc_handleGetHeadVector.sqf +++ b/addons/sys_core/fnc_handleGetHeadVector.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Sends the current head direction vector to the Mumble/TeamSpeak plugin. + * Sends the current head direction vector to the VOIP plugin. * * Arguments: * None diff --git a/addons/sys_core/fnc_handleGetPluginVersion.sqf b/addons/sys_core/fnc_handleGetPluginVersion.sqf index b47822234..9bec5fb85 100644 --- a/addons/sys_core/fnc_handleGetPluginVersion.sqf +++ b/addons/sys_core/fnc_handleGetPluginVersion.sqf @@ -1,10 +1,10 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handles the return of the current plugin version from Mumble/TeamSpeak. Displays messages to the player if any of the versions do not match. + * Handles the return of the current plugin version from VOIP. Displays messages to the player if any of the versions do not match. * * Arguments: - * 0: Mumble/TeamSpeak plugin version + * 0: VOIP plugin version * * Return Value: * Handled @@ -35,7 +35,7 @@ if (!ACRE_SPIT_VERSION && {!isNil "ACRE_FULL_SERVER_VERSION"}) then { if (_warn) then { ACRE_HAS_WARNED = true; - ERROR_WITH_TITLE_3("Mismatched Mumble/TeamSpeak plugin or mod versions!","\nMumble/TeamSpeak plugin version: %1\nYour version: %2\nServer version: %3",GVAR(pluginVersion),QUOTE(VERSION_STR),ACRE_FULL_SERVER_VERSION); + ERROR_WITH_TITLE_3("Mismatched VOIP plugin or mod versions!","\nVOIP plugin version: %1\nYour version: %2\nServer version: %3",GVAR(pluginVersion),QUOTE(VERSION_STR),ACRE_FULL_SERVER_VERSION); } else { if (ACRE_HAS_WARNED) then { ACRE_HAS_WARNED = false; diff --git a/addons/sys_core/fnc_isMuted.sqf b/addons/sys_core/fnc_isMuted.sqf index 3e0b8837b..f6be1881a 100644 --- a/addons/sys_core/fnc_isMuted.sqf +++ b/addons/sys_core/fnc_isMuted.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * This function determines is used to check if the unit should be muted on Mumble/TeamSpeak or not. + * This function determines is used to check if the unit should be muted on VOIP or not. * * Arguments: * 0: unit diff --git a/addons/sys_core/fnc_muting.sqf b/addons/sys_core/fnc_muting.sqf index 4bae1f969..a1cc79d8b 100644 --- a/addons/sys_core/fnc_muting.sqf +++ b/addons/sys_core/fnc_muting.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Sets up the per frame event handler to mute and unmute clients on Mumble/TeamSpeak. The muting occurs to optimize Mumble/TeamSpeak + * Sets up the per frame event handler to mute and unmute clients on ^VOIP. The muting occurs to optimize VOIP * bandwidth as voice data is not sent for muted clients. * * Arguments: diff --git a/addons/sys_core/fnc_pong.sqf b/addons/sys_core/fnc_pong.sqf index f5eb187c3..f44184deb 100644 --- a/addons/sys_core/fnc_pong.sqf +++ b/addons/sys_core/fnc_pong.sqf @@ -1,8 +1,8 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handler for recieving pong messages from the Mumble/TeamSpeak plugin. This is called periodically as it provides a - * simple check to make sure Mumble/TeamSpeak is still connected to the game. + * Handler for recieving pong messages from the VOIP plugin. This is called periodically as it provides a + * simple check to make sure VOIP is still connected to the game. * * Arguments: * None diff --git a/addons/sys_core/fnc_processDirectSpeaker.sqf b/addons/sys_core/fnc_processDirectSpeaker.sqf index e4d559817..9a0cba923 100644 --- a/addons/sys_core/fnc_processDirectSpeaker.sqf +++ b/addons/sys_core/fnc_processDirectSpeaker.sqf @@ -1,13 +1,13 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Calculates the information required by Mumble/TeamSpeak for a direct speech speaker. + * Calculates the information required by VOIP for a direct speech speaker. * * Arguments: * 0: Unit * * Return Value: - * Parameters to send to Mumble/TeamSpeak + * Parameters to send to VOIP * * Example: * [unit] call acre_sys_core_fnc_processDirectSpeaker diff --git a/addons/sys_core/fnc_processRadioSpeaker.sqf b/addons/sys_core/fnc_processRadioSpeaker.sqf index 31909c149..b2f2ad39c 100644 --- a/addons/sys_core/fnc_processRadioSpeaker.sqf +++ b/addons/sys_core/fnc_processRadioSpeaker.sqf @@ -1,14 +1,14 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Calculates the information required by Mumble/TeamSpeak for a radio speaker. + * Calculates the information required by VOIP for a radio speaker. * * Arguments: * 0: Unit to process * 1: List of radio classnames * * Return Value: - * Parameters to send to Mumble/TeamSpeak + * Parameters to send to VOIP * * Example: * [unit,["ACRE_PRC343_ID_1"]] call acre_sys_core_fnc_processRadioSpeaker diff --git a/addons/sys_core/fnc_remoteStartSpeaking.sqf b/addons/sys_core/fnc_remoteStartSpeaking.sqf index a5041db25..42d5538b1 100644 --- a/addons/sys_core/fnc_remoteStartSpeaking.sqf +++ b/addons/sys_core/fnc_remoteStartSpeaking.sqf @@ -4,7 +4,7 @@ * Handles the event of other (remote) players starting to speaking. * * Arguments: - * 0: Mumble/TeamSpeak ID of talking player + * 0: VOIP ID of talking player * 1: Language ID * 2: Net ID of player object * 3: On radio diff --git a/addons/sys_core/fnc_remoteStopSpeaking.sqf b/addons/sys_core/fnc_remoteStopSpeaking.sqf index 51fd72c88..ab18d38d5 100644 --- a/addons/sys_core/fnc_remoteStopSpeaking.sqf +++ b/addons/sys_core/fnc_remoteStopSpeaking.sqf @@ -4,7 +4,7 @@ * Handles the event of other (remote) players stopping speaking. * * Arguments: - * 0: Mumble/TeamSpeak ID of talking player + * 0: VOIP ID of talking player * 1: Net ID of player object * * Return Value: diff --git a/addons/sys_core/fnc_setPluginSetting.sqf b/addons/sys_core/fnc_setPluginSetting.sqf index 740f2db34..79f43e39d 100644 --- a/addons/sys_core/fnc_setPluginSetting.sqf +++ b/addons/sys_core/fnc_setPluginSetting.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handles setting Mumble/TeamSpeak plugin settings. Waits for pipe to open and then applies them. + * Handles setting VOIP plugin settings. Waits for pipe to open and then applies them. * * Arguments: * 0: Setting Name diff --git a/addons/sys_core/fnc_speaking.sqf b/addons/sys_core/fnc_speaking.sqf index 035664450..59b1c0508 100644 --- a/addons/sys_core/fnc_speaking.sqf +++ b/addons/sys_core/fnc_speaking.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Sets up the the per frame event handler for processing all the speaking data which in turn will send data to Mumble/TeamSpeak. + * Sets up the the per frame event handler for processing all the speaking data which in turn will send data to VOIP. * * Arguments: * None diff --git a/addons/sys_core/fnc_voipIdToPlayer.sqf b/addons/sys_core/fnc_voipIdToPlayer.sqf index 2ec38c1a3..68eba0eaa 100644 --- a/addons/sys_core/fnc_voipIdToPlayer.sqf +++ b/addons/sys_core/fnc_voipIdToPlayer.sqf @@ -1,10 +1,10 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Retrieves the game object of a player from a Mumble/TeamSpeak ID. + * Retrieves the game object of a player from a VOIP ID. * * Arguments: - * 0: Mumble/TeamSpeak ID + * 0: VOIP ID * * Return Value: * Player diff --git a/addons/sys_core/initSettings.sqf b/addons/sys_core/initSettings.sqf index b7a049fed..6e67bed16 100644 --- a/addons/sys_core/initSettings.sqf +++ b/addons/sys_core/initSettings.sqf @@ -46,7 +46,7 @@ {["disableUnmuteClients", _this] call FUNC(setPluginSetting)} ] call CBA_fnc_addSetting; -// Mumble/TeamSpeak Channel Switching +// VOIP Channel Switching // Switch channels [ QGVAR(voipChannelSwitch), diff --git a/addons/sys_io/fnc_missionDisplayLoad.sqf b/addons/sys_io/fnc_missionDisplayLoad.sqf index 54f1f7105..f323bad62 100644 --- a/addons/sys_io/fnc_missionDisplayLoad.sqf +++ b/addons/sys_io/fnc_missionDisplayLoad.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Move Mumble/TeamSpeak 3 channel on main display load. + * Move VOIP channel on main display load. * * Arguments: * None @@ -16,6 +16,6 @@ */ if (GVAR(serverStarted) && {isMultiplayer}) then { - // Move Mumble/TeamSpeak 3 channel on display 46 (main display) initialization + // Move VOIP channel on display 46 (main display) initialization call FUNC(voipChannelMove); }; diff --git a/addons/sys_io/fnc_ping.sqf b/addons/sys_io/fnc_ping.sqf index 65800f550..fb9f6b96a 100644 --- a/addons/sys_io/fnc_ping.sqf +++ b/addons/sys_io/fnc_ping.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Creates a loop to send periodic messages to the Mumble/TeamSpeak plugin (via the ACRE2Arma extension) to indicate that the game is still connected. + * Creates a loop to send periodic messages to the VOIP plugin (via the ACRE2Arma extension) to indicate that the game is still connected. * * Arguments: * None @@ -17,7 +17,7 @@ DFUNC(pingFunc) = { if (GVAR(serverStarted)) then { - LOG("ARMA3 TO MUMBLE/TS3: PING!"); + LOG("ARMA3 TO VOIP: PING!"); // diag_log text format["%1 ACRE: ping!", diag_tickTime]; private _ret = "ACRE2Arma" callExtension "2ping:"; if (diag_tickTime - GVAR(pongTime) > 10) then { diff --git a/addons/sys_io/fnc_sendMessage.sqf b/addons/sys_io/fnc_sendMessage.sqf index 31bbacf54..4e2151d4b 100644 --- a/addons/sys_io/fnc_sendMessage.sqf +++ b/addons/sys_io/fnc_sendMessage.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Sends a message to the Mumble/TeamSpeak plugin via the ACRE2Arma extension. + * Sends a message to the VOIP plugin via the ACRE2Arma extension. * * Arguments: * 0: Message diff --git a/addons/sys_io/fnc_server.sqf b/addons/sys_io/fnc_server.sqf index 0e7b57912..128a32262 100644 --- a/addons/sys_io/fnc_server.sqf +++ b/addons/sys_io/fnc_server.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Creates a PFH to monitor the ACRE2Arma extension's connection to the Mumble/TeamSpeak plugin. + * Creates a PFH to monitor the ACRE2Arma extension's connection to the VOIP plugin. * * Arguments: * None @@ -54,7 +54,7 @@ DFUNC(connectionFnc) = { INFO("Pipe opened."); GVAR(serverStarted) = true; - // Move Mumble/TeamSpeak 3 channel if already in-game (otherwise display XEH will take care of it) + // Move VOIP channel if already in-game (otherwise display XEH will take care of it) if (!isNull (findDisplay 46)) then { call FUNC(voipChannelMove); }; diff --git a/addons/sys_io/fnc_serverReadLoop.sqf b/addons/sys_io/fnc_serverReadLoop.sqf index dbb46db7d..a32172d78 100644 --- a/addons/sys_io/fnc_serverReadLoop.sqf +++ b/addons/sys_io/fnc_serverReadLoop.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Checks if the ACRE2Arma extension has any pending messages (typically for return data from the Mumble/TeamSpeak plugin). This is called on a per frame basis. + * Checks if the ACRE2Arma extension has any pending messages (typically for return data from the VOIP plugin). This is called on a per frame basis. * * Arguments: * None diff --git a/addons/sys_io/fnc_startServer.sqf b/addons/sys_io/fnc_startServer.sqf index 7c371913a..97af7e34d 100644 --- a/addons/sys_io/fnc_startServer.sqf +++ b/addons/sys_io/fnc_startServer.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Starts the SQF code to maintain connectivity to the Mumble/TeamSpeak plugin via the ACRE2Arma extension. + * Starts the SQF code to maintain connectivity to the VOIP plugin via the ACRE2Arma extension. * * Arguments: * None diff --git a/addons/sys_io/fnc_voipChannelMove.sqf b/addons/sys_io/fnc_voipChannelMove.sqf index b01938d69..bfac67425 100644 --- a/addons/sys_io/fnc_voipChannelMove.sqf +++ b/addons/sys_io/fnc_voipChannelMove.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: Tim Beswick - * Sends configured channel name and server name to Mumble/TS plugin, triggering Mumble/TeamSpeak 3 channel move. + * Sends configured channel name and server name to VOI^P plugin, triggering VOIP channel move. * * Arguments: * None @@ -16,5 +16,5 @@ */ private _channelDetails = format ["%1,%2,%3", EGVAR(sys_core,voipChannelName), EGVAR(sys_core,voipChannelPassword), serverName]; -TRACE_1("Moving Mumble/TS3 Channel",_channelDetails); +TRACE_1("Moving VOIP Channel",_channelDetails); CALL_RPC("setChannelDetails",_channelDetails); diff --git a/addons/sys_rpc/fnc_addProcedure.sqf b/addons/sys_rpc/fnc_addProcedure.sqf index d850c49a6..9d19eac2c 100644 --- a/addons/sys_rpc/fnc_addProcedure.sqf +++ b/addons/sys_rpc/fnc_addProcedure.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Adds a procedure for when a message is received from the Mumble/TeamSpeak plugin. Note only one callback exists + * Adds a procedure for when a message is received from the VOIP plugin. Note only one callback exists * before procedure this will override any previously setup callbacks for the specified procedure name. * * Arguments: diff --git a/addons/sys_rpc/fnc_callRemoteProcedure.sqf b/addons/sys_rpc/fnc_callRemoteProcedure.sqf index 9f1fd6112..cb966e3a2 100644 --- a/addons/sys_rpc/fnc_callRemoteProcedure.sqf +++ b/addons/sys_rpc/fnc_callRemoteProcedure.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Calls a procedure in the Mumble/TeamSpeak plugin. + * Calls a procedure in the VOIP plugin. * * Arguments: * 0: Procedure name diff --git a/addons/sys_rpc/fnc_handleData.sqf b/addons/sys_rpc/fnc_handleData.sqf index 62aeb8baf..2b56a7526 100644 --- a/addons/sys_rpc/fnc_handleData.sqf +++ b/addons/sys_rpc/fnc_handleData.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Handles the receipt of messages from the Mumble/TeamSpeak plugin. Firstly by de-serializing the recieved message. It will then call any procedure handlers. + * Handles the receipt of messages from the VOIP plugin. Firstly by de-serializing the recieved message. It will then call any procedure handlers. * * Arguments: * 0: Message diff --git a/addons/sys_server/XEH_postInitServer.sqf b/addons/sys_server/XEH_postInitServer.sqf index bdb1b9c41..9c8a73724 100644 --- a/addons/sys_server/XEH_postInitServer.sqf +++ b/addons/sys_server/XEH_postInitServer.sqf @@ -23,5 +23,5 @@ ACRE_FULL_SERVER_VERSION = QUOTE(VERSION_STR); publicVariable "ACRE_FULL_SERVER_VERSION"; -// Event handler to remove disconnected clients from the spectator Mumble/TeamSpeak list +// Event handler to remove disconnected clients from the spectator VOIP list addMissionEventHandler ["PlayerDisconnected", {_this call FUNC(handlePlayerDisconnected);}]; diff --git a/addons/sys_server/XEH_preInitServer.sqf b/addons/sys_server/XEH_preInitServer.sqf index 748a17660..6bc31a440 100644 --- a/addons/sys_server/XEH_preInitServer.sqf +++ b/addons/sys_server/XEH_preInitServer.sqf @@ -11,7 +11,7 @@ GVAR(masterIdList) = []; GVAR(markedForGC) = HASH_CREATE; //Entry format key: radioId value: [time_last_recieved,time_last_gc_find,object] -DVAR(ACRE_SPECTATORS_LIST) = []; // Mumble/TeamSpeak 3 IDs of players spectating +DVAR(ACRE_SPECTATORS_LIST) = []; // VOIP IDs of players spectating DVAR(ACRE_SPECTATORS_A3_CLIENT_ID_LIST) = []; // clientOwner IDs of players spectating GVAR(masterIdTable) = HASH_CREATE; diff --git a/addons/sys_server/fnc_setSpectator.sqf b/addons/sys_server/fnc_setSpectator.sqf index f4f06efcc..326697a17 100644 --- a/addons/sys_server/fnc_setSpectator.sqf +++ b/addons/sys_server/fnc_setSpectator.sqf @@ -4,7 +4,7 @@ * Updates the ACRE_SPECTATORS_LIST global variable. * * Arguments: - * 0: Mumble/TeamSpeak ID + * 0: VOIP ID * 1: Specatator status (1 = on, 0 = off) * 2: Arma 3 Client ID * diff --git a/addons/sys_sounds/fnc_handleLoadedSound.sqf b/addons/sys_sounds/fnc_handleLoadedSound.sqf index 61bb135f1..46142d1a2 100644 --- a/addons/sys_sounds/fnc_handleLoadedSound.sqf +++ b/addons/sys_sounds/fnc_handleLoadedSound.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * This is the callback function for recieving the event "handleLoadedSound" from Mumble/TeamSpeak. It just ensures a sound is marked as + * This is the callback function for recieving the event "handleLoadedSound" from VOIP plugin. It just ensures a sound is marked as * loaded to prevent it from being loaded again. It will also call the callback function specified in the loadSound function if one exists. * * Arguments: diff --git a/addons/sys_sounds/fnc_loadSound.sqf b/addons/sys_sounds/fnc_loadSound.sqf index 21fdf6341..fbb5e11d5 100644 --- a/addons/sys_sounds/fnc_loadSound.sqf +++ b/addons/sys_sounds/fnc_loadSound.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Function to send a b64 sound to the Mumble/TeamSpeak plugin to be loaded. Once loaded the sound will always be available. + * Function to send a b64 sound to the VOIP plugin to be loaded. Once loaded the sound will always be available. * * Arguments: * 0: Sound classname (in CfgAcreSounds) @@ -19,7 +19,7 @@ params ["_className",["_returnFunction",nil],["_force",false]]; -// If Mumble/TeamSpeak is connected. +// If VOIP plugin is connected. if (EGVAR(sys_core,voipId) != -1) then { if (!(_className in GVAR(loadedSounds)) && {!_force}) then { private _fileName = getText(configFile >> "CfgAcreSounds" >> _className >> "sound"); diff --git a/addons/sys_sounds/fnc_playSound.sqf b/addons/sys_sounds/fnc_playSound.sqf index aba2cf02a..a13263e69 100644 --- a/addons/sys_sounds/fnc_playSound.sqf +++ b/addons/sys_sounds/fnc_playSound.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* * Author: ACRE2Team - * Plays a loaded sound from Mumble/TeamSpeak. + * Plays a loaded sound from VOIP solution. * * Arguments: * 0: Sound classname - Same classname as used in the loadSound function. From 802c3c576fb9a68513dcad73af3d952efdf74b93 Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Mon, 18 May 2020 20:16:11 -0700 Subject: [PATCH 026/104] For the sake of ease when building both plugins archs manually. --- extensions/build_x64/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 extensions/build_x64/.gitignore diff --git a/extensions/build_x64/.gitignore b/extensions/build_x64/.gitignore new file mode 100644 index 000000000..5e7d2734c --- /dev/null +++ b/extensions/build_x64/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore From 71895c9c1c90f0b1e045b6fba6faa56a4bef3fe8 Mon Sep 17 00:00:00 2001 From: jonpas Date: Wed, 20 May 2020 14:52:03 +0200 Subject: [PATCH 027/104] Adapt release build tool for Mumble plugin and new plugin build paths --- tools/make.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/make.py b/tools/make.py index c9af5411d..617110a15 100755 --- a/tools/make.py +++ b/tools/make.py @@ -74,10 +74,10 @@ signature_blacklist = [] importantFiles = ["acre_logo_medium_ca.paa", "meta.cpp", "mod.cpp", "LICENSE", "README.md", "acre.dll", "acre_x64.dll", "ACRE2Arma.dll", "ACRE2Arma_x64.dll", "ACRE2Steam.dll", "ACRE2Steam_x64.dll"] extrasFiles = ["examples", "Wav2B64.exe"] -pluginFiles = ["acre2_win32.dll", "acre2_win64.dll"] +pluginFiles = ["ts3", "mumble"] versionFiles = ["README.md", "extensions\\src\\ACRE2Shared\\version.h", "docs\\_data\\sidebar.yml"] -extensions32 = ["ACRE2Arma\\acre", "ACRE2Arma\\arma2ts", "ACRE2\\ACRE2Steam", "ACRE2\\ACRE2TS", "Extras\\Wav2B64"] -extensions64 = ["ACRE2Arma\\acre", "ACRE2Arma\\arma2ts", "ACRE2\\ACRE2Steam", "ACRE2\\ACRE2TS"] +extensions32 = ["ACRE2Arma\\acre", "ACRE2Arma\\arma2ts", "ACRE2\\ACRE2Steam", "ACRE2\\ACRE2TS", "ACRE2\\ACRE2Mumble", "Extras\\Wav2B64"] +extensions64 = ["ACRE2Arma\\acre", "ACRE2Arma\\arma2ts", "ACRE2\\ACRE2Steam", "ACRE2\\ACRE2TS", "ACRE2\\ACRE2Mumble"] # be_cred_file expected to be in folder defined by enviorment variable CBA_PUBLISH_CREDENTIALS_PATH be_cred_filename = "acre_battleye_creds.json" @@ -436,8 +436,12 @@ def copy_important_files(source_dir,destination_dir): for file in pluginFiles: filePath = os.path.join(source_plugin_dir, file) if os.path.exists(filePath): - print_green("Copying plugin dll => {}".format(filePath)) - shutil.copy(filePath, destination_plugin_dir) + if os.path.isdir(filePath): + print_green("Copying plugin directory => {}".format(filePath)) + shutil.copytree(filePath, os.path.join(destination_plugin_dir,file)) + else: + print_green("Copying plugin dll => {}".format(filePath)) + shutil.copy(filePath, destination_plugin_dir) else: missingFiles.append("{}".format(filePath)) print_error("Failed copying plugin dll => {}".format(filePath)) From f89ba631ec404e86be529ebd9fbb83397cb44982 Mon Sep 17 00:00:00 2001 From: jonpas Date: Wed, 20 May 2020 14:52:13 +0200 Subject: [PATCH 028/104] v2.7.3.1025 --- addons/main/script_version.hpp | 2 +- extensions/src/ACRE2Shared/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index 98ee667f8..6fb2fe39b 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 2 #define MINOR 7 #define PATCHLVL 3 -#define BUILD 1024 +#define BUILD 1025 diff --git a/extensions/src/ACRE2Shared/version.h b/extensions/src/ACRE2Shared/version.h index aaa64346b..2300febd1 100644 --- a/extensions/src/ACRE2Shared/version.h +++ b/extensions/src/ACRE2Shared/version.h @@ -1,4 +1,4 @@ #define ACRE_VERSION_MAJOR 2 #define ACRE_VERSION_MINOR 7 #define ACRE_VERSION_SUBMINOR 3 -#define ACRE_VERSION_BUILD 1024 +#define ACRE_VERSION_BUILD 1025 From c3138666ab6de14db84d49f0ec6f2892a5849442 Mon Sep 17 00:00:00 2001 From: jonpas Date: Wed, 20 May 2020 15:05:06 +0200 Subject: [PATCH 029/104] Place Mumble PDB next to other symbols (no name clash) --- extensions/src/ACRE2Mumble/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/src/ACRE2Mumble/CMakeLists.txt b/extensions/src/ACRE2Mumble/CMakeLists.txt index 9bdbb055b..26a5ab283 100644 --- a/extensions/src/ACRE2Mumble/CMakeLists.txt +++ b/extensions/src/ACRE2Mumble/CMakeLists.txt @@ -27,5 +27,5 @@ add_custom_command(TARGET ${ACRE_NAME} POST_BUILD # Copy DLL to plugins COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_SOURCE_DIR}/../plugin/mumble/${FINAL_DLL_NAME} # Copy PDB to symbols - COMMAND ${CMAKE_COMMAND} -E copy $/${ACRE_NAME}.pdb ${PROJECT_SOURCE_DIR}/../symbols/mumble/${ACRE_ARCH}/${ACRE_NAME}.pdb + COMMAND ${CMAKE_COMMAND} -E copy $/${ACRE_NAME}.pdb ${PROJECT_SOURCE_DIR}/../symbols/${ACRE_ARCH}/${ACRE_NAME}.pdb ) From 784c68464086366f16f5689bce7ecbce616a4a4c Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Thu, 21 May 2020 11:04:02 -0700 Subject: [PATCH 030/104] Remove folder I didn't need. --- extensions/build_x64/.gitignore | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 extensions/build_x64/.gitignore diff --git a/extensions/build_x64/.gitignore b/extensions/build_x64/.gitignore deleted file mode 100644 index 5e7d2734c..000000000 --- a/extensions/build_x64/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore From f47eef7c3322688ed51713e3f695c4b659da6b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sat, 23 May 2020 22:13:36 +0200 Subject: [PATCH 031/104] Fix duplicate paths in mumble. Fix Try Again --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 91 +++++++++++-------- extensions/src/ACRE2Steam/mumble_plugin.hpp | 8 ++ 2 files changed, 61 insertions(+), 38 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 01c060b54..8f86e669f 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -161,43 +161,50 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { return; } - const idi::acre::UpdateCode update_ts3 = ts3_plugin.handle_update_plugin(); - std::string error_msg; - const bool update_ts3_ok = (update_ts3 != idi::acre::UpdateCode::update_failed) && (update_ts3 != idi::acre::UpdateCode::other); - if (!update_ts3_ok) { - error_msg = ts3_plugin.get_last_error_message(); - } - - const idi::acre::UpdateCode update_mumble = mumble_plugin.handle_update_plugin(); - const bool update_mumble_ok = - (update_mumble != idi::acre::UpdateCode::update_failed) && (update_mumble != idi::acre::UpdateCode::other); - if (!update_mumble_ok) { - error_msg = mumble_plugin.get_last_error_message(); - } + bool try_copy = false; + + do { + const idi::acre::UpdateCode update_ts3 = ts3_plugin.handle_update_plugin(); + std::string error_msg; + const bool update_ts3_ok = (update_ts3 != idi::acre::UpdateCode::update_failed) && (update_ts3 != idi::acre::UpdateCode::other); + if (!update_ts3_ok) { + error_msg = ts3_plugin.get_last_error_message(); + } - if (!update_ts3_ok || !update_mumble_ok) { - std::ostringstream oss; - oss << "ACRE2 was unable to copy the Mumble/TeamSpeak 3 plugin. Please check if you have write access to the plugin folder, " - << "close any instances of Mumble and/or TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you would like to close Arma 3 " - << "click Cancel. Press Continue to launch Arma 3 regardless.\n\n" - << error_msg; - const int32_t result = - MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); - if (result == IDCANCEL) { - TerminateProcess(GetCurrentProcess(), 0); - return; - } else if (result == IDCONTINUE) { - sprintf(output, "[-4,true,%d %d]", ts3_plugin.get_last_error(), mumble_plugin.get_last_error()); - return; + const idi::acre::UpdateCode update_mumble = mumble_plugin.handle_update_plugin(); + const bool update_mumble_ok = + (update_mumble != idi::acre::UpdateCode::update_failed) && (update_mumble != idi::acre::UpdateCode::other); + if (!update_mumble_ok) { + error_msg = mumble_plugin.get_last_error_message(); } - } - // Update was not necessary. - if ((update_ts3 == idi::acre::UpdateCode::update_not_necessary) && - (update_mumble == idi::acre::UpdateCode::update_not_necessary)) { // No update was copied etc. - strncpy(output, "[0]", outputSize); - return; - } + if (!update_ts3_ok || !update_mumble_ok) { + std::ostringstream oss; + oss << "ACRE2 was unable to copy the Mumble/TeamSpeak 3 plugin. Please check if you have write access to the plugin folder, " + << "close any instances of Mumble and/or TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you would like to close Arma 3 " + << "click Cancel. Press Continue to launch Arma 3 regardless.\n\n" + << error_msg; + const int32_t result = + MessageBoxA(nullptr, (LPCSTR)oss.str().c_str(), "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); + if (result == IDCANCEL) { + TerminateProcess(GetCurrentProcess(), 0); + return; + } + else if (result == IDCONTINUE) { + sprintf(output, "[-4,true,%d %d]", ts3_plugin.get_last_error(), mumble_plugin.get_last_error()); + return; + } + } else { + try_copy = true; + + // Update was not necessary. + if ((update_ts3 == idi::acre::UpdateCode::update_not_necessary) && + (update_mumble == idi::acre::UpdateCode::update_not_necessary)) { // No update was copied etc. + strncpy(output, "[0]", outputSize); + return; + } + } + } while (!try_copy); std::ostringstream oss; oss << "A new version of ACRE2 (" << current_version << ") has been installed!\n\n"; @@ -209,8 +216,10 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { oss << path << "\n"; found_paths.append(path + "\n"); } + + oss << "\n"; } - oss << "\n"; + if (!mumble_plugin.get_updated_paths().empty()) { oss << "The Mumble plugins have been copied to the following location(s):\n"; @@ -218,24 +227,30 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { oss << path << "\n"; found_paths.append(path + "\n"); } + + oss << "\n"; } - oss << "\n"; + if (!ts3_plugin.get_removed_paths().empty()) { oss << "The TeamSpeak 3 plugin has been removed from the following location(s):\n"; for (const auto &path : ts3_plugin.get_removed_paths()) { oss << path << "\n"; } + + oss << "\n"; } - oss << "\n"; + if (!mumble_plugin.get_removed_paths().empty()) { oss << "The Mumble plugin has been removed from the following location(s):\n"; for (const auto &path : mumble_plugin.get_removed_paths()) { oss << path << "\n"; } + + oss << "\n"; } - oss << "\n"; + oss << "If this is NOT valid, please uninstall all versions of Mumble and/or TeamSpeak 3 and reinstall both it and ACRE2 or copy the plugins " << "manually to your correct installation.\n\n"; diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index 3ad67f02d..fe585544a 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -52,6 +52,14 @@ namespace idi::acre { } } + // Do not delete if we need to copy it + std::vector mumble_locations = get_plugin_locations(); + std::vector mumble_delete_locations = get_plugin_delete_locations(); + + for (const auto& location : mumble_locations) { + (void)std::remove(mumble_delete_locations.begin(), mumble_delete_locations.end(), location); + } + // No locations to copy to. return !get_plugin_locations().empty(); } From ac416933a1b66e8c4683be7ec7491163fcb9d16c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sat, 23 May 2020 22:26:10 +0200 Subject: [PATCH 032/104] Delete all locations instead of only the first match --- extensions/src/ACRE2Steam/mumble_plugin.hpp | 2 +- extensions/src/ACRE2Steam/ts3_plugin.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index fe585544a..97d2260c9 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -57,7 +57,7 @@ namespace idi::acre { std::vector mumble_delete_locations = get_plugin_delete_locations(); for (const auto& location : mumble_locations) { - (void)std::remove(mumble_delete_locations.begin(), mumble_delete_locations.end(), location); + mumble_delete_locations.erase(std::remove(mumble_delete_locations.begin(), mumble_delete_locations.end(), location), mumble_delete_locations.end()); } // No locations to copy to. diff --git a/extensions/src/ACRE2Steam/ts3_plugin.hpp b/extensions/src/ACRE2Steam/ts3_plugin.hpp index f6c1c0d0c..19385f321 100644 --- a/extensions/src/ACRE2Steam/ts3_plugin.hpp +++ b/extensions/src/ACRE2Steam/ts3_plugin.hpp @@ -62,7 +62,7 @@ namespace idi::acre { std::vector ts3_delete_locations = get_plugin_delete_locations(); for (const auto &location : ts3_locations) { - (void) std::remove(ts3_delete_locations.begin(), ts3_delete_locations.end(), location); + ts3_delete_locations.erase(std::remove(ts3_delete_locations.begin(), ts3_delete_locations.end(), location), ts3_delete_locations.end()); } // No locations to copy to. From ae51ac52cfdc4da8f2065ac212576436d5c29ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sun, 24 May 2020 22:15:11 +0200 Subject: [PATCH 033/104] Overhaul options system for auto-plugin copy --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 53 +++---------- extensions/src/ACRE2Steam/command_options.cpp | 74 +++++++++++++++++++ extensions/src/ACRE2Steam/command_options.hpp | 32 ++++++++ 3 files changed, 116 insertions(+), 43 deletions(-) create mode 100644 extensions/src/ACRE2Steam/command_options.cpp create mode 100644 extensions/src/ACRE2Steam/command_options.hpp diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 8f86e669f..420b7cdd6 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -1,5 +1,6 @@ /** * @author Ferran Obón Santacana (Magnetar) + * @author Cliff Foster (Nou) * @author James Smith (snippers) * * @copyright Copyright (c) 2020 International Development & Integration Systems LLC @@ -14,6 +15,7 @@ #include "mumble_plugin.hpp" #include "shlobj.h" #include "ts3_plugin.hpp" +#include "command_options.hpp" #include #include @@ -40,42 +42,6 @@ void __stdcall RVExtensionVersion(char *output, int outputSize) { sprintf_s(output, outputSize - 1, "%s", ACRE_VERSION); } -inline std::string get_cmdline() { - return std::string(GetCommandLineA()); -} - -bool skip_plugin_copy() { - return std::string::npos != get_cmdline().find("-skipAcrePluginCopy"); -} - -bool skip_ts_plugin_copy() { - return std::string::npos != get_cmdline().find("-skipAcreTSPluginCopy"); -} - -bool skip_mumble_plugin_copy() { - return std::string::npos != get_cmdline().find("-skipAcreMumblePluginCopy"); -} - -std::string mumble_install_path() { - const std::string option = "-mumblePath="; - size_t pos = get_cmdline().find(option); - if (pos == std::string::npos) { - return ""; - } - size_t end_path_pos = get_cmdline().find_first_of(' ', pos); - if (end_path_pos == std::string::npos) { - // Check for end of line - - end_path_pos = get_cmdline().find_first_of('\n', pos); - - if (end_path_pos == std::string::npos) { - return ""; - } - } - pos += option.length(); - return get_cmdline().substr(pos, end_path_pos - pos); -} - void __stdcall RVExtension(char *output, int outputSize, const char *function) { size_t id_length = 1; std::string functionStr(function); @@ -94,15 +60,19 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { const auto command = static_cast(std::atoi(id.c_str())); - if (skip_plugin_copy()) { + std::string cmd_line = std::string(GetCommandLineA()); + idi::acre::Arguments cmd_args(cmd_line); + if (cmd_args.has_argument("-skipAcrePluginCopy")) { return; } - const bool skip_ts_plugin = skip_ts_plugin_copy(); - const bool skip_mumble_plugin = skip_mumble_plugin_copy(); + const bool skip_ts_plugin = cmd_args.has_argument("-skipAcreTSPluginCopy"); + const bool skip_mumble_plugin = cmd_args.has_argument("-skipAcreMumblePluginCopy"); + + std::string test = cmd_args.get_argument("-mumblePath"); idi::acre::TS3Plugin ts3_plugin(skip_ts_plugin); - idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, mumble_install_path()); + idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); switch (command) { case SteamCommand::check: { @@ -231,7 +201,6 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { oss << "\n"; } - if (!ts3_plugin.get_removed_paths().empty()) { oss << "The TeamSpeak 3 plugin has been removed from the following location(s):\n"; for (const auto &path : ts3_plugin.get_removed_paths()) { @@ -241,7 +210,6 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { oss << "\n"; } - if (!mumble_plugin.get_removed_paths().empty()) { oss << "The Mumble plugin has been removed from the following location(s):\n"; for (const auto &path : mumble_plugin.get_removed_paths()) { @@ -251,7 +219,6 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { oss << "\n"; } - oss << "If this is NOT valid, please uninstall all versions of Mumble and/or TeamSpeak 3 and reinstall both it and ACRE2 or copy the plugins " << "manually to your correct installation.\n\n"; oss << "If this appears to be the correct folder(s) please remember to enable the plugin in Mumble and/or TeamSpeak 3!"; diff --git a/extensions/src/ACRE2Steam/command_options.cpp b/extensions/src/ACRE2Steam/command_options.cpp new file mode 100644 index 000000000..5cbc1f4dd --- /dev/null +++ b/extensions/src/ACRE2Steam/command_options.cpp @@ -0,0 +1,74 @@ +/** + * @author Ferran Obón Santacana (Magnetar) + * @author Thymo- + * + * @copyright Copyright (c) 2020 International Development & Integration Systems LLC + * + * Command line options for ACRE2. + */ + +#include "command_options.hpp" + +#include +#include + +using ::idi::acre::Arguments; + +const std::string& Arguments::get_argument(const std::string& key_) const noexcept { + const auto it = arguments.find(key_); + + if (it == arguments.cend()) { + return ""; + } + + return it->second; +} + +bool Arguments::has_argument(const std::string& key_) const noexcept { + return arguments.cend() != arguments.find(key_); +} + +void Arguments::parse_line(const std::string& line_) noexcept(false) { + std::istringstream iss(line_); + std::string arg; + while (std::getline(iss, arg, ' ')) { + const std::string par_opt("-par="); + std::string par_path; + if (arg.find("-par") != arg.npos) { + par_path = arg.substr(par_opt.length()); + + std::ifstream par_file(par_path); + + // Append all options from the parameter file + if (!par_file.is_open()) { + throw std::runtime_error("Parameters file could not be opened!"); + } + + std::string par_line; + std::getline(par_file, par_line); + if (par_line == "class Arg") { + par_file.close(); + throw std::runtime_error("Old file format detected"); + } + + par_file.seekg(0, par_file.beg); + + while (std::getline(par_file, par_line)) { + handle_argument(par_line); + } + + par_file.close(); + } else { + handle_argument(arg); + } + } +} + +void Arguments::handle_argument(const std::string& arg_) noexcept { + const auto& option_pos = arg_.find('='); + if (option_pos != arg_.npos) { + arguments[arg_.substr(0, option_pos)] = arg_.substr(option_pos + 1, arg_.length() - option_pos); + } else { + arguments[arg_] = ""; + } +} diff --git a/extensions/src/ACRE2Steam/command_options.hpp b/extensions/src/ACRE2Steam/command_options.hpp new file mode 100644 index 000000000..f0631c14a --- /dev/null +++ b/extensions/src/ACRE2Steam/command_options.hpp @@ -0,0 +1,32 @@ +/** + * @author Ferran Obón Santacana (Magnetar) + * + * @copyright Copyright (c) 2020 International Development & Integration Systems LLC + * + * Mumble auto-plugin copy functionality. + */ +#pragma once + +#include +#include + +namespace idi::acre { + class Arguments { + public: + explicit Arguments(std::string& line_) noexcept(false) { + parse_line(line_); + } + + ~Arguments() = default; + + const std::string& get_argument(const std::string &key_) const noexcept; + + bool has_argument(const std::string& key_) const noexcept; + + private: + void parse_line(const std::string& line_) noexcept(false); + void handle_argument(const std::string& arg_) noexcept; + + std::unordered_map arguments; + }; +} From 97480d0702d68936c6b931456bc5d3ddfefc7ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Thu, 28 May 2020 22:43:33 +0200 Subject: [PATCH 034/104] Do not use deprecated functions to convert wide char string to utf-8 string --- extensions/src/ACRE2Steam/mumble_plugin.hpp | 5 ++--- extensions/src/ACRE2Steam/ts3_plugin.hpp | 5 ++--- extensions/src/ACRE2Steam/voip_plugin.hpp | 22 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index 97d2260c9..5748b3b25 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -40,9 +40,8 @@ namespace idi::acre { return false; } - // TODO: Substitude it with WideCharToMultiByte from "Windows.h" - std::wstring_convert> conv; - std::string app_data = conv.to_bytes(folder_path); + // Convert to UTF-8 string + std::string app_data = wide_string_to_utf8(folder_path); app_data.append("\\Mumble"); check_plugin_locations(app_data); diff --git a/extensions/src/ACRE2Steam/ts3_plugin.hpp b/extensions/src/ACRE2Steam/ts3_plugin.hpp index 19385f321..6a2b9f1a4 100644 --- a/extensions/src/ACRE2Steam/ts3_plugin.hpp +++ b/extensions/src/ACRE2Steam/ts3_plugin.hpp @@ -34,9 +34,8 @@ namespace idi::acre { return false; } - // TODO: Substitude it with WideCharToMultiByte from "Windows.h" - std::wstring_convert> conv; - std::string app_data = conv.to_bytes(app_data_roaming); + // Convert to UTF-8 string + std::string app_data = wide_string_to_utf8(app_data_roaming); app_data.append("\\TS3Client"); CoTaskMemFree(app_data_roaming); // Free it up. diff --git a/extensions/src/ACRE2Steam/voip_plugin.hpp b/extensions/src/ACRE2Steam/voip_plugin.hpp index 8cb079299..1c9c35a06 100644 --- a/extensions/src/ACRE2Steam/voip_plugin.hpp +++ b/extensions/src/ACRE2Steam/voip_plugin.hpp @@ -59,6 +59,28 @@ namespace idi::acre { protected: + // Convert a wide Unicode string to an UTF8 string + + /** + * Convert a wide Unicode string to an UTF8 string . + * + * @param[in] wide_str_ Wide unicode string + * + * @return std::string UTF-8 encoded string + */ + std::string wide_string_to_utf8(const std::wstring& wide_str_) { + if (wide_str_.empty()) { + return ""; + } + + const int32_t size_needed = WideCharToMultiByte(CP_UTF8, 0, &wide_str_[0], static_cast(wide_str_.size()), nullptr, 0, nullptr, nullptr); + + std::string utf8_str(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, &wide_str_[0], static_cast(wide_str_.size()), &utf8_str[0], size_needed, nullptr, nullptr); + + return utf8_str; + } + bool get_skip_plugin() const noexcept { return skip_plugin; } bool compare_file(const std::string &path_a_, const std::string &path_b_) noexcept; From 3ad99605ae4001204094f2218a1370259b2393a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Wed, 3 Jun 2020 07:30:20 +0200 Subject: [PATCH 035/104] Parallel check of the plugins --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 420b7cdd6..dcd393c66 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #pragma comment(lib, "shlwapi.lib") @@ -134,16 +135,20 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { bool try_copy = false; do { - const idi::acre::UpdateCode update_ts3 = ts3_plugin.handle_update_plugin(); + std::future update_ts3 = std::async(std::launch::async, [&]() {return ts3_plugin.handle_update_plugin(); }); + std::future update_mumble = std::async(std::launch::async, [&]() {return mumble_plugin.handle_update_plugin(); }); + + const idi::acre::UpdateCode ts3_update_result = update_ts3.get(); + const idi::acre::UpdateCode mumble_update_result = update_mumble.get(); + std::string error_msg; - const bool update_ts3_ok = (update_ts3 != idi::acre::UpdateCode::update_failed) && (update_ts3 != idi::acre::UpdateCode::other); + const bool update_ts3_ok = (ts3_update_result != idi::acre::UpdateCode::update_failed) && (ts3_update_result != idi::acre::UpdateCode::other); if (!update_ts3_ok) { error_msg = ts3_plugin.get_last_error_message(); } - const idi::acre::UpdateCode update_mumble = mumble_plugin.handle_update_plugin(); const bool update_mumble_ok = - (update_mumble != idi::acre::UpdateCode::update_failed) && (update_mumble != idi::acre::UpdateCode::other); + (mumble_update_result != idi::acre::UpdateCode::update_failed) && (mumble_update_result != idi::acre::UpdateCode::other); if (!update_mumble_ok) { error_msg = mumble_plugin.get_last_error_message(); } @@ -168,8 +173,8 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { try_copy = true; // Update was not necessary. - if ((update_ts3 == idi::acre::UpdateCode::update_not_necessary) && - (update_mumble == idi::acre::UpdateCode::update_not_necessary)) { // No update was copied etc. + if ((ts3_update_result == idi::acre::UpdateCode::update_not_necessary) && + (mumble_update_result == idi::acre::UpdateCode::update_not_necessary)) { // No update was copied etc. strncpy(output, "[0]", outputSize); return; } From b859418da7ab9b363005b1963d3059af854713bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Wed, 3 Jun 2020 14:42:36 +0200 Subject: [PATCH 036/104] Mumble registry finding --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 5 +- extensions/src/ACRE2Steam/mumble_plugin.hpp | 73 ++++++++++++++++++- extensions/src/ACRE2Steam/voip_plugin.cpp | 8 +- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index dcd393c66..6e288cf63 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -70,10 +70,9 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { const bool skip_ts_plugin = cmd_args.has_argument("-skipAcreTSPluginCopy"); const bool skip_mumble_plugin = cmd_args.has_argument("-skipAcreMumblePluginCopy"); - std::string test = cmd_args.get_argument("-mumblePath"); - idi::acre::TS3Plugin ts3_plugin(skip_ts_plugin); - idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); + idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, ""); + //idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); switch (command) { case SteamCommand::check: { diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index 5748b3b25..32fa05f99 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -18,7 +18,7 @@ namespace idi::acre { class Mumble_plugin final : public VOIPPlugin { public: explicit Mumble_plugin(bool skip_plugin_, std::string mumble_path_ = "") noexcept - : VOIPPlugin(skip_plugin_, "SOFTWARE\\Mumble\\Mumble", find_mod_file("plugin/mumble/acre2_win32.dll"), find_mod_file("plugin/mumble/acre2_win64.dll")), + : VOIPPlugin(skip_plugin_, "SOFTWARE\\Mumble\\Mumble\\plugins", find_mod_file("plugin/mumble/acre2_win32.dll"), find_mod_file("plugin/mumble/acre2_win64.dll")), mumble_path(std::move(mumble_path_)) {} ~Mumble_plugin() noexcept final = default; @@ -30,10 +30,13 @@ namespace idi::acre { if (!mumble_path.empty()) { check_plugin_locations(mumble_path); } else { + parse_mumble_registry(false); // 32 bits + parse_mumble_registry(true); // 64 bits + // TODO: 32 bits applications will not recognise FOLDERID_ProgramFilesX64 - std::array folder_ids = {FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64}; + std::array folder_ids = { FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64 }; for (const auto folder : folder_ids) { - wchar_t *folder_path = nullptr; + wchar_t* folder_path = nullptr; SHGetKnownFolderPath(folder, 0, nullptr, &folder_path); if (folder_path == nullptr) { @@ -64,6 +67,70 @@ namespace idi::acre { } private: + void parse_mumble_registry(const bool use_x64_) noexcept { + REGSAM sam_key = KEY_READ | KEY_WOW64_64KEY; + + if (!use_x64_) { + sam_key = KEY_READ; + } + + HKEY registry_key; + if (RegOpenKeyEx(HKEY_CURRENT_USER, get_registry_key().c_str(), 0, sam_key, ®istry_key) != ERROR_SUCCESS) { + return; + } + + DWORD num_subkeys = 0; + if (RegQueryInfoKey(registry_key, nullptr, nullptr, nullptr, &num_subkeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS) { + RegCloseKey(registry_key); + return; + } + + for (DWORD idx = 0; idx < num_subkeys; idx++) { + TCHAR achKey[max_key_length]; + DWORD cbName = max_key_length; + if (RegEnumKeyEx(registry_key, idx, achKey, &cbName, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS) { + continue; + } + + HKEY plugin_key; + std::string name = get_registry_key() + "\\" + std::string(achKey); + if (RegOpenKeyEx(HKEY_CURRENT_USER, name.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &plugin_key) != ERROR_SUCCESS) { + continue; + } + + DWORD type; + DWORD cbData; + if (RegQueryValueEx(plugin_key, "path", nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { + RegCloseKey(plugin_key); + continue; + } + + if (type != REG_SZ) { + RegCloseKey(plugin_key); + continue; + } + + std::string file_path(cbData / sizeof(char), '\0'); + if (RegQueryValueEx(plugin_key, "path", nullptr, nullptr, reinterpret_cast(&file_path[0]), &cbData) == ERROR_SUCCESS) { + RegCloseKey(plugin_key); + + size_t first_null = file_path.find_first_of('\0'); + if (first_null != std::string::npos) { + file_path.resize(first_null); + } + + std::filesystem::path plugin_path(file_path); + if (std::filesystem::exists(plugin_path)) { + const std::string mumble_path = plugin_path.parent_path().parent_path().string(); + check_plugin_locations(mumble_path); + } + } + } + + RegCloseKey(registry_key); + } + + static constexpr std::uint8_t max_key_length = 255U; std::string mumble_path; }; } // namespace idi::acre diff --git a/extensions/src/ACRE2Steam/voip_plugin.cpp b/extensions/src/ACRE2Steam/voip_plugin.cpp index 4b1da9c46..0ce5fa5c2 100644 --- a/extensions/src/ACRE2Steam/voip_plugin.cpp +++ b/extensions/src/ACRE2Steam/voip_plugin.cpp @@ -63,11 +63,9 @@ std::string idi::acre::find_mod_file(const std::string& filename) { } std::string VOIPPlugin::read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, const bool use_x64_) noexcept { - REGSAM sam_key; + REGSAM sam_key = KEY_READ | KEY_WOW64_64KEY; - if (use_x64_) { - sam_key = KEY_READ | KEY_WOW64_64KEY; - } else { + if (!use_x64_) { sam_key = KEY_READ; } @@ -124,7 +122,7 @@ bool VOIPPlugin::compare_file(const std::string &path_a_, const std::string &pat } void VOIPPlugin::check_plugin_locations(const std::string &app_data_) noexcept { - if (std::filesystem::exists(app_data_)) { + if (std::filesystem::exists(app_data_) && (plugin_locations.cend() == std::find(plugin_locations.cbegin(), plugin_locations.cend(), app_data_))) { plugin_locations.emplace_back(app_data_); } } From c49b4b0ccac9c41228cbec1f11c9ffab9846969f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Wed, 3 Jun 2020 14:50:08 +0200 Subject: [PATCH 037/104] Fix empty mumble path. Fix duplicate entries --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 5 +++-- extensions/src/ACRE2Steam/command_options.cpp | 2 +- extensions/src/ACRE2Steam/command_options.hpp | 2 +- extensions/src/ACRE2Steam/voip_plugin.cpp | 8 ++++++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 6e288cf63..dcd393c66 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -70,9 +70,10 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { const bool skip_ts_plugin = cmd_args.has_argument("-skipAcreTSPluginCopy"); const bool skip_mumble_plugin = cmd_args.has_argument("-skipAcreMumblePluginCopy"); + std::string test = cmd_args.get_argument("-mumblePath"); + idi::acre::TS3Plugin ts3_plugin(skip_ts_plugin); - idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, ""); - //idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); + idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); switch (command) { case SteamCommand::check: { diff --git a/extensions/src/ACRE2Steam/command_options.cpp b/extensions/src/ACRE2Steam/command_options.cpp index 5cbc1f4dd..3f955edbe 100644 --- a/extensions/src/ACRE2Steam/command_options.cpp +++ b/extensions/src/ACRE2Steam/command_options.cpp @@ -14,7 +14,7 @@ using ::idi::acre::Arguments; -const std::string& Arguments::get_argument(const std::string& key_) const noexcept { +std::string Arguments::get_argument(const std::string& key_) const noexcept { const auto it = arguments.find(key_); if (it == arguments.cend()) { diff --git a/extensions/src/ACRE2Steam/command_options.hpp b/extensions/src/ACRE2Steam/command_options.hpp index f0631c14a..b91387d3d 100644 --- a/extensions/src/ACRE2Steam/command_options.hpp +++ b/extensions/src/ACRE2Steam/command_options.hpp @@ -19,7 +19,7 @@ namespace idi::acre { ~Arguments() = default; - const std::string& get_argument(const std::string &key_) const noexcept; + std::string get_argument(const std::string &key_) const noexcept; bool has_argument(const std::string& key_) const noexcept; diff --git a/extensions/src/ACRE2Steam/voip_plugin.cpp b/extensions/src/ACRE2Steam/voip_plugin.cpp index 0ce5fa5c2..6c33a4bda 100644 --- a/extensions/src/ACRE2Steam/voip_plugin.cpp +++ b/extensions/src/ACRE2Steam/voip_plugin.cpp @@ -201,7 +201,9 @@ idi::acre::UpdateCode VOIPPlugin::handle_update_plugin() noexcept { return UpdateCode::update_failed; } - updated_paths.emplace_back(location); + if (updated_paths.cend() == std::find(updated_paths.cbegin(), updated_paths.cend(), location)) { + updated_paths.emplace_back(location); + } update_status = UpdateCode::update_ok; } } @@ -226,7 +228,9 @@ idi::acre::UpdateCode VOIPPlugin::handle_update_plugin() noexcept { return UpdateCode::update_failed; } - removed_paths.emplace_back(location); + if (removed_paths.cend() == std::find(removed_paths.cbegin(), removed_paths.cend(), location)) { + removed_paths.emplace_back(location); + } update_status = UpdateCode::update_ok; } } From 9b8533919505f025da23f55f0c127a0d6ac2c678 Mon Sep 17 00:00:00 2001 From: Magnetar Date: Tue, 9 Jun 2020 09:00:34 +0200 Subject: [PATCH 038/104] Pass on ACRE2Steam --- extensions/src/ACRE2Steam/command_options.cpp | 22 ++++++------- extensions/src/ACRE2Steam/command_options.hpp | 12 +++---- extensions/src/ACRE2Steam/mumble_plugin.hpp | 31 +++++++++++-------- extensions/src/ACRE2Steam/ts3_plugin.hpp | 11 ++++--- extensions/src/ACRE2Steam/voip_plugin.cpp | 15 +++------ extensions/src/ACRE2Steam/voip_plugin.hpp | 14 ++++----- 6 files changed, 53 insertions(+), 52 deletions(-) diff --git a/extensions/src/ACRE2Steam/command_options.cpp b/extensions/src/ACRE2Steam/command_options.cpp index 3f955edbe..ef0fce4e9 100644 --- a/extensions/src/ACRE2Steam/command_options.cpp +++ b/extensions/src/ACRE2Steam/command_options.cpp @@ -9,12 +9,12 @@ #include "command_options.hpp" -#include #include +#include using ::idi::acre::Arguments; -std::string Arguments::get_argument(const std::string& key_) const noexcept { +std::string Arguments::get_argument(const std::string &key_) const noexcept { const auto it = arguments.find(key_); if (it == arguments.cend()) { @@ -24,17 +24,17 @@ std::string Arguments::get_argument(const std::string& key_) const noexcept { return it->second; } -bool Arguments::has_argument(const std::string& key_) const noexcept { +bool Arguments::has_argument(const std::string &key_) const noexcept { return arguments.cend() != arguments.find(key_); } -void Arguments::parse_line(const std::string& line_) noexcept(false) { +void Arguments::parse_line(const std::string &line_) noexcept(false) { std::istringstream iss(line_); std::string arg; while (std::getline(iss, arg, ' ')) { const std::string par_opt("-par="); std::string par_path; - if (arg.find("-par") != arg.npos) { + if (arg.find("-par") != std::string::npos) { par_path = arg.substr(par_opt.length()); std::ifstream par_file(par_path); @@ -46,27 +46,27 @@ void Arguments::parse_line(const std::string& line_) noexcept(false) { std::string par_line; std::getline(par_file, par_line); - if (par_line == "class Arg") { + if (par_line == "class Arg") { par_file.close(); throw std::runtime_error("Old file format detected"); } - par_file.seekg(0, par_file.beg); + par_file.seekg(0, std::ifstream::beg); while (std::getline(par_file, par_line)) { handle_argument(par_line); } - par_file.close(); + par_file.close(); } else { handle_argument(arg); } } } -void Arguments::handle_argument(const std::string& arg_) noexcept { - const auto& option_pos = arg_.find('='); - if (option_pos != arg_.npos) { +void Arguments::handle_argument(const std::string &arg_) noexcept { + const auto &option_pos = arg_.find('='); + if (option_pos != std::string::npos) { arguments[arg_.substr(0, option_pos)] = arg_.substr(option_pos + 1, arg_.length() - option_pos); } else { arguments[arg_] = ""; diff --git a/extensions/src/ACRE2Steam/command_options.hpp b/extensions/src/ACRE2Steam/command_options.hpp index b91387d3d..8a7b04f05 100644 --- a/extensions/src/ACRE2Steam/command_options.hpp +++ b/extensions/src/ACRE2Steam/command_options.hpp @@ -13,20 +13,18 @@ namespace idi::acre { class Arguments { public: - explicit Arguments(std::string& line_) noexcept(false) { - parse_line(line_); - } + explicit Arguments(std::string &line_) noexcept(false) { parse_line(line_); } ~Arguments() = default; std::string get_argument(const std::string &key_) const noexcept; - bool has_argument(const std::string& key_) const noexcept; + bool has_argument(const std::string &key_) const noexcept; private: - void parse_line(const std::string& line_) noexcept(false); - void handle_argument(const std::string& arg_) noexcept; + void parse_line(const std::string &line_) noexcept(false); + void handle_argument(const std::string &arg_) noexcept; std::unordered_map arguments; }; -} +} // namespace idi::acre diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index 32fa05f99..670efd774 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -13,12 +13,14 @@ #include #include - namespace idi::acre { class Mumble_plugin final : public VOIPPlugin { public: explicit Mumble_plugin(bool skip_plugin_, std::string mumble_path_ = "") noexcept - : VOIPPlugin(skip_plugin_, "SOFTWARE\\Mumble\\Mumble\\plugins", find_mod_file("plugin/mumble/acre2_win32.dll"), find_mod_file("plugin/mumble/acre2_win64.dll")), + : VOIPPlugin(skip_plugin_, + "SOFTWARE\\Mumble\\Mumble\\plugins", + find_mod_file("plugin/mumble/acre2_win32.dll"), + find_mod_file("plugin/mumble/acre2_win64.dll")), mumble_path(std::move(mumble_path_)) {} ~Mumble_plugin() noexcept final = default; @@ -34,9 +36,9 @@ namespace idi::acre { parse_mumble_registry(true); // 64 bits // TODO: 32 bits applications will not recognise FOLDERID_ProgramFilesX64 - std::array folder_ids = { FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64 }; + std::array folder_ids = {FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64}; for (const auto folder : folder_ids) { - wchar_t* folder_path = nullptr; + wchar_t *folder_path = nullptr; SHGetKnownFolderPath(folder, 0, nullptr, &folder_path); if (folder_path == nullptr) { @@ -44,7 +46,7 @@ namespace idi::acre { } // Convert to UTF-8 string - std::string app_data = wide_string_to_utf8(folder_path); + std::string app_data = VOIPPlugin::wide_string_to_utf8(folder_path); app_data.append("\\Mumble"); check_plugin_locations(app_data); @@ -55,11 +57,12 @@ namespace idi::acre { } // Do not delete if we need to copy it - std::vector mumble_locations = get_plugin_locations(); + std::vector mumble_locations = get_plugin_locations(); std::vector mumble_delete_locations = get_plugin_delete_locations(); - for (const auto& location : mumble_locations) { - mumble_delete_locations.erase(std::remove(mumble_delete_locations.begin(), mumble_delete_locations.end(), location), mumble_delete_locations.end()); + for (const auto &location : mumble_locations) { + mumble_delete_locations.erase( + std::remove(mumble_delete_locations.begin(), mumble_delete_locations.end(), location), mumble_delete_locations.end()); } // No locations to copy to. @@ -80,17 +83,18 @@ namespace idi::acre { } DWORD num_subkeys = 0; - if (RegQueryInfoKey(registry_key, nullptr, nullptr, nullptr, &num_subkeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS) { + if (RegQueryInfoKey(registry_key, nullptr, nullptr, nullptr, &num_subkeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr) != ERROR_SUCCESS) { RegCloseKey(registry_key); return; } for (DWORD idx = 0; idx < num_subkeys; idx++) { - TCHAR achKey[max_key_length]; - DWORD cbName = max_key_length; + TCHAR achKey[max_key_length]; + DWORD cbName = max_key_length; if (RegEnumKeyEx(registry_key, idx, achKey, &cbName, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS) { continue; - } + } HKEY plugin_key; std::string name = get_registry_key() + "\\" + std::string(achKey); @@ -111,7 +115,8 @@ namespace idi::acre { } std::string file_path(cbData / sizeof(char), '\0'); - if (RegQueryValueEx(plugin_key, "path", nullptr, nullptr, reinterpret_cast(&file_path[0]), &cbData) == ERROR_SUCCESS) { + if (RegQueryValueEx(plugin_key, "path", nullptr, nullptr, reinterpret_cast(&file_path[0]), &cbData) == + ERROR_SUCCESS) { RegCloseKey(plugin_key); size_t first_null = file_path.find_first_of('\0'); diff --git a/extensions/src/ACRE2Steam/ts3_plugin.hpp b/extensions/src/ACRE2Steam/ts3_plugin.hpp index 6a2b9f1a4..0966a6f03 100644 --- a/extensions/src/ACRE2Steam/ts3_plugin.hpp +++ b/extensions/src/ACRE2Steam/ts3_plugin.hpp @@ -13,12 +13,14 @@ #include #include - namespace idi::acre { class TS3Plugin final : public VOIPPlugin { public: explicit TS3Plugin(bool skip_plugin_) noexcept - : VOIPPlugin(skip_plugin_, "SOFTWARE\\TeamSpeak 3 Client", find_mod_file("plugin/ts3/acre2_win32.dll"), find_mod_file("plugin/ts3/acre2_win64.dll")) {} + : VOIPPlugin(skip_plugin_, + "SOFTWARE\\TeamSpeak 3 Client", + find_mod_file("plugin/ts3/acre2_win32.dll"), + find_mod_file("plugin/ts3/acre2_win64.dll")) {} ~TS3Plugin() noexcept final = default; bool collect_plugin_locations() noexcept final { @@ -35,7 +37,7 @@ namespace idi::acre { } // Convert to UTF-8 string - std::string app_data = wide_string_to_utf8(app_data_roaming); + std::string app_data = VOIPPlugin::wide_string_to_utf8(app_data_roaming); app_data.append("\\TS3Client"); CoTaskMemFree(app_data_roaming); // Free it up. @@ -61,7 +63,8 @@ namespace idi::acre { std::vector ts3_delete_locations = get_plugin_delete_locations(); for (const auto &location : ts3_locations) { - ts3_delete_locations.erase(std::remove(ts3_delete_locations.begin(), ts3_delete_locations.end(), location), ts3_delete_locations.end()); + ts3_delete_locations.erase( + std::remove(ts3_delete_locations.begin(), ts3_delete_locations.end(), location), ts3_delete_locations.end()); } // No locations to copy to. diff --git a/extensions/src/ACRE2Steam/voip_plugin.cpp b/extensions/src/ACRE2Steam/voip_plugin.cpp index 6c33a4bda..0958ed1bb 100644 --- a/extensions/src/ACRE2Steam/voip_plugin.cpp +++ b/extensions/src/ACRE2Steam/voip_plugin.cpp @@ -19,23 +19,17 @@ using ::idi::acre::VOIPPlugin; std::string idi::acre::find_mod_folder() { char module_path[MAX_PATH]; - GetModuleFileNameA((HINSTANCE)&__ImageBase, module_path, MAX_PATH); + GetModuleFileNameA((HINSTANCE) &__ImageBase, module_path, MAX_PATH); char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; - _splitpath( - module_path, - drive, - dir, - nullptr, - nullptr - ); + _splitpath(module_path, drive, dir, nullptr, nullptr); return (std::string(drive) + std::string(dir)); } -std::string idi::acre::find_mod_file(const std::string& filename) { +std::string idi::acre::find_mod_file(const std::string &filename) { std::string path = find_mod_folder() + filename; if (!std::filesystem::exists(path)) { // No mod path was set, it means they used the mod config. It *DOES* mean it relative to a folder in our path at least. @@ -122,7 +116,8 @@ bool VOIPPlugin::compare_file(const std::string &path_a_, const std::string &pat } void VOIPPlugin::check_plugin_locations(const std::string &app_data_) noexcept { - if (std::filesystem::exists(app_data_) && (plugin_locations.cend() == std::find(plugin_locations.cbegin(), plugin_locations.cend(), app_data_))) { + if (std::filesystem::exists(app_data_) && + (plugin_locations.cend() == std::find(plugin_locations.cbegin(), plugin_locations.cend(), app_data_))) { plugin_locations.emplace_back(app_data_); } } diff --git a/extensions/src/ACRE2Steam/voip_plugin.hpp b/extensions/src/ACRE2Steam/voip_plugin.hpp index 1c9c35a06..1d6de0831 100644 --- a/extensions/src/ACRE2Steam/voip_plugin.hpp +++ b/extensions/src/ACRE2Steam/voip_plugin.hpp @@ -17,14 +17,13 @@ #include #include - namespace idi::acre { EXTERN_C IMAGE_DOS_HEADER __ImageBase; std::string find_mod_folder(); - std::string find_mod_file(const std::string& filename); + std::string find_mod_file(const std::string &filename); enum class UpdateCode : std::uint8_t { update_not_necessary, update_ok, update_failed, other }; @@ -54,11 +53,10 @@ namespace idi::acre { const std::vector &get_updated_paths() const noexcept { return updated_paths; } const std::vector &get_removed_paths() const noexcept { return removed_paths; } - + std::string read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, bool use_x64_) noexcept; protected: - // Convert a wide Unicode string to an UTF8 string /** @@ -68,15 +66,17 @@ namespace idi::acre { * * @return std::string UTF-8 encoded string */ - std::string wide_string_to_utf8(const std::wstring& wide_str_) { + static std::string wide_string_to_utf8(const std::wstring &wide_str_) { if (wide_str_.empty()) { return ""; } - const int32_t size_needed = WideCharToMultiByte(CP_UTF8, 0, &wide_str_[0], static_cast(wide_str_.size()), nullptr, 0, nullptr, nullptr); + const int32_t size_needed = + WideCharToMultiByte(CP_UTF8, 0, &wide_str_[0], static_cast(wide_str_.size()), nullptr, 0, nullptr, nullptr); std::string utf8_str(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &wide_str_[0], static_cast(wide_str_.size()), &utf8_str[0], size_needed, nullptr, nullptr); + WideCharToMultiByte( + CP_UTF8, 0, &wide_str_[0], static_cast(wide_str_.size()), &utf8_str[0], size_needed, nullptr, nullptr); return utf8_str; } From 88c397ab10658e3b8d63d58c96444d9a8dfbbe10 Mon Sep 17 00:00:00 2001 From: Magnetar Date: Tue, 9 Jun 2020 09:26:20 +0200 Subject: [PATCH 039/104] Code cleanup. Static functions. Nothrow --- .../MumbleCallbacks_channelEvents.cpp | 89 +---------- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 64 ++------ .../MumbleCallbacks_pluginEvents.cpp | 16 +- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 85 +++++------ .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 24 ++- .../ACRE2Mumble/MumbleCallbacks_static.cpp | 16 +- extensions/src/ACRE2Mumble/MumbleClient.cpp | 141 +++++------------- extensions/src/ACRE2Mumble/MumbleClient.h | 46 +++--- .../src/ACRE2Mumble/MumbleCommandServer.cpp | 51 +++---- .../src/ACRE2Mumble/MumbleCommandServer.h | 20 +-- extensions/src/ACRE2Mumble/MumbleFunctions.h | 2 +- .../src/ACRE2Mumble/acre2_mumble_dllmain.cpp | 19 --- extensions/src/ACRE2Shared/IClient.h | 80 +++++----- 13 files changed, 207 insertions(+), 446 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp index c505fa5ce..4979c24fa 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp @@ -1,93 +1,16 @@ -#include "compat.h" - - - -#include "Log.h" - -#include "Engine.h" -#include "Types.h" #include "AcreSettings.h" +#include "Engine.h" +#include "Log.h" #include "MumbleFunctions.h" +#include "Types.h" +#include "compat.h" extern MumbleAPI mumAPI; extern mumble_connection_t activeConnection; extern plugin_id_t pluginID; -//extern TS3Functions ts3Functions; -/* -// -// Handle move events for silencing -// -//void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage) { -void mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, mumble_channelid_t newChannelID) { - // Only unmute if teamspeak is not linked to ARMA. - if (!CAcreSettings::getInstance()->getDisableUnmuteClients() && !(CEngine::getInstance()->getGameServer()->getConnected())) { - - // Get local client ID - mumble_userid_t myID; - - //if (ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) { - if (mumAPI.getLocalUserID(pluginID, activeConnection, &myID) != STATUS_OK) { - return; // Exit if we don't - } - - //Unmute all clients if local user moves. - if (userID == myID) { - mumble_userid_t* clientsInChannel; - std::size_t userCount = 0U; - //if (ts3Functions.getChannelClientList(serverConnectionHandlerID, newChannelID, &clientsInChannel) == ERROR_ok) { - if (mumAPI.getUsersInChannel(pluginID, activeConnection, newChannelID, &clientsInChannel, &userCount) { - // Unmute clients in the current channel. Not Supported in mumble. - // ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientsInChannel, NULL); - } - mumAPI.freeMemory(pluginID, (void *) &clientsInChannel); - } else { - //Only unmute joining user when not current client. - mumble_userid_t clientIDArray[2]; // List of clients to unmute. - clientIDArray[0] = userID; // Client ID to unmute - clientIDArray[1] = 0; // Mark end of array with a 0 value. - //ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientIDArray, NULL); - } - } - -} - -//void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID moverID, const char* moverName, const char* moverUniqueIdentifier, const char* moveMessage) { -void mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, mumble_channelid_t newChannelID) { - // Only unmute if teamspeak is not linked to ARMA. - if (!CAcreSettings::getInstance()->getDisableUnmuteClients() && !(CEngine::getInstance()->getGameServer()->getConnected())) { - - // Get local client ID - mumble_userid_t myID; - - //if (ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) { - if(mumAPI.getLocalUserID(pluginID, activeConnection, &myID) != STATUS_OK) { - return; // Exit if we don't - } - - //Unmute all clients if local user moves. - if (userID == myID) { - mumble_userid_t* clientsInChannel; - std::size_t userCount = 0U; - // if (ts3Functions.getChannelClientList(serverConnectionHandlerID, newChannelID, &clientsInChannel) == ERROR_ok) { - if (mumAPI.getUsersInChannel(pluginID, activeConnection, newChannelID, &clientsInChannel, &userCount) { - // Unmute clients in the current channel. Not Supported in mumble. - ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientsInChannel, NULL); - } - ts3Functions.freeMemory(clientsInChannel); - } else { - //Only unmute joining user when not current client. - mumble_userid_t clientIDArray[2]; // List of clients to unmute. - clientIDArray[0] = userID; // Client ID to unmute - clientIDArray[1] = 0; // Mark end of array with a 0 value. - //ts3Functions.requestUnmuteClients(serverConnectionHandlerID, clientIDArray, NULL); - } - } -} -*/ -// void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) { void mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID) { - (void)connection; - (void)channelID; + (void) connection; + (void) channelID; CEngine::getInstance()->getClient()->updateShouldSwitchChannel(true); } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 283c07006..1e64d694b 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -1,46 +1,17 @@ -#include "compat.h" - -#include "Log.h" #include "Engine.h" +#include "Log.h" #include "MumbleClient.h" #include "MumbleCommandServer.h" -#include "helpers.h" - #include "MumbleFunctions.h" +#include "compat.h" +#include "helpers.h" -#define FROM_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_fromTS" -#define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toTS" +#define FROM_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_fromTS" +#define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toTS" extern MumbleAPI mumAPI; mumble_connection_t activeConnection = -1; -plugin_id_t pluginID = -1; -/* -const char* ts3plugin_name() { - return ACRE_NAME; -} -const char* ts3plugin_version() { - return ACRE_VERSION; -} -int ts3plugin_apiVersion() { - const int32_t api = getTSAPIVersion(); - - // API Compatibility - // v23 - onPluginCommandEvent_v23 = (api < 23) ? 0 : 1; - - return api; -} -const char* ts3plugin_author() { - return ACRE_TEAM_URL; -} -const char* ts3plugin_description() { - return ACRE_DESC; -} -void ts3plugin_setFunctionPointers(const struct TS3Functions funcs) { - ts3Functions = funcs; -} -*/ - +plugin_id_t pluginID = -1; void mumble_registerPluginID(plugin_id_t id) { pluginID = id; @@ -54,10 +25,11 @@ void mumble_registerAPIFunctions(struct MumbleAPI api) { mumAPI = api; CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); if (CEngine::getInstance() != NULL) { - if (((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer()) != NULL) { - ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); + if (((CMumbleCommandServer *) CEngine::getInstance()->getExternalServer()) != NULL) { + ((CMumbleCommandServer *) CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); } - if (pluginID != -1) ((CMumbleCommandServer*)CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); + if (pluginID != -1) + ((CMumbleCommandServer *) CEngine::getInstance()->getExternalServer())->setCommandId(pluginID); if (activeConnection != -1) { // we are activating while connected, call it // virtualize a connect event @@ -66,9 +38,6 @@ void mumble_registerAPIFunctions(struct MumbleAPI api) { } } -// -// Init -// mumble_error_t mumble_init(mumble_connection_t connection) { if (connection != -1) { activeConnection = connection; @@ -77,21 +46,16 @@ mumble_error_t mumble_init(mumble_connection_t connection) { return STATUS_OK; } - void mumble_onServerSynchronized(mumble_connection_t connection) { activeConnection = connection; - // // set ID on every new connection acre::id_t clientId = 0; - //ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), (anyID*)& clientId); - mumAPI.getLocalUserID(pluginID, activeConnection, (mumble_userid_t*)& clientId); + mumAPI.getLocalUserID(pluginID, activeConnection, (mumble_userid_t *) &clientId); CEngine::getInstance()->getSelf()->setId(clientId); CEngine::getInstance()->getExternalServer()->setId(clientId); - // subscribe to all channels to receive event - //ts3Functions.requestChannelSubscribeAll(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { CEngine::getInstance()->getClient()->start(static_cast(clientId)); } @@ -100,13 +64,15 @@ void mumble_onServerSynchronized(mumble_connection_t connection) { void mumble_onServerDisconnected(mumble_connection_t connection) { activeConnection = -1; - if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { + if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && + (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { CEngine::getInstance()->getClient()->stop(); } } void mumble_shutdown() { - if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { + if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && + (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { CEngine::getInstance()->getClient()->stop(); } CEngine::getInstance()->stop(); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp index e1048741d..730587eb8 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp @@ -1,22 +1,14 @@ -#include "compat.h" - #include "Engine.h" - #include "Log.h" - #include "MumbleFunctions.h" - - +#include "compat.h" // // Handle a command event // -bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char* data, size_t dataLength, - const char* dataID) { - //LOG("[%s], [%s]", pluginName, pluginCommand); - - if ((dataLength > 0U) && CEngine::getInstance()->getExternalServer()) { - CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *)data, dataLength); +bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, const char *dataID) { + if ((dataLength > 0U) && CEngine::getInstance()->getExternalServer()) { + CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *) data, dataLength); return true; } return false; diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 83e416ff0..ce83b178c 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -1,29 +1,22 @@ -#include "compat.h" - -#include "FilterVolume.h" -#include "FilterPosition.h" - #include "Engine.h" - +#include "FilterPosition.h" +#include "FilterVolume.h" #include "Log.h" - #include "MumbleClient.h" - #include "Wave.h" +#include "compat.h" #include #define _USE_MATH_DEFINES -#include -#include - #include "AcreDsp.h" +#include +#include -typedef std::numeric_limits LIMITER; +using LIMITER = std::numeric_limits; -//void ts3plugin_onEditPlaybackVoiceDataEvent(uint64 server, anyID id, short* samples, int sampleCount, int channels) { -bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID) { +bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID) { if (CEngine::getInstance()->getSoundSystemOverride()) { return false; } @@ -37,31 +30,33 @@ bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_ } // Make this faster - - //if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { + + // if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { const std::uint32_t mixdownSampleLength = sampleCount * channelCount; - int16_t *mixdownSamples = new int16_t[mixdownSampleLength]; + int16_t *mixdownSamples = new (nothrow) int16_t[mixdownSampleLength]; + if (mixdownSamples == nullptr) { + return false; + } //} - for (std::int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { + for (std::uint32_t c = 0; c <= mixdownSampleLength - 1U; ++c) { float sample = outputPCM[c]; - if (sample > 1.0) { - sample = 1.0; - } - else if (sample < -1.0) { - sample = -1.0; + if (sample > 1.0F) { + sample = 1.0F; + } else if (sample < -1.0F) { + sample = -1.0F; } mixdownSamples[c] = static_cast(sample * LIMITER::max()); } - CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent(static_cast(userID), mixdownSamples, sampleCount, channelCount); + CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent( + static_cast(userID), mixdownSamples, sampleCount, channelCount); - for (std::int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { + for (std::uint32_t c = 0; c <= mixdownSampleLength - 1; ++c) { float mixedSample = 0.0F; if (mixdownSamples[c] > 0) { mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); - } - else { + } else { mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); } outputPCM[c] = mixedSample; @@ -70,11 +65,7 @@ bool mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_ return true; } - - - bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount) { - if (CEngine::getInstance()->getSoundSystemOverride()) { return false; } @@ -86,26 +77,27 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin if (!CEngine::getInstance()->getGameServer()->getConnected()) { return false; } - - uint32_t speakerMask = 0U; - speakerMask = SPEAKER_STEREO; + + uint32_t speakerMask = SPEAKER_STEREO; // Make this faster - //if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { + // if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { const uint32_t mixdownSampleLength = sampleCount * channelCount; - int16_t *mixdownSamples = new int16_t[mixdownSampleLength]; + int16_t *mixdownSamples = new (nothrow) int16_t[mixdownSampleLength]; + if (mixdownSamples == nullptr) { + return false; + } //} - for (int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { + for (int32_t c = 0; c <= mixdownSampleLength - 1U; ++c) { float sample = outputPCM[c]; - if (sample > 1.0) { - sample = 1.0; - } - else if (sample < -1.0) { - sample = -1.0; + if (sample > 1.0F) { + sample = 1.0F; + } else if (sample < -1.0F) { + sample = -1.0F; } - mixdownSamples[c] = static_cast(sample * LIMITER::max()); + mixdownSamples[c] = static_cast(sample * LIMITER::max()); } CEngine::getInstance()->getSoundEngine()->onEditMixedPlaybackVoiceDataEvent(mixdownSamples, sampleCount, channelCount, speakerMask); @@ -114,8 +106,7 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin float mixedSample = 0.0F; if (mixdownSamples[c] > 0) { mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); - } - else { + } else { mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); } outputPCM[c] = mixedSample; @@ -123,7 +114,3 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin delete[] mixdownSamples; return true; } - -void ts3plugin_onEditCapturedVoiceDataEvent(uint64_t server, short* samples, int sampleCount, int channels, int* edited) { - CEngine::getInstance()->getSoundEngine()->onEditCapturedVoiceDataEvent(samples, sampleCount, channels); -} diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index d184cf726..fe3489ae9 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -1,17 +1,12 @@ -#include "compat.h" - - -#include "Types.h" -#include "Macros.h" - #include "Engine.h" - #include "Log.h" - +#include "Macros.h" #include "MumbleClient.h" +#include "Types.h" +#include "compat.h" // -// TS3 Speaking callbacks +// Mumble Speaking callbacks // void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t status) { LOG("mumble_onUserTalkingStateChanged ENTER: %d", status); @@ -43,13 +38,14 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use if (CEngine::getInstance()->getClient()->getOnRadio()) { if (CEngine::getInstance()->getClient()->getVAD()) { return; - } else { - if (status == TalkingState::PASSIVE || status == TalkingState::INVALID) { - if (!CEngine::getInstance()->getClient()->getRadioPTTDown()) { - CEngine::getInstance()->getClient()->setOnRadio(false); - } + } + + if (status == TalkingState::PASSIVE || status == TalkingState::INVALID) { + if (!CEngine::getInstance()->getClient()->getRadioPTTDown()) { + CEngine::getInstance()->getClient()->setOnRadio(false); } } + return; } TRACE("enter: [%d],[%d]", clientID, status); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp index 61ec5b5d7..531c0f89e 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -1,19 +1,17 @@ -#include "compat.h" -#include "Types.h" -#include "Macros.h" #include "Engine.h" -#include "Player.h" - - +#include "Macros.h" #include "MumbleFunctions.h" +#include "Player.h" +#include "Types.h" +#include "compat.h" #ifdef USE_ACRE2UI - #include "UiEngine.hpp" +#include "UiEngine.hpp" #endif #include "Log.h" -const char* mumble_getName() { +const char *mumble_getName() { return ACRE_NAME; } @@ -22,5 +20,5 @@ version_t mumble_getAPIVersion() { } version_t mumble_getVersion() { - return version_t{ ACRE_VERSION_MAJOR, ACRE_VERSION_MINOR, ACRE_VERSION_SUBMINOR }; + return version_t{ACRE_VERSION_MAJOR, ACRE_VERSION_MINOR, ACRE_VERSION_SUBMINOR}; } diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index e37a92506..da241e2bf 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -1,14 +1,12 @@ -#include "compat.h" - -#include "MumbleClient.h" +#include "AcreSettings.h" #include "Engine.h" -#include "Types.h" +#include "Log.h" +#include "MumbleClient.h" #include "MumbleFunctions.h" -#include "shlobj.h" #include "Shlwapi.h" -#include "Log.h" - -#include "AcreSettings.h" +#include "Types.h" +#include "compat.h" +#include "shlobj.h" #pragma comment(lib, "Shlwapi.lib") @@ -18,7 +16,6 @@ extern MumbleAPI mumAPI; extern mumble_connection_t activeConnection; extern plugin_id_t pluginID; -//TS3Functions CMumbleClient::ts3Functions; acre::Result CMumbleClient::initialize(void) { setPreviousChannel(INVALID_MUMBLE_CHANNEL); @@ -26,19 +23,19 @@ acre::Result CMumbleClient::initialize(void) { } acre::Result CMumbleClient::setMuted(const acre::id_t id_, const bool muted_) { - (void)id_; - (void)muted_; + (void) id_; + (void) muted_; return acre::Result::ok; } acre::Result CMumbleClient::setMuted(std::list idList_, bool muted_) { - (void)idList_; - (void)muted_; + (void) idList_; + (void) muted_; return acre::Result::ok; } acre::Result CMumbleClient::getMuted(acre::id_t id_) { - (void)id_; + (void) id_; return acre::Result::ok; } @@ -50,7 +47,6 @@ acre::Result CMumbleClient::stop() { this->m_versionThreadHandle.join(); } this->setState(acre::State::stopped); - } return acre::Result::ok; } @@ -67,65 +63,11 @@ acre::Result CMumbleClient::start(const acre::id_t id_) { this->setState(acre::State::running); this->setIsX3DInitialized(false); - //this->m_versionThreadHandle = std::thread(&CMumbleClient::exPersistVersion, this); + // this->m_versionThreadHandle = std::thread(&CMumbleClient::exPersistVersion, this); return acre::Result::ok; } -/* -acre::Result CMumbleClient::exPersistVersion( void ) { - - CMumbleClient::setClientMetadata(ACRE_VERSION_METADATA); - - ts3Functions.printMessageToCurrentTab("ACRE2 loaded and initialized"); - ts3Functions.printMessageToCurrentTab(ACRE_VERSION_METADATA); - - clock_t run = clock() / CLOCKS_PER_SEC; - clock_t delta = run; - while (this->getState() == acre::State::running && CEngine::getInstance()->getExternalServer()) { - - delta = (clock() / CLOCKS_PER_SEC) - run; - if (delta > (PERSIST_VERSION_TIMER / 1000) ) { - char selfVariableBuffer[4096]; - if (CEngine::getInstance()->getGameServer()->getConnected()) { - _snprintf_s(selfVariableBuffer, 4094, "%s\nArma Connected: Yes", ACRE_VERSION_METADATA); - } else { - _snprintf_s(selfVariableBuffer, 4094, "%s\nArma Connected: No", ACRE_VERSION_METADATA); - } - CMumbleClient::setClientMetadata(selfVariableBuffer); - run = clock() / CLOCKS_PER_SEC; - } - - Sleep(100); - } - - return acre::Result::error; -} - - -acre::Result CMumbleClient::setClientMetadata(const char *const data) { - char* clientInfo; - anyID myID; - ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &myID); - ts3Functions.getClientVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), myID, CLIENT_META_DATA, &clientInfo); - std::string to_set; - std::string_view sharedMsg = clientInfo; - const size_t start_pos = sharedMsg.find(START_DATA); - const size_t end_pos = sharedMsg.find(END_DATA); - if ((start_pos == std::string::npos) || (end_pos == std::string::npos)) { - to_set = to_set + START_DATA + data + END_DATA; - } else { - const std::string before = (std::string)sharedMsg.substr(0, start_pos); - const std::string after = (std::string)sharedMsg.substr(end_pos + strlen(END_DATA), std::string::npos); - to_set = before + START_DATA + data + END_DATA + after; - } - ts3Functions.setClientSelfVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_META_DATA, to_set.c_str()); - ts3Functions.freeMemory(clientInfo); - ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), nullptr); - return acre::Result::ok; -} -*/ - bool CMumbleClient::getVAD() { transmission_mode_t transmitMode; const mumble_error_t err = mumAPI.getLocalUserTransmissionMode(pluginID, &transmitMode); @@ -163,7 +105,8 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } else { stopDirectSpeaking = true; } - } else if (this->getVAD() && (this->getSpeakingState() != TalkingState::PASSIVE && this->getSpeakingState() != TalkingState::INVALID)) { + } else if (this->getVAD() && + (this->getSpeakingState() != TalkingState::PASSIVE && this->getSpeakingState() != TalkingState::INVALID)) { stopDirectSpeaking = true; } } @@ -223,7 +166,7 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ resendDirectSpeaking = true; } } else if (this->getSpeakingState() == 1) { - resendDirectSpeaking = true; + resendDirectSpeaking = true; } } @@ -236,16 +179,15 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ } acre::Result CMumbleClient::enableMicrophone(const bool status_) { - (void)status_; + (void) status_; return acre::Result::ok; } - acre::Result CMumbleClient::playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) { return acre::Result::ok; } -std::string CMumbleClient::getUniqueId( ) { +std::string CMumbleClient::getUniqueId() { return "not used"; } @@ -258,7 +200,7 @@ std::string CMumbleClient::getConfigFilePath(void) { return tempFolder; } -std::string CMumbleClient::getTempFilePath( void ) { +std::string CMumbleClient::getTempFilePath(void) { char tempPath[MAX_PATH - 14]; GetTempPathA(sizeof(tempPath), tempPath); std::string tempFolder = std::string(tempPath); @@ -289,7 +231,7 @@ acre::Result CMumbleClient::microphoneOpen(bool status_) { return acre::Result::ok; } -acre::Result CMumbleClient::unMuteAll( void ) { +acre::Result CMumbleClient::unMuteAll(void) { return acre::Result::ok; } @@ -299,11 +241,11 @@ acre::Result CMumbleClient::moveToServerChannel() { mumble_userid_t clientId; std::vector details = getChannelDetails(); - //if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == STATUS_OK) { mumble_channelid_t currentChannelId = INVALID_MUMBLE_CHANNEL; - //if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousChannel() == INVALID_MUMBLE_CHANNEL) { - if ((mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) && (getPreviousChannel() == INVALID_MUMBLE_CHANNEL)) { + + if ((mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) && + (getPreviousChannel() == INVALID_MUMBLE_CHANNEL)) { setPreviousChannel(currentChannelId); } @@ -314,14 +256,12 @@ acre::Result CMumbleClient::moveToServerChannel() { password = details.at(1); } - //ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr); mumAPI.requestUserMove(pluginID, activeConnection, clientId, channelId, password.c_str()); - } } } setShouldSwitchChannel(false); - + return acre::Result::ok; } @@ -329,14 +269,13 @@ acre::Result CMumbleClient::moveToPreviousChannel() { LOG("moveToPreviousChannel ENTER"); if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { mumble_userid_t clientId = -1; - //if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { + if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == STATUS_OK) { mumble_channelid_t currentChannelId = INVALID_MUMBLE_CHANNEL; - //if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok) { - if (mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) { + + if (mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) { const mumble_channelid_t channelId = static_cast(getPreviousChannel()); if (channelId != INVALID_MUMBLE_CHANNEL && channelId != currentChannelId) { - //ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, "", nullptr); mumAPI.requestUserMove(pluginID, activeConnection, clientId, channelId, ""); } } @@ -349,11 +288,11 @@ acre::Result CMumbleClient::moveToPreviousChannel() { uint64_t CMumbleClient::findChannelByNames(std::vector details_) { LOG("findChannelByNames ENTER"); - mumble_channelid_t*channelList = nullptr; - std::size_t channelCount = 0U; - //if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { + mumble_channelid_t *channelList = nullptr; + std::size_t channelCount = 0U; + if (mumAPI.getAllChannels(pluginID, activeConnection, &channelList, &channelCount) == STATUS_OK) { - mumble_channelid_t channelId = INVALID_MUMBLE_CHANNEL; + mumble_channelid_t channelId = INVALID_MUMBLE_CHANNEL; mumble_channelid_t defaultChannelId = INVALID_MUMBLE_CHANNEL; std::map channelMap; std::string name = details_.at(2); @@ -362,9 +301,9 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { } for (std::size_t idx = 0U; idx < channelCount; idx++) { - channelId = *channelList + idx; - char* channelName = nullptr; - //if (ts3Functions.getChannelVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { + channelId = *channelList + idx; + char *channelName = nullptr; + if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == STATUS_OK) { std::string channelNameString(channelName); if (channelNameString.find(DEFAULT_MUMBLE_CHANNEL) != -1 || (!details_.at(0).empty() && channelNameString == name)) { @@ -379,9 +318,9 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { mumAPI.freeMemory(pluginID, (void *) &channelList); mumble_channelid_t bestChannelId = INVALID_MUMBLE_CHANNEL; - int32_t bestMatches = 0; - int32_t bestDistance = 10; - for (auto& element : channelMap) { + int32_t bestMatches = 0; + int32_t bestDistance = 10; + for (auto &element : channelMap) { std::string fullChannelName = element.second; // Full comparison if (fullChannelName.compare(name) == 0) { @@ -392,28 +331,28 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { // Word comparison const int32_t matches = getWordMatches(cleanChannelName, name); if (matches > bestMatches) { - bestMatches = matches; + bestMatches = matches; bestChannelId = element.first; continue; } // Char comparison const int32_t distance = levenshteinDistance(cleanChannelName, name); if (distance <= bestDistance) { - bestDistance = distance; + bestDistance = distance; bestChannelId = element.first; } } if (bestChannelId == INVALID_MUMBLE_CHANNEL) { if (!details_.at(0).empty()) { details_.at(0) = ""; - bestChannelId = static_cast(findChannelByNames(details_)); + bestChannelId = static_cast(findChannelByNames(details_)); } else if (defaultChannelId != INVALID_MUMBLE_CHANNEL) { bestChannelId = defaultChannelId; } } return bestChannelId; } - + return 0; } diff --git a/extensions/src/ACRE2Mumble/MumbleClient.h b/extensions/src/ACRE2Mumble/MumbleClient.h index 7f1201730..1fffd0361 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.h +++ b/extensions/src/ACRE2Mumble/MumbleClient.h @@ -2,17 +2,17 @@ #include "IClient.h" #include "MumbleFunctions.h" -#include + #include +#include #include -class CMumbleClient: public IClient { +class CMumbleClient : public IClient { public: - - CMumbleClient() = default; + CMumbleClient() = default; ~CMumbleClient() final = default; - acre::Result initialize( void ) final; + acre::Result initialize(void) final; acre::Result setMuted(const acre::id_t id_, const bool muted_) final; acre::Result setMuted(std::list idList_, const bool muted_) final; @@ -22,7 +22,7 @@ class CMumbleClient: public IClient { acre::Result stop() final; acre::Result start(const acre::id_t id_) final; - acre::Result exPersistVersion( void ); + acre::Result exPersistVersion(void); acre::Result setClientMetadata(const char *const data); @@ -33,22 +33,22 @@ class CMumbleClient: public IClient { bool getVAD(); /*! - * \brief Handles local player starting speaking. - * - * \param[in] speakingType_ ACRE speaking type - * - * \return acre::Result::ok if operation successful - */ + * \brief Handles local player starting speaking. + * + * \param[in] speakingType_ ACRE speaking type + * + * \return acre::Result::ok if operation successful + */ acre::Result localStartSpeaking(const acre::Speaking speakingType_) final; /*! - * \brief Handles local player starting speaking. - * - * \param[in] speakingType_ ACRE speaking type - * \param[in] radioId_ Unique radio ideintifier - * - * \return acre::Result::ok if operation successful - */ + * \brief Handles local player starting speaking. + * + * \param[in] speakingType_ ACRE speaking type + * \param[in] radioId_ Unique radio ideintifier + * + * \return acre::Result::ok if operation successful + */ acre::Result localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_) final; /*! @@ -58,18 +58,18 @@ class CMumbleClient: public IClient { * * \return acre::Result::ok if operation successful */ - acre::Result localStopSpeaking(const acre::Speaking speakingType_ ) final; + acre::Result localStopSpeaking(const acre::Speaking speakingType_) final; - std::string getTempFilePath( void ) final; + std::string getTempFilePath(void) final; std::string getConfigFilePath(void) final; acre::Result playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) final; - std::string getUniqueId( ) final; + std::string getUniqueId() final; acre::Result microphoneOpen(const bool status_) final; - acre::Result unMuteAll( void ) final; + acre::Result unMuteAll(void) final; acre::Result moveToServerChannel() final; acre::Result moveToPreviousChannel() final; diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index da707f43b..a1cf32fed 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -1,39 +1,30 @@ +#include "Log.h" +#include "MumbleClient.h" #include "MumbleCommandServer.h" - #include "MumbleFunctions.h" - #include "TextMessage.h" -#include "Log.h" - -#include "MumbleClient.h" extern MumbleAPI mumAPI; extern mumble_connection_t activeConnection; extern plugin_id_t pluginID; -acre::Result CMumbleCommandServer::initialize(void){ +acre::Result CMumbleCommandServer::initialize() { TRACE("enter"); return acre::Result::ok; } -acre::Result CMumbleCommandServer::shutdown(void) { +acre::Result CMumbleCommandServer::shutdown() { TRACE("enter"); return acre::Result::ok; } - -acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ +acre::Result CMumbleCommandServer::sendMessage(IMessage *msg) { LOCK(this); - /* - ts3Functions.sendPluginCommand((unsigned __int64)ts3Functions.getCurrentServerConnectionHandlerID(), - (const char*)this->getCommandId(), - (const char*)msg->getData(), - PluginCommandTarget_CURRENT_CHANNEL, NULL, NULL); - */ - mumble_userid_t* channelUsers = nullptr; - size_t userCount = 0U; + + mumble_userid_t *channelUsers = nullptr; + size_t userCount = 0U; mumble_channelid_t currentChannel; mumble_error_t err; err = mumAPI.getChannelOfUser(pluginID, activeConnection, this->getId(), ¤tChannel); @@ -46,12 +37,12 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ LOG("ERROR, UNABLE TO GET USERS IN CHANNEL: %d", err); return acre::Result::error; } - err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const char*)msg->getData(), msg->getLength(), "ACRE2"); + err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const char *) msg->getData(), msg->getLength(), "ACRE2"); if (err != ErrorCode::EC_OK) { LOG("ERROR, UNABLE TO SEND MESSAGE DATA: %d", err); return acre::Result::error; } - err = mumAPI.freeMemory(pluginID, (void *)channelUsers); + err = mumAPI.freeMemory(pluginID, (void *) channelUsers); if (err != ErrorCode::EC_OK) { LOG("ERROR, UNABLE TO FREE CHANNEL USER LIST: %d", err); return acre::Result::error; @@ -64,34 +55,32 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg){ return acre::Result::ok; } -acre::Result CMumbleCommandServer::handleMessage(unsigned char* data) { - return this->handleMessage(data, strlen((char*)data)); +acre::Result CMumbleCommandServer::handleMessage(unsigned char *data) { + return this->handleMessage(data, strlen((char *) data)); } -acre::Result CMumbleCommandServer::handleMessage(unsigned char* data, size_t length) { - CTextMessage* msg = nullptr; - //TRACE("recv: [%s]", data); - msg = new (std::nothrow) CTextMessage((char*)data, length); +acre::Result CMumbleCommandServer::handleMessage(unsigned char *data, size_t length) { + CTextMessage *msg = nullptr; + // TRACE("recv: [%s]", data); + msg = new (std::nothrow) CTextMessage((char *) data, length); if (CEngine::getInstance()->getRpcEngine() && (msg != nullptr)) { - CEngine::getInstance()->getRpcEngine()->runProcedure((IServer*)this, (IMessage*)msg); + CEngine::getInstance()->getRpcEngine()->runProcedure((IServer *) this, (IMessage *) msg); } return acre::Result::ok; } - -acre::Result CMumbleCommandServer::release(void) { +acre::Result CMumbleCommandServer::release() { return acre::Result::ok; } - // // constructor/destructor foo -// +// CMumbleCommandServer::CMumbleCommandServer(const acre::id_t id) { this->setId(id); } -CMumbleCommandServer::CMumbleCommandServer(void) { +CMumbleCommandServer::CMumbleCommandServer() { this->setCommandId(0); this->setConnected(true); } diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.h b/extensions/src/ACRE2Mumble/MumbleCommandServer.h index ec7b02d71..828344662 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.h +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.h @@ -1,18 +1,15 @@ #pragma once -#include "compat.h" -#include "Types.h" -#include "Macros.h" +#include "Engine.h" #include "IMessage.h" #include "IServer.h" - -#include "Engine.h" #include "Lockable.h" - +#include "Macros.h" #include "MumbleFunctions.h" +#include "Types.h" +#include "compat.h" -class CMumbleCommandServer : public IServer, public CLockable -{ +class CMumbleCommandServer : public IServer, public CLockable { public: CMumbleCommandServer(void); CMumbleCommandServer(const acre::id_t id); @@ -22,14 +19,13 @@ class CMumbleCommandServer : public IServer, public CLockable acre::Result shutdown(void) final; acre::Result sendMessage(IMessage *msg) final; - acre::Result handleMessage(unsigned char* msg) final; - acre::Result handleMessage(unsigned char* msg, size_t length) final; - + acre::Result handleMessage(unsigned char *msg) final; + acre::Result handleMessage(unsigned char *msg, size_t length) final; acre::Result release(void) final; inline void setCommandId(plugin_id_t value) noexcept { m_commandId = value; } - inline plugin_id_t getCommandId() const noexcept { return m_commandId; } + inline plugin_id_t getCommandId() const noexcept { return m_commandId; } inline void setConnected(const bool value) final { m_connected = value; } inline bool getConnected() const final { return m_connected; } diff --git a/extensions/src/ACRE2Mumble/MumbleFunctions.h b/extensions/src/ACRE2Mumble/MumbleFunctions.h index 5dbbe6b57..d51907a77 100644 --- a/extensions/src/ACRE2Mumble/MumbleFunctions.h +++ b/extensions/src/ACRE2Mumble/MumbleFunctions.h @@ -1,4 +1,4 @@ #pragma once -#include "MumblePlugin.h" #include "MumbleAPI.h" +#include "MumblePlugin.h" diff --git a/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp b/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp index f6ff06493..6a8240044 100644 --- a/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp +++ b/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp @@ -1,25 +1,6 @@ -//#include "compat.h" -//#include "Log.h" #include "MumbleFunctions.h" MumbleAPI mumAPI; - #pragma comment(lib, "x3daudio.lib") #pragma comment(lib, "shlwapi.lib") - -/* -[module(dll, name="acre2", version="1.0")]; - - -BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID) { - - if (reason == DLL_PROCESS_ATTACH){ - //g_Log = (Log *)new Log("acre.log"); - } - if (reason == DLL_PROCESS_DETACH) { - - } - return 1; -} -*/ diff --git a/extensions/src/ACRE2Shared/IClient.h b/extensions/src/ACRE2Shared/IClient.h index 2255847f7..50e4bf51c 100644 --- a/extensions/src/ACRE2Shared/IClient.h +++ b/extensions/src/ACRE2Shared/IClient.h @@ -1,58 +1,58 @@ #pragma once -#include "compat.h" -#include "Types.h" -#include "Macros.h" #include "ACRE_VECTOR.h" +#include "Macros.h" +#include "Types.h" +#include "compat.h" #include #include +#include #include #include #include -#include class IClient { public: - IClient() noexcept = default; + IClient() noexcept = default; virtual ~IClient() noexcept = default; - virtual acre::Result initialize( void ) = 0; + virtual acre::Result initialize(void) = 0; - virtual acre::Result setMuted(const acre::id_t id, const bool muted) = 0; + virtual acre::Result setMuted(const acre::id_t id, const bool muted) = 0; virtual acre::Result setMuted(std::list idList, const bool muted) = 0; virtual acre::Result getMuted(const acre::id_t id) = 0; - virtual acre::Result stop() = 0; + virtual acre::Result stop() = 0; virtual acre::Result start(const acre::id_t id) = 0; virtual acre::Result enableMicrophone(const bool status) = 0; virtual acre::Result microphoneOpen(const bool status) = 0; - virtual acre::Result localStartSpeaking(const acre::Speaking speakingType) = 0; + virtual acre::Result localStartSpeaking(const acre::Speaking speakingType) = 0; virtual acre::Result localStartSpeaking(const acre::Speaking speakingType, const std::string radioId) = 0; - virtual acre::Result localStopSpeaking(const acre::Speaking speakingType) = 0; + virtual acre::Result localStopSpeaking(const acre::Speaking speakingType) = 0; - virtual std::string getTempFilePath( void ) = 0; + virtual std::string getTempFilePath(void) = 0; virtual std::string getConfigFilePath(void) = 0; virtual std::string getUniqueId() = 0; virtual acre::Result playSound(std::string path, acre::vec3_fp32_t position, const float32_t volume, const int32_t looping) = 0; - virtual acre::Result unMuteAll( void ) = 0; + virtual acre::Result unMuteAll(void) = 0; - virtual acre::Result moveToServerChannel() = 0; - virtual acre::Result moveToPreviousChannel() = 0; + virtual acre::Result moveToServerChannel() = 0; + virtual acre::Result moveToPreviousChannel() = 0; virtual acre::Result updateChannelDetails(const std::vector details) = 0; - virtual acre::Result updateShouldSwitchChannel(const bool state) = 0; - virtual bool shouldSwitchChannel() = 0; - virtual bool getVAD() = 0; + virtual acre::Result updateShouldSwitchChannel(const bool state) = 0; + virtual bool shouldSwitchChannel() = 0; + virtual bool getVAD() = 0; virtual std::uint64_t findChannelByNames(std::vector details_) = 0; - + bool gethadVAD() const noexcept { return had_vad; } void sethadVAD(const bool value_) noexcept { had_vad = value_; } @@ -100,7 +100,7 @@ class IClient { void setState(acre::State value) noexcept { state = value; } protected: - virtual std::uint32_t getWordMatches(const std::string& string1_, const std::string& string2_) noexcept { + virtual std::uint32_t getWordMatches(const std::string &string1_, const std::string &string2_) noexcept { std::vector words1; std::vector words2; @@ -116,8 +116,8 @@ class IClient { } std::int32_t matches = 0; - for (auto& word1 : words1) { - for (auto& word2 : words2) { + for (auto &word1 : words1) { + for (auto &word2 : words2) { if (word1 == word2) { matches++; } @@ -126,26 +126,23 @@ class IClient { return matches; } - virtual std::uint32_t levenshteinDistance(const std::string& string1_, const std::string& string2_) noexcept { - std::int32_t length1 = string1_.size(); + virtual std::uint32_t levenshteinDistance(const std::string &string1_, const std::string &string2_) noexcept { + std::int32_t length1 = string1_.size(); const std::int32_t length2 = string2_.size(); const decltype(length1) columnStart = decltype(length1)(1); - decltype(length1)* const column = new decltype(length1)[length1 + 1]; + decltype(length1) *const column = new decltype(length1)[length1 + 1]; std::iota(column + columnStart, column + length1 + 1, columnStart); for (auto x = columnStart; x <= length2; x++) { - column[0] = x; + column[0] = x; std::int32_t lastDiagonal = x - columnStart; for (auto y = columnStart; y <= length1; y++) { - const int32_t oldDiagonal = column[y]; + const int32_t oldDiagonal = column[y]; const std::initializer_list possibilities = { - column[y] + 1, - column[y - 1] + 1, - lastDiagonal + (string1_[y - 1] == string2_[x - 1] ? 0 : 1) - }; - column[y] = min(possibilities); + column[y] + 1, column[y - 1] + 1, lastDiagonal + (string1_[y - 1] == string2_[x - 1] ? 0 : 1)}; + column[y] = min(possibilities); lastDiagonal = oldDiagonal; } } @@ -156,28 +153,26 @@ class IClient { virtual std::string removeSubstrings(std::string string_, std::string substring_) noexcept { const std::string::size_type substringLength = substring_.length(); - for (auto iterator = string_.find(substring_); - iterator != std::string::npos; - iterator = string_.find(substring_)) + for (auto iterator = string_.find(substring_); iterator != std::string::npos; iterator = string_.find(substring_)) string_.erase(iterator, substringLength); return string_; } private: - bool had_vad = false; + bool had_vad = false; bool input_active = false; - bool on_radio = false; + bool on_radio = false; std::int32_t speaking_state = 0; - bool radioPTTDown = false; - bool intercom_ptt_down = false; - bool main_ptt_down = false; - bool direct_first = false; + bool radioPTTDown = false; + bool intercom_ptt_down = false; + bool main_ptt_down = false; + bool direct_first = false; bool hit_speaking_event = false; - bool x3d_initialized = false; + bool x3d_initialized = false; - std::uint32_t speaker_mask = 0U; + std::uint32_t speaker_mask = 0U; std::uint64_t previous_channel = 0LU; std::vector channel_details; @@ -185,4 +180,3 @@ class IClient { acre::State state = acre::State::stopped; }; - From 0eca5f834bd615eee7861d2ac6ce9ebf105987e0 Mon Sep 17 00:00:00 2001 From: Magnetar Date: Tue, 9 Jun 2020 10:18:29 +0200 Subject: [PATCH 040/104] Fix possible overflow --- extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index ce83b178c..60d8ef844 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -90,7 +90,7 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin } //} - for (int32_t c = 0; c <= mixdownSampleLength - 1U; ++c) { + for (uint32_t c = 0; c <= mixdownSampleLength - 1U; ++c) { float sample = outputPCM[c]; if (sample > 1.0F) { sample = 1.0F; @@ -102,7 +102,7 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin CEngine::getInstance()->getSoundEngine()->onEditMixedPlaybackVoiceDataEvent(mixdownSamples, sampleCount, channelCount, speakerMask); - for (int32_t c = 0; c <= mixdownSampleLength - 1; ++c) { + for (uint32_t c = 0; c <= mixdownSampleLength - 1; ++c) { float mixedSample = 0.0F; if (mixdownSamples[c] > 0) { mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); From 7512de6a29b3832f80bac236cf3c18b5cd966752 Mon Sep 17 00:00:00 2001 From: Magnetar Date: Tue, 9 Jun 2020 10:25:49 +0200 Subject: [PATCH 041/104] Use constexpr --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 36 +-- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 287 +++++++++--------- 2 files changed, 165 insertions(+), 158 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index da241e2bf..f57461e69 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -10,15 +10,15 @@ #pragma comment(lib, "Shlwapi.lib") -#define INVALID_MUMBLE_CHANNEL -1 -#define DEFAULT_MUMBLE_CHANNEL "ACRE" +static constexpr std::int32_t = -1; +constexpr char default_mumble_channel[] = "ACRE"; extern MumbleAPI mumAPI; extern mumble_connection_t activeConnection; extern plugin_id_t pluginID; -acre::Result CMumbleClient::initialize(void) { - setPreviousChannel(INVALID_MUMBLE_CHANNEL); +acre::Result CMumbleClient::initialize() { + setPreviousChannel(invalid_mumble_channel); return acre::Result::ok; } @@ -242,15 +242,15 @@ acre::Result CMumbleClient::moveToServerChannel() { std::vector details = getChannelDetails(); if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == STATUS_OK) { - mumble_channelid_t currentChannelId = INVALID_MUMBLE_CHANNEL; + mumble_channelid_t currentChannelId = invalid_mumble_channel; if ((mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) && - (getPreviousChannel() == INVALID_MUMBLE_CHANNEL)) { + (getPreviousChannel() == invalid_mumble_channel)) { setPreviousChannel(currentChannelId); } const mumble_channelid_t channelId = static_cast(findChannelByNames(details)); - if ((channelId != INVALID_MUMBLE_CHANNEL) && (channelId != currentChannelId)) { + if ((channelId != invalid_mumble_channel) && (channelId != currentChannelId)) { std::string password; if (details.at(1) != "" && details.at(0) != "") { password = details.at(1); @@ -271,16 +271,16 @@ acre::Result CMumbleClient::moveToPreviousChannel() { mumble_userid_t clientId = -1; if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == STATUS_OK) { - mumble_channelid_t currentChannelId = INVALID_MUMBLE_CHANNEL; + mumble_channelid_t currentChannelId = invalid_mumble_channel; if (mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) { const mumble_channelid_t channelId = static_cast(getPreviousChannel()); - if (channelId != INVALID_MUMBLE_CHANNEL && channelId != currentChannelId) { + if (channelId != invalid_mumble_channel && channelId != currentChannelId) { mumAPI.requestUserMove(pluginID, activeConnection, clientId, channelId, ""); } } } - setPreviousChannel(INVALID_MUMBLE_CHANNEL); + setPreviousChannel(invalid_mumble_channel); } return acre::Result::ok; @@ -292,8 +292,8 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { std::size_t channelCount = 0U; if (mumAPI.getAllChannels(pluginID, activeConnection, &channelList, &channelCount) == STATUS_OK) { - mumble_channelid_t channelId = INVALID_MUMBLE_CHANNEL; - mumble_channelid_t defaultChannelId = INVALID_MUMBLE_CHANNEL; + mumble_channelid_t channelId = invalid_mumble_channel; + mumble_channelid_t defaultChannelId = invalid_mumble_channel; std::map channelMap; std::string name = details_.at(2); if (details_.at(0) != "") { @@ -306,8 +306,8 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == STATUS_OK) { std::string channelNameString(channelName); - if (channelNameString.find(DEFAULT_MUMBLE_CHANNEL) != -1 || (!details_.at(0).empty() && channelNameString == name)) { - if (channelNameString == DEFAULT_MUMBLE_CHANNEL) { + if (channelNameString.find(default_mumble_channel) != -1 || (!details_.at(0).empty() && channelNameString == name)) { + if (channelNameString == default_mumble_channel) { defaultChannelId = channelId; } channelMap.emplace(channelId, channelNameString); @@ -317,7 +317,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { mumAPI.freeMemory(pluginID, (void *) &channelList); - mumble_channelid_t bestChannelId = INVALID_MUMBLE_CHANNEL; + mumble_channelid_t bestChannelId = invalid_mumble_channel; int32_t bestMatches = 0; int32_t bestDistance = 10; for (auto &element : channelMap) { @@ -327,7 +327,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { bestChannelId = element.first; break; } - const std::string cleanChannelName = removeSubstrings(fullChannelName, DEFAULT_MUMBLE_CHANNEL); + const std::string cleanChannelName = removeSubstrings(fullChannelName, default_mumble_channel); // Word comparison const int32_t matches = getWordMatches(cleanChannelName, name); if (matches > bestMatches) { @@ -342,11 +342,11 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { bestChannelId = element.first; } } - if (bestChannelId == INVALID_MUMBLE_CHANNEL) { + if (bestChannelId == invalid_mumble_channel) { if (!details_.at(0).empty()) { details_.at(0) = ""; bestChannelId = static_cast(findChannelByNames(details_)); - } else if (defaultChannelId != INVALID_MUMBLE_CHANNEL) { + } else if (defaultChannelId != invalid_mumble_channel) { bestChannelId = defaultChannelId; } } diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index dcd393c66..0bd14bdfb 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -12,21 +12,21 @@ //#include "Log.h" #include "Macros.h" #include "Shlwapi.h" +#include "command_options.hpp" #include "mumble_plugin.hpp" #include "shlobj.h" #include "ts3_plugin.hpp" -#include "command_options.hpp" #include #include #include #include +#include #include #include #include #include #include -#include #pragma comment(lib, "shlwapi.lib") @@ -67,7 +67,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { return; } - const bool skip_ts_plugin = cmd_args.has_argument("-skipAcreTSPluginCopy"); + const bool skip_ts_plugin = cmd_args.has_argument("-skipAcreTSPluginCopy"); const bool skip_mumble_plugin = cmd_args.has_argument("-skipAcreMumblePluginCopy"); std::string test = cmd_args.get_argument("-mumblePath"); @@ -76,181 +76,188 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); switch (command) { - case SteamCommand::check: { - strncpy(output, "1", outputSize); - return; - } - case SteamCommand::get_path: { - std::string path; - if (skip_ts_plugin) { - path = ts3_plugin.read_reg_value(HKEY_LOCAL_MACHINE, ts3_plugin.get_registry_key().c_str(), "", false); + case SteamCommand::check: { + strncpy(output, "1", outputSize); + return; } + case SteamCommand::get_path: { + std::string path; + if (skip_ts_plugin) { + path = ts3_plugin.read_reg_value(HKEY_LOCAL_MACHINE, ts3_plugin.get_registry_key().c_str(), "", false); + } - if (skip_mumble_plugin) { - path.append("\n" + mumble_plugin.read_reg_value(HKEY_LOCAL_MACHINE, mumble_plugin.get_registry_key().c_str(), "", false)); + if (skip_mumble_plugin) { + path.append("\n" + mumble_plugin.read_reg_value(HKEY_LOCAL_MACHINE, mumble_plugin.get_registry_key().c_str(), "", false)); + } + strncpy(output, path.c_str(), outputSize); + return; } - strncpy(output, path.c_str(), outputSize); - return; - } - case SteamCommand::do_copy: { - std::string current_version = params; + case SteamCommand::do_copy: { + std::string current_version = params; - // Check ACRE2 installation - if (!ts3_plugin.check_acre_installation() || !mumble_plugin.check_acre_installation()) { - std::vector missing_plugins = ts3_plugin.get_missing_acre_plugins(); - missing_plugins.insert(missing_plugins.end(), std::begin(mumble_plugin.get_missing_acre_plugins()), - std::end(mumble_plugin.get_missing_acre_plugins())); + // Check ACRE2 installation + if (!ts3_plugin.check_acre_installation() || !mumble_plugin.check_acre_installation()) { + std::vector missing_plugins = ts3_plugin.get_missing_acre_plugins(); + missing_plugins.insert(missing_plugins.end(), std::begin(mumble_plugin.get_missing_acre_plugins()), + std::end(mumble_plugin.get_missing_acre_plugins())); - std::ostringstream oss; - oss << "ACRE2 was unable to find ACRE 2 plugin files.\n\n"; - for (const auto &missing : missing_plugins) { - oss << "\t" << missing << "\n"; + std::ostringstream oss; + oss << "ACRE2 was unable to find ACRE 2 plugin files.\n\n"; + for (const auto &missing : missing_plugins) { + oss << "\t" << missing << "\n"; + } + oss << "\n\n" + << "The ACRE2 installation is likely corrupted. Please reinstall."; + + const std::int32_t result = + MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_OK | MB_ICONERROR); + TerminateProcess(GetCurrentProcess(), 0); + return; } - oss << "\n\n" - << "The ACRE2 installation is likely corrupted. Please reinstall."; - const std::int32_t result = MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_OK | MB_ICONERROR); - TerminateProcess(GetCurrentProcess(), 0); - return; - } + const bool ts3_locations_success = ts3_plugin.collect_plugin_locations(); + const bool mumble_locations_success = mumble_plugin.collect_plugin_locations(); + + if (!ts3_locations_success && !mumble_locations_success) { + const std::int32_t result = MessageBoxA(nullptr, + "ACRE2 was unable to find a TeamSpeak 3 or a Mumble installation. If you do have an installation please copy the plugins " + "yourself or reinstall TeamSpeak 3. \n\n If you are sure you have Mumble and/or TeamSpeak 3 installed and wish to " + "prevent this message " + "from appearing again remove ACRE2Steam.dll and ACRE2Steam_x64.dll from your @acre2 folder.\n\nContinue anyway?", + "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); + if (result == IDYES) { + strncpy(output, "[-3,true]", outputSize); + return; + } - const bool ts3_locations_success = ts3_plugin.collect_plugin_locations(); - const bool mumble_locations_success = mumble_plugin.collect_plugin_locations(); - - if (!ts3_locations_success && !mumble_locations_success) { - const std::int32_t result = MessageBoxA(nullptr, - "ACRE2 was unable to find a TeamSpeak 3 or a Mumble installation. If you do have an installation please copy the plugins " - "yourself or reinstall TeamSpeak 3. \n\n If you are sure you have Mumble and/or TeamSpeak 3 installed and wish to prevent this message " - "from appearing again remove ACRE2Steam.dll and ACRE2Steam_x64.dll from your @acre2 folder.\n\nContinue anyway?", - "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); - if (result == IDYES) { - strncpy(output, "[-3,true]", outputSize); + TerminateProcess(GetCurrentProcess(), 0); return; } - TerminateProcess(GetCurrentProcess(), 0); - return; - } - - bool try_copy = false; + bool try_copy = false; - do { - std::future update_ts3 = std::async(std::launch::async, [&]() {return ts3_plugin.handle_update_plugin(); }); - std::future update_mumble = std::async(std::launch::async, [&]() {return mumble_plugin.handle_update_plugin(); }); + do { + std::future update_ts3 = + std::async(std::launch::async, [&]() { return ts3_plugin.handle_update_plugin(); }); + std::future update_mumble = + std::async(std::launch::async, [&]() { return mumble_plugin.handle_update_plugin(); }); - const idi::acre::UpdateCode ts3_update_result = update_ts3.get(); - const idi::acre::UpdateCode mumble_update_result = update_mumble.get(); + const idi::acre::UpdateCode ts3_update_result = update_ts3.get(); + const idi::acre::UpdateCode mumble_update_result = update_mumble.get(); - std::string error_msg; - const bool update_ts3_ok = (ts3_update_result != idi::acre::UpdateCode::update_failed) && (ts3_update_result != idi::acre::UpdateCode::other); - if (!update_ts3_ok) { - error_msg = ts3_plugin.get_last_error_message(); - } - - const bool update_mumble_ok = - (mumble_update_result != idi::acre::UpdateCode::update_failed) && (mumble_update_result != idi::acre::UpdateCode::other); - if (!update_mumble_ok) { - error_msg = mumble_plugin.get_last_error_message(); - } + std::string error_msg; + const bool update_ts3_ok = + (ts3_update_result != idi::acre::UpdateCode::update_failed) && (ts3_update_result != idi::acre::UpdateCode::other); + if (!update_ts3_ok) { + error_msg = ts3_plugin.get_last_error_message(); + } - if (!update_ts3_ok || !update_mumble_ok) { - std::ostringstream oss; - oss << "ACRE2 was unable to copy the Mumble/TeamSpeak 3 plugin. Please check if you have write access to the plugin folder, " - << "close any instances of Mumble and/or TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you would like to close Arma 3 " - << "click Cancel. Press Continue to launch Arma 3 regardless.\n\n" - << error_msg; - const int32_t result = - MessageBoxA(nullptr, (LPCSTR)oss.str().c_str(), "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); - if (result == IDCANCEL) { - TerminateProcess(GetCurrentProcess(), 0); - return; + const bool update_mumble_ok = + (mumble_update_result != idi::acre::UpdateCode::update_failed) && (mumble_update_result != idi::acre::UpdateCode::other); + if (!update_mumble_ok) { + error_msg = mumble_plugin.get_last_error_message(); } - else if (result == IDCONTINUE) { - sprintf(output, "[-4,true,%d %d]", ts3_plugin.get_last_error(), mumble_plugin.get_last_error()); - return; + + if (!update_ts3_ok || !update_mumble_ok) { + std::ostringstream oss; + oss << "ACRE2 was unable to copy the Mumble/TeamSpeak 3 plugin. Please check if you have write access to the plugin " + "folder, " + << "close any instances of Mumble and/or TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you would like " + "to close Arma 3 " + << "click Cancel. Press Continue to launch Arma 3 regardless.\n\n" + << error_msg; + const int32_t result = MessageBoxA( + nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); + if (result == IDCANCEL) { + TerminateProcess(GetCurrentProcess(), 0); + return; + } else if (result == IDCONTINUE) { + sprintf(output, "[-4,true,%d %d]", ts3_plugin.get_last_error(), mumble_plugin.get_last_error()); + return; + } + } else { + try_copy = true; + + // Update was not necessary. + if ((ts3_update_result == idi::acre::UpdateCode::update_not_necessary) && + (mumble_update_result == idi::acre::UpdateCode::update_not_necessary)) { // No update was copied etc. + strncpy(output, "[0]", outputSize); + return; + } } - } else { - try_copy = true; + } while (!try_copy); - // Update was not necessary. - if ((ts3_update_result == idi::acre::UpdateCode::update_not_necessary) && - (mumble_update_result == idi::acre::UpdateCode::update_not_necessary)) { // No update was copied etc. - strncpy(output, "[0]", outputSize); - return; + std::ostringstream oss; + oss << "A new version of ACRE2 (" << current_version << ") has been installed!\n\n"; + + std::string found_paths; + if (!ts3_plugin.get_updated_paths().empty()) { + oss << "The TeamSpeak 3 plugins have been copied to the following location(s):\n"; + for (const auto &path : ts3_plugin.get_updated_paths()) { + oss << path << "\n"; + found_paths.append(path + "\n"); } + + oss << "\n"; } - } while (!try_copy); - std::ostringstream oss; - oss << "A new version of ACRE2 (" << current_version << ") has been installed!\n\n"; + if (!mumble_plugin.get_updated_paths().empty()) { + oss << "The Mumble plugins have been copied to the following location(s):\n"; + for (const auto &path : mumble_plugin.get_updated_paths()) { + oss << path << "\n"; + found_paths.append(path + "\n"); + } - std::string found_paths; - if (!ts3_plugin.get_updated_paths().empty()) { - oss << "The TeamSpeak 3 plugins have been copied to the following location(s):\n"; - for (const auto &path : ts3_plugin.get_updated_paths()) { - oss << path << "\n"; - found_paths.append(path + "\n"); + oss << "\n"; } - oss << "\n"; - } - + if (!ts3_plugin.get_removed_paths().empty()) { + oss << "The TeamSpeak 3 plugin has been removed from the following location(s):\n"; + for (const auto &path : ts3_plugin.get_removed_paths()) { + oss << path << "\n"; + } - if (!mumble_plugin.get_updated_paths().empty()) { - oss << "The Mumble plugins have been copied to the following location(s):\n"; - for (const auto &path : mumble_plugin.get_updated_paths()) { - oss << path << "\n"; - found_paths.append(path + "\n"); + oss << "\n"; } - oss << "\n"; - } - - if (!ts3_plugin.get_removed_paths().empty()) { - oss << "The TeamSpeak 3 plugin has been removed from the following location(s):\n"; - for (const auto &path : ts3_plugin.get_removed_paths()) { - oss << path << "\n"; - } + if (!mumble_plugin.get_removed_paths().empty()) { + oss << "The Mumble plugin has been removed from the following location(s):\n"; + for (const auto &path : mumble_plugin.get_removed_paths()) { + oss << path << "\n"; + } - oss << "\n"; - } - - if (!mumble_plugin.get_removed_paths().empty()) { - oss << "The Mumble plugin has been removed from the following location(s):\n"; - for (const auto &path : mumble_plugin.get_removed_paths()) { - oss << path << "\n"; + oss << "\n"; } - oss << "\n"; - } - - oss << "If this is NOT valid, please uninstall all versions of Mumble and/or TeamSpeak 3 and reinstall both it and ACRE2 or copy the plugins " - << "manually to your correct installation.\n\n"; - oss << "If this appears to be the correct folder(s) please remember to enable the plugin in Mumble and/or TeamSpeak 3!"; - const int32_t result = MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Success", MB_OK | MB_ICONINFORMATION); + oss << "If this is NOT valid, please uninstall all versions of Mumble and/or TeamSpeak 3 and reinstall both it and ACRE2 or " + "copy the plugins " + << "manually to your correct installation.\n\n"; + oss << "If this appears to be the correct folder(s) please remember to enable the plugin in Mumble and/or TeamSpeak 3!"; + const int32_t result = + MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Success", MB_OK | MB_ICONINFORMATION); - sprintf(output, "[1,\"%s\"]", found_paths.c_str()); - return; - } - default: - return; + sprintf(output, "[1,\"%s\"]", found_paths.c_str()); + return; + } + default: + return; } } -void Init(void) {} +void Init() {} -void Cleanup(void) {} +void Cleanup() {} BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH: - Init(); - break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - Cleanup(); - break; + case DLL_PROCESS_ATTACH: + Init(); + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + Cleanup(); + break; } return TRUE; } From b07fc74ae5043cbab3f5b34bbb04f4b8650300e5 Mon Sep 17 00:00:00 2001 From: Magnetar Date: Tue, 9 Jun 2020 10:42:19 +0200 Subject: [PATCH 042/104] Futher improvements. Code clarity --- .../ACRE2DistortionTestPlugin/TS3Client.cpp | 191 ++++++++--------- extensions/src/ACRE2Mumble/MumbleClient.cpp | 27 ++- .../src/ACRE2Mumble/MumbleCommandServer.cpp | 12 +- extensions/src/ACRE2Shared/IClient.h | 2 +- extensions/src/ACRE2TS/TS3Client.cpp | 201 +++++++++--------- extensions/src/ACRE2TS/TS3Client.h | 51 +++-- 6 files changed, 234 insertions(+), 250 deletions(-) diff --git a/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp b/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp index 3d9c38d15..4dfb55b45 100644 --- a/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp +++ b/extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp @@ -1,14 +1,12 @@ -#include "compat.h" - -#include "TS3Client.h" +#include "AcreSettings.h" #include "Engine.h" -#include "Types.h" +#include "Log.h" +#include "Shlwapi.h" +#include "TS3Client.h" #include "TsFunctions.h" +#include "Types.h" +#include "compat.h" #include "shlobj.h" -#include "Shlwapi.h" -#include "Log.h" - -#include "AcreSettings.h" #pragma comment(lib, "Shlwapi.lib") @@ -17,7 +15,7 @@ extern TS3Functions ts3Functions; -//TS3Functions CTS3Client::ts3Functions; +// TS3Functions CTS3Client::ts3Functions; acre::Result CTS3Client::initialize(void) { setPreviousChannel(INVALID_TS3_CHANNEL); @@ -41,12 +39,10 @@ acre::Result CTS3Client::setMuted(const acre::id_t id_, const bool muted_) { } acre::Result CTS3Client::setMuted(std::list idList_, bool muted_) { - return acre::Result::ok; } acre::Result CTS3Client::getMuted(acre::id_t id_) { - return acre::Result::ok; } @@ -58,7 +54,6 @@ acre::Result CTS3Client::stop() { this->m_versionThreadHandle.join(); } this->setState(acre::State::stopped); - } return acre::Result::ok; } @@ -80,27 +75,26 @@ acre::Result CTS3Client::start(const acre::id_t id_) { return acre::Result::ok; } -acre::Result CTS3Client::exPersistVersion( void ) { - +acre::Result CTS3Client::exPersistVersion(void) { ts3Functions.setClientSelfVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_META_DATA, ACRE_VERSION_METADATA); ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); ts3Functions.printMessageToCurrentTab("ACRE2 loaded and initialized"); ts3Functions.printMessageToCurrentTab(ACRE_VERSION_METADATA); - clock_t run = clock() / CLOCKS_PER_SEC; + clock_t run = clock() / CLOCKS_PER_SEC; clock_t delta = run; while (this->getState() == acre::State::running && CEngine::getInstance()->getExternalServer()) { - delta = (clock() / CLOCKS_PER_SEC) - run; - if (delta > (PERSIST_VERSION_TIMER / 1000) ) { + if (delta > (PERSIST_VERSION_TIMER / 1000)) { char selfVariableBuffer[4096]; if (CEngine::getInstance()->getGameServer()->getConnected()) { _snprintf_s(selfVariableBuffer, 4094, "%s\nArma Connected: Yes", ACRE_VERSION_METADATA); } else { _snprintf_s(selfVariableBuffer, 4094, "%s\nArma Connected: No", ACRE_VERSION_METADATA); } - ts3Functions.setClientSelfVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_META_DATA, selfVariableBuffer); + ts3Functions.setClientSelfVariableAsString( + ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_META_DATA, selfVariableBuffer); ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); run = clock() / CLOCKS_PER_SEC; } @@ -114,7 +108,7 @@ acre::Result CTS3Client::exPersistVersion( void ) { bool CTS3Client::getVAD() { char *data; bool returnValue = false; - uint32_t res = ts3Functions.getPreProcessorConfigValue(ts3Functions.getCurrentServerConnectionHandlerID(), "vad", &data); + uint32_t res = ts3Functions.getPreProcessorConfigValue(ts3Functions.getCurrentServerConnectionHandlerID(), "vad", &data); if (!res) { if (!strcmp(data, "true")) { returnValue = true; @@ -208,7 +202,7 @@ acre::Result CTS3Client::localStopSpeaking(const acre::Speaking speakingType_) { resendDirectSpeaking = true; } } else if (this->getSpeakingState() == STATUS_TALKING) { - resendDirectSpeaking = true; + resendDirectSpeaking = true; } } @@ -226,9 +220,10 @@ acre::Result CTS3Client::enableMicrophone(const bool status_) { if (currentStatus != status_) { uint32_t res = 0u; if (status_) { - res = ts3Functions.setClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, MUTEINPUT_NONE); + res = ts3Functions.setClientSelfVariableAsInt( + ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, MUTEINPUT_NONE); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("Error toggling microphone enabled: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -236,9 +231,10 @@ acre::Result CTS3Client::enableMicrophone(const bool status_) { return acre::Result::ok; } } else { - res = ts3Functions.setClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, MUTEINPUT_MUTED); + res = ts3Functions.setClientSelfVariableAsInt( + ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, MUTEINPUT_MUTED); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("Error, failed to disable microphone input: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -248,7 +244,7 @@ acre::Result CTS3Client::enableMicrophone(const bool status_) { } res = ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); if (!((res == ERROR_ok) || (res == ERROR_ok_no_update))) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("STOP TALKING: Error flushing after toggling microphone muted: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -260,11 +256,11 @@ acre::Result CTS3Client::enableMicrophone(const bool status_) { } bool CTS3Client::getInputStatus() { - bool status = false; - int32_t ret = 0u; + bool status = false; + int32_t ret = 0u; uint32_t res = ts3Functions.getClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, &ret); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("Error querying microphone input status: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -280,16 +276,16 @@ bool CTS3Client::getInputStatus() { } acre::Result CTS3Client::playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) { - if (!PathFileExistsA(path_.c_str())) { return acre::Result::error; } char soundpackDb[32]; uint32_t ret = 0u; - uint32_t res = ts3Functions.getClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_OUTPUT_MUTED, (int32_t *) &ret); + uint32_t res = + ts3Functions.getClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_OUTPUT_MUTED, (int32_t *) &ret); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("Error checking playback status: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -302,31 +298,25 @@ acre::Result CTS3Client::playSound(std::string path_, acre::vec3_fp32_t position } // create a volume ranged from -40 to 0dB change - _snprintf_s(soundpackDb, 32, "%f", (-40.0f + (40.0f * volume_) ) ); + _snprintf_s(soundpackDb, 32, "%f", (-40.0f + (40.0f * volume_))); // change the soundpack volume for this squawks volume - ts3Functions.setPlaybackConfigValue(ts3Functions.getCurrentServerConnectionHandlerID(), - "volume_factor_wave", - soundpackDb); + ts3Functions.setPlaybackConfigValue(ts3Functions.getCurrentServerConnectionHandlerID(), "volume_factor_wave", soundpackDb); TS3_VECTOR vector = {position_.x, position_.z, position_.y}; TRACE("HIT [%f,%f,%f]", vector.x, vector.z, vector.y); uint64_t playHandle; - ret = ts3Functions.playWaveFileHandle(ts3Functions.getCurrentServerConnectionHandlerID(), - path_.c_str(), - looping_, - &playHandle); - ret = ts3Functions.set3DWaveAttributes(ts3Functions.getCurrentServerConnectionHandlerID(), - playHandle, - &vector); + ret = ts3Functions.playWaveFileHandle(ts3Functions.getCurrentServerConnectionHandlerID(), path_.c_str(), looping_, &playHandle); + ret = ts3Functions.set3DWaveAttributes(ts3Functions.getCurrentServerConnectionHandlerID(), playHandle, &vector); return acre::Result::ok; } -std::string CTS3Client::getUniqueId( ) { +std::string CTS3Client::getUniqueId() { char *uniqueId; std::string serverUniqueId = ""; - uint32_t res = ts3Functions.getServerVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), VIRTUALSERVER_UNIQUE_IDENTIFIER, &uniqueId); + uint32_t res = ts3Functions.getServerVariableAsString( + ts3Functions.getCurrentServerConnectionHandlerID(), VIRTUALSERVER_UNIQUE_IDENTIFIER, &uniqueId); if (res == ERROR_ok) { serverUniqueId = std::string(uniqueId); if (uniqueId) { @@ -352,7 +342,7 @@ std::string CTS3Client::getConfigFilePath(void) { return tempFolder; } -std::string CTS3Client::getTempFilePath( void ) { +std::string CTS3Client::getTempFilePath(void) { char tempPath[MAX_PATH - 14]; GetTempPathA(sizeof(tempPath), tempPath); std::string tempFolder = std::string(tempPath); @@ -375,9 +365,10 @@ acre::Result CTS3Client::microphoneOpen(bool status_) { this->setInputActive(false); } - uint32_t res = ts3Functions.setClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_DEACTIVATED, micStatus); + uint32_t res = + ts3Functions.setClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_DEACTIVATED, micStatus); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("STOP TALKING: Error toggling push-to-talk: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -387,7 +378,7 @@ acre::Result CTS3Client::microphoneOpen(bool status_) { res = ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); if (!(res == ERROR_ok || res == ERROR_ok_no_update)) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("STOP TALKING: Error flushing after toggling push-to-talk: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -397,53 +388,51 @@ acre::Result CTS3Client::microphoneOpen(bool status_) { return acre::Result::ok; } -acre::Result CTS3Client::unMuteAll( void ) { +acre::Result CTS3Client::unMuteAll(void) { anyID clientId; anyID *clientList; - uint32_t total_retries = 0; + uint32_t total_retries = 0; uint32_t total_intentional_runs = 0; - //for (total_intentional_runs = 0; total_intentional_runs < 3; total_intentional_runs++) { - uint32_t res = ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId); - if (res == ERROR_ok) { - - res = ERROR_undefined; - for (total_retries = 0; (total_retries < 5) && (res != ERROR_ok); total_retries++) { - res = ts3Functions.getClientList(ts3Functions.getCurrentServerConnectionHandlerID(), &clientList); - if (res == ERROR_ok) { - res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), clientList, NULL); - //if (res != ERROR_ok) { - // Sleep(500 * total_retries); - //} - ts3Functions.freeMemory(clientList); - } - } - - /* - /* - This was the alternative method originally, but it was hitting the spam threshold */ - /* Disable this method + // for (total_intentional_runs = 0; total_intentional_runs < 3; total_intentional_runs++) { + uint32_t res = ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId); + if (res == ERROR_ok) { + res = ERROR_undefined; + for (total_retries = 0; (total_retries < 5) && (res != ERROR_ok); total_retries++) { res = ts3Functions.getClientList(ts3Functions.getCurrentServerConnectionHandlerID(), &clientList); if (res == ERROR_ok) { - for (x=0;clientList[x]!=0 && total_retries < 20;x++) { - anyID tempList[2]; - uint32_t tries_on_client; - - tempList[0] = (anyID)clientList[x]; - tempList[1] = 0x0000; - - res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), clientList, NULL); - for (tries_on_client = 0; tries_on_client < 5 && total_retries < 20 && res != ERROR_ok; tries_on_client++, total_retries++) { - res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), tempList, NULL); - if (res != ERROR_ok) { - Sleep(500 * tries_on_client); - } - } - } + res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), clientList, NULL); + // if (res != ERROR_ok) { + // Sleep(500 * total_retries); + //} ts3Functions.freeMemory(clientList); } - */ } + + /* + /* - This was the alternative method originally, but it was hitting the spam threshold */ + /* Disable this method + res = ts3Functions.getClientList(ts3Functions.getCurrentServerConnectionHandlerID(), &clientList); + if (res == ERROR_ok) { + for (x=0;clientList[x]!=0 && total_retries < 20;x++) { + anyID tempList[2]; + uint32_t tries_on_client; + + tempList[0] = (anyID)clientList[x]; + tempList[1] = 0x0000; + + res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), clientList, NULL); + for (tries_on_client = 0; tries_on_client < 5 && total_retries < 20 && res != ERROR_ok; tries_on_client++, total_retries++) + { res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), tempList, NULL); if (res != ERROR_ok) + { Sleep(500 * tries_on_client); + } + } + } + ts3Functions.freeMemory(clientList); + } + */ + } // Sleep(500); //} return acre::Result::ok; @@ -456,7 +445,9 @@ acre::Result CTS3Client::moveToServerChannel() { if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; - if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousChannel() == INVALID_TS3_CHANNEL) { + if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == + ERROR_ok && + getPreviousChannel() == INVALID_TS3_CHANNEL) { setPreviousChannel(currentChannelId); } @@ -466,7 +457,8 @@ acre::Result CTS3Client::moveToServerChannel() { if (details.at(1) != "" && details.at(0) != "") { password = details.at(1); } - ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr); + ts3Functions.requestClientMove( + ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr); } } } @@ -479,7 +471,8 @@ acre::Result CTS3Client::moveToPreviousChannel() { anyID clientId; if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; - if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok) { + if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == + ERROR_ok) { const uint64_t channelId = getPreviousChannel(); if (channelId != INVALID_TS3_CHANNEL && channelId != currentChannelId) { ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, "", nullptr); @@ -494,7 +487,7 @@ acre::Result CTS3Client::moveToPreviousChannel() { uint64_t CTS3Client::findChannelByNames(std::vector details_) { uint64_t *channelList; if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { - uint64_t channelId = INVALID_TS3_CHANNEL; + uint64_t channelId = INVALID_TS3_CHANNEL; uint64_t defaultChannelId = INVALID_TS3_CHANNEL; std::map channelMap; std::string name = details_.at(2); @@ -504,8 +497,9 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { while (*channelList) { channelId = *channelList; channelList++; - char* channelName; - if (ts3Functions.getChannelVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { + char *channelName; + if (ts3Functions.getChannelVariableAsString( + ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { std::string channelNameString = std::string(channelName); if (channelNameString.find(DEFAULT_TS3_CHANNEL) != -1 || (details_.at(0) != "" && channelNameString == name)) { if (channelNameString == DEFAULT_TS3_CHANNEL) { @@ -517,9 +511,9 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { } uint64_t bestChannelId = INVALID_TS3_CHANNEL; - int32_t bestMatches = 0; - int32_t bestDistance = 10; - for (auto& element : channelMap) { + int32_t bestMatches = 0; + int32_t bestDistance = 10; + for (auto &element : channelMap) { std::string fullChannelName = element.second; // Full comparison if (fullChannelName.compare(name) == 0) { @@ -530,20 +524,20 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { // Word comparison const int32_t matches = getWordMatches(cleanChannelName, name); if (matches > bestMatches) { - bestMatches = matches; + bestMatches = matches; bestChannelId = element.first; continue; } // Char comparison const int32_t distance = levenshteinDistance(cleanChannelName, name); if (distance <= bestDistance) { - bestDistance = distance; + bestDistance = distance; bestChannelId = element.first; } } if (bestChannelId == INVALID_TS3_CHANNEL) { - if (details_.at(0) != "") { - details_.at(0) = ""; + if (!details_.at(0).empty()) { + details_.at(0).clear(); bestChannelId = findChannelByNames(details_); } else if (defaultChannelId != INVALID_TS3_CHANNEL) { bestChannelId = defaultChannelId; @@ -554,7 +548,6 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { return INVALID_TS3_CHANNEL; } - acre::Result CTS3Client::updateChannelDetails(std::vector details_) { setChannelDetails(details_); if (!details_.empty()) { diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index f57461e69..5a3874e07 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -213,21 +213,18 @@ std::string CMumbleClient::getTempFilePath(void) { } acre::Result CMumbleClient::microphoneOpen(bool status_) { - if (status_) { - const mumble_error_t res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, true); - if (res != ErrorCode::EC_OK) { + const mumble_error_t res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, status_); + if (res != ErrorCode::EC_OK) { + if (status_) { LOG("Error toggling PTT Open\n"); - return acre::Result::error; - } - this->setInputActive(true); - } else { - const mumble_error_t res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, false); - if (res != ErrorCode::EC_OK) { + } else { LOG("Error toggling PTT Closed\n"); - return acre::Result::error; } - this->setInputActive(false); + + return acre::Result::error; } + + this->setInputActive(status_); return acre::Result::ok; } @@ -252,7 +249,7 @@ acre::Result CMumbleClient::moveToServerChannel() { const mumble_channelid_t channelId = static_cast(findChannelByNames(details)); if ((channelId != invalid_mumble_channel) && (channelId != currentChannelId)) { std::string password; - if (details.at(1) != "" && details.at(0) != "") { + if (!details.at(1).empty() && !details.at(0).empty()) { password = details.at(1); } @@ -296,7 +293,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { mumble_channelid_t defaultChannelId = invalid_mumble_channel; std::map channelMap; std::string name = details_.at(2); - if (details_.at(0) != "") { + if (!details_.at(0).empty()) { name = details_.at(0); } @@ -344,8 +341,8 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { } if (bestChannelId == invalid_mumble_channel) { if (!details_.at(0).empty()) { - details_.at(0) = ""; - bestChannelId = static_cast(findChannelByNames(details_)); + details_.at(0).clear(); + bestChannelId = static_cast(findChannelByNames(details_)); } else if (defaultChannelId != invalid_mumble_channel) { bestChannelId = defaultChannelId; } diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index a1cf32fed..8de2c5c18 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -23,20 +23,22 @@ acre::Result CMumbleCommandServer::shutdown() { acre::Result CMumbleCommandServer::sendMessage(IMessage *msg) { LOCK(this); - mumble_userid_t *channelUsers = nullptr; - size_t userCount = 0U; - mumble_channelid_t currentChannel; - mumble_error_t err; - err = mumAPI.getChannelOfUser(pluginID, activeConnection, this->getId(), ¤tChannel); + mumble_userid_t *channelUsers = nullptr; + size_t userCount = 0U; + mumble_channelid_t currentChannel = 0; + + mumble_error_t err = mumAPI.getChannelOfUser(pluginID, activeConnection, this->getId(), ¤tChannel); if (err != ErrorCode::EC_OK) { LOG("ERROR, UNABLE TO GET CHANNEL OF USER: %d", err); return acre::Result::error; } + err = mumAPI.getUsersInChannel(pluginID, activeConnection, currentChannel, &channelUsers, &userCount); if (err != ErrorCode::EC_OK) { LOG("ERROR, UNABLE TO GET USERS IN CHANNEL: %d", err); return acre::Result::error; } + err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const char *) msg->getData(), msg->getLength(), "ACRE2"); if (err != ErrorCode::EC_OK) { LOG("ERROR, UNABLE TO SEND MESSAGE DATA: %d", err); diff --git a/extensions/src/ACRE2Shared/IClient.h b/extensions/src/ACRE2Shared/IClient.h index 50e4bf51c..38f030968 100644 --- a/extensions/src/ACRE2Shared/IClient.h +++ b/extensions/src/ACRE2Shared/IClient.h @@ -51,7 +51,7 @@ class IClient { virtual bool shouldSwitchChannel() = 0; virtual bool getVAD() = 0; - virtual std::uint64_t findChannelByNames(std::vector details_) = 0; + virtual std::uint64_t findChannelByNames(std::vector &details_) = 0; bool gethadVAD() const noexcept { return had_vad; } void sethadVAD(const bool value_) noexcept { had_vad = value_; } diff --git a/extensions/src/ACRE2TS/TS3Client.cpp b/extensions/src/ACRE2TS/TS3Client.cpp index a54820ba5..8f5edfe78 100644 --- a/extensions/src/ACRE2TS/TS3Client.cpp +++ b/extensions/src/ACRE2TS/TS3Client.cpp @@ -1,14 +1,12 @@ -#include "compat.h" - -#include "TS3Client.h" +#include "AcreSettings.h" #include "Engine.h" -#include "Types.h" +#include "Log.h" +#include "Shlwapi.h" +#include "TS3Client.h" #include "TsFunctions.h" +#include "Types.h" +#include "compat.h" #include "shlobj.h" -#include "Shlwapi.h" -#include "Log.h" - -#include "AcreSettings.h" #pragma comment(lib, "Shlwapi.lib") @@ -17,7 +15,7 @@ extern TS3Functions ts3Functions; -//TS3Functions CTS3Client::ts3Functions; +// TS3Functions CTS3Client::ts3Functions; acre::Result CTS3Client::initialize(void) { setPreviousChannel(INVALID_TS3_CHANNEL); @@ -41,12 +39,10 @@ acre::Result CTS3Client::setMuted(const acre::id_t id_, const bool muted_) { } acre::Result CTS3Client::setMuted(std::list idList_, bool muted_) { - return acre::Result::ok; } acre::Result CTS3Client::getMuted(acre::id_t id_) { - return acre::Result::ok; } @@ -58,7 +54,6 @@ acre::Result CTS3Client::stop() { this->m_versionThreadHandle.join(); } this->setState(acre::State::stopped); - } return acre::Result::ok; } @@ -80,19 +75,17 @@ acre::Result CTS3Client::start(const acre::id_t id_) { return acre::Result::ok; } -acre::Result CTS3Client::exPersistVersion( void ) { - +acre::Result CTS3Client::exPersistVersion(void) { CTS3Client::setClientMetadata(ACRE_VERSION_METADATA); ts3Functions.printMessageToCurrentTab("ACRE2 loaded and initialized"); ts3Functions.printMessageToCurrentTab(ACRE_VERSION_METADATA); - clock_t run = clock() / CLOCKS_PER_SEC; + clock_t run = clock() / CLOCKS_PER_SEC; clock_t delta = run; while (this->getState() == acre::State::running && CEngine::getInstance()->getExternalServer()) { - delta = (clock() / CLOCKS_PER_SEC) - run; - if (delta > (PERSIST_VERSION_TIMER / 1000) ) { + if (delta > (PERSIST_VERSION_TIMER / 1000)) { char selfVariableBuffer[4096]; if (CEngine::getInstance()->getGameServer()->getConnected()) { _snprintf_s(selfVariableBuffer, 4094, "%s\nArma Connected: Yes", ACRE_VERSION_METADATA); @@ -110,20 +103,20 @@ acre::Result CTS3Client::exPersistVersion( void ) { } acre::Result CTS3Client::setClientMetadata(const char *const data) { - char* clientInfo; + char *clientInfo; anyID myID; ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &myID); ts3Functions.getClientVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), myID, CLIENT_META_DATA, &clientInfo); std::string to_set; std::string_view sharedMsg = clientInfo; - const size_t start_pos = sharedMsg.find(START_DATA); - const size_t end_pos = sharedMsg.find(END_DATA); + const size_t start_pos = sharedMsg.find(START_DATA); + const size_t end_pos = sharedMsg.find(END_DATA); if ((start_pos == std::string::npos) || (end_pos == std::string::npos)) { to_set = to_set + START_DATA + data + END_DATA; } else { - const std::string before = (std::string)sharedMsg.substr(0, start_pos); - const std::string after = (std::string)sharedMsg.substr(end_pos + strlen(END_DATA), std::string::npos); - to_set = before + START_DATA + data + END_DATA + after; + const std::string before = (std::string) sharedMsg.substr(0, start_pos); + const std::string after = (std::string) sharedMsg.substr(end_pos + strlen(END_DATA), std::string::npos); + to_set = before + START_DATA + data + END_DATA + after; } ts3Functions.setClientSelfVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_META_DATA, to_set.c_str()); ts3Functions.freeMemory(clientInfo); @@ -134,7 +127,7 @@ acre::Result CTS3Client::setClientMetadata(const char *const data) { bool CTS3Client::getVAD() { char *data; bool returnValue = false; - uint32_t res = ts3Functions.getPreProcessorConfigValue(ts3Functions.getCurrentServerConnectionHandlerID(), "vad", &data); + uint32_t res = ts3Functions.getPreProcessorConfigValue(ts3Functions.getCurrentServerConnectionHandlerID(), "vad", &data); if (!res) { if (!strcmp(data, "true")) { returnValue = true; @@ -235,7 +228,7 @@ acre::Result CTS3Client::localStopSpeaking(const acre::Speaking speakingType_) { resendDirectSpeaking = true; } } else if (this->getSpeakingState() == STATUS_TALKING) { - resendDirectSpeaking = true; + resendDirectSpeaking = true; } } @@ -253,9 +246,10 @@ acre::Result CTS3Client::enableMicrophone(const bool status_) { if (currentStatus != status_) { uint32_t res = 0u; if (status_) { - res = ts3Functions.setClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, MUTEINPUT_NONE); + res = ts3Functions.setClientSelfVariableAsInt( + ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, MUTEINPUT_NONE); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("Error toggling microphone enabled: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -263,9 +257,10 @@ acre::Result CTS3Client::enableMicrophone(const bool status_) { return acre::Result::ok; } } else { - res = ts3Functions.setClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, MUTEINPUT_MUTED); + res = ts3Functions.setClientSelfVariableAsInt( + ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, MUTEINPUT_MUTED); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("Error, failed to disable microphone input: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -275,7 +270,7 @@ acre::Result CTS3Client::enableMicrophone(const bool status_) { } res = ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); if (!((res == ERROR_ok) || (res == ERROR_ok_no_update))) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("STOP TALKING: Error flushing after toggling microphone muted: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -287,11 +282,11 @@ acre::Result CTS3Client::enableMicrophone(const bool status_) { } bool CTS3Client::getInputStatus() { - bool status = false; - int32_t ret = 0u; + bool status = false; + int32_t ret = 0u; uint32_t res = ts3Functions.getClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_MUTED, &ret); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("Error querying microphone input status: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -307,16 +302,16 @@ bool CTS3Client::getInputStatus() { } acre::Result CTS3Client::playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) { - if (!PathFileExistsA(path_.c_str())) { return acre::Result::error; } char soundpackDb[32]; uint32_t ret = 0u; - uint32_t res = ts3Functions.getClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_OUTPUT_MUTED, (int32_t *) &ret); + uint32_t res = + ts3Functions.getClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_OUTPUT_MUTED, (int32_t *) &ret); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("Error checking playback status: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -329,31 +324,25 @@ acre::Result CTS3Client::playSound(std::string path_, acre::vec3_fp32_t position } // create a volume ranged from -40 to 0dB change - _snprintf_s(soundpackDb, 32, "%f", (-40.0f + (40.0f * volume_) ) ); + _snprintf_s(soundpackDb, 32, "%f", (-40.0f + (40.0f * volume_))); // change the soundpack volume for this squawks volume - ts3Functions.setPlaybackConfigValue(ts3Functions.getCurrentServerConnectionHandlerID(), - "volume_factor_wave", - soundpackDb); + ts3Functions.setPlaybackConfigValue(ts3Functions.getCurrentServerConnectionHandlerID(), "volume_factor_wave", soundpackDb); TS3_VECTOR vector = {position_.x, position_.z, position_.y}; TRACE("HIT [%f,%f,%f]", vector.x, vector.z, vector.y); uint64_t playHandle; - ret = ts3Functions.playWaveFileHandle(ts3Functions.getCurrentServerConnectionHandlerID(), - path_.c_str(), - looping_, - &playHandle); - ret = ts3Functions.set3DWaveAttributes(ts3Functions.getCurrentServerConnectionHandlerID(), - playHandle, - &vector); + ret = ts3Functions.playWaveFileHandle(ts3Functions.getCurrentServerConnectionHandlerID(), path_.c_str(), looping_, &playHandle); + ret = ts3Functions.set3DWaveAttributes(ts3Functions.getCurrentServerConnectionHandlerID(), playHandle, &vector); return acre::Result::ok; } -std::string CTS3Client::getUniqueId( ) { +std::string CTS3Client::getUniqueId() { char *uniqueId; std::string serverUniqueId = ""; - uint32_t res = ts3Functions.getServerVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), VIRTUALSERVER_UNIQUE_IDENTIFIER, &uniqueId); + uint32_t res = ts3Functions.getServerVariableAsString( + ts3Functions.getCurrentServerConnectionHandlerID(), VIRTUALSERVER_UNIQUE_IDENTIFIER, &uniqueId); if (res == ERROR_ok) { serverUniqueId = std::string(uniqueId); if (uniqueId) { @@ -379,7 +368,7 @@ std::string CTS3Client::getConfigFilePath(void) { return tempFolder; } -std::string CTS3Client::getTempFilePath( void ) { +std::string CTS3Client::getTempFilePath(void) { char tempPath[MAX_PATH - 14]; GetTempPathA(sizeof(tempPath), tempPath); std::string tempFolder = std::string(tempPath); @@ -402,9 +391,10 @@ acre::Result CTS3Client::microphoneOpen(bool status_) { this->setInputActive(false); } - uint32_t res = ts3Functions.setClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_DEACTIVATED, micStatus); + uint32_t res = + ts3Functions.setClientSelfVariableAsInt(ts3Functions.getCurrentServerConnectionHandlerID(), CLIENT_INPUT_DEACTIVATED, micStatus); if (res != ERROR_ok) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("STOP TALKING: Error toggling push-to-talk: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -414,7 +404,7 @@ acre::Result CTS3Client::microphoneOpen(bool status_) { res = ts3Functions.flushClientSelfUpdates(ts3Functions.getCurrentServerConnectionHandlerID(), NULL); if (!(res == ERROR_ok || res == ERROR_ok_no_update)) { - char* errorMsg; + char *errorMsg; if (ts3Functions.getErrorMessage(res, &errorMsg) == ERROR_ok) { LOG("STOP TALKING: Error flushing after toggling push-to-talk: %s\n", errorMsg); ts3Functions.freeMemory(errorMsg); @@ -424,53 +414,51 @@ acre::Result CTS3Client::microphoneOpen(bool status_) { return acre::Result::ok; } -acre::Result CTS3Client::unMuteAll( void ) { +acre::Result CTS3Client::unMuteAll(void) { anyID clientId; anyID *clientList; - uint32_t total_retries = 0; + uint32_t total_retries = 0; uint32_t total_intentional_runs = 0; - //for (total_intentional_runs = 0; total_intentional_runs < 3; total_intentional_runs++) { - uint32_t res = ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId); - if (res == ERROR_ok) { - - res = ERROR_undefined; - for (total_retries = 0; (total_retries < 5) && (res != ERROR_ok); total_retries++) { - res = ts3Functions.getClientList(ts3Functions.getCurrentServerConnectionHandlerID(), &clientList); - if (res == ERROR_ok) { - res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), clientList, NULL); - //if (res != ERROR_ok) { - // Sleep(500 * total_retries); - //} - ts3Functions.freeMemory(clientList); - } - } - - /* - /* - This was the alternative method originally, but it was hitting the spam threshold */ - /* Disable this method + // for (total_intentional_runs = 0; total_intentional_runs < 3; total_intentional_runs++) { + uint32_t res = ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId); + if (res == ERROR_ok) { + res = ERROR_undefined; + for (total_retries = 0; (total_retries < 5) && (res != ERROR_ok); total_retries++) { res = ts3Functions.getClientList(ts3Functions.getCurrentServerConnectionHandlerID(), &clientList); if (res == ERROR_ok) { - for (x=0;clientList[x]!=0 && total_retries < 20;x++) { - anyID tempList[2]; - uint32_t tries_on_client; - - tempList[0] = (anyID)clientList[x]; - tempList[1] = 0x0000; - - res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), clientList, NULL); - for (tries_on_client = 0; tries_on_client < 5 && total_retries < 20 && res != ERROR_ok; tries_on_client++, total_retries++) { - res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), tempList, NULL); - if (res != ERROR_ok) { - Sleep(500 * tries_on_client); - } - } - } + res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), clientList, NULL); + // if (res != ERROR_ok) { + // Sleep(500 * total_retries); + //} ts3Functions.freeMemory(clientList); } - */ } + + /* + /* - This was the alternative method originally, but it was hitting the spam threshold */ + /* Disable this method + res = ts3Functions.getClientList(ts3Functions.getCurrentServerConnectionHandlerID(), &clientList); + if (res == ERROR_ok) { + for (x=0;clientList[x]!=0 && total_retries < 20;x++) { + anyID tempList[2]; + uint32_t tries_on_client; + + tempList[0] = (anyID)clientList[x]; + tempList[1] = 0x0000; + + res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), clientList, NULL); + for (tries_on_client = 0; tries_on_client < 5 && total_retries < 20 && res != ERROR_ok; tries_on_client++, total_retries++) + { res = ts3Functions.requestUnmuteClients(ts3Functions.getCurrentServerConnectionHandlerID(), tempList, NULL); if (res != ERROR_ok) + { Sleep(500 * tries_on_client); + } + } + } + ts3Functions.freeMemory(clientList); + } + */ + } // Sleep(500); //} return acre::Result::ok; @@ -483,7 +471,9 @@ acre::Result CTS3Client::moveToServerChannel() { if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; - if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok && getPreviousChannel() == INVALID_TS3_CHANNEL) { + if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == + ERROR_ok && + getPreviousChannel() == INVALID_TS3_CHANNEL) { setPreviousChannel(currentChannelId); } @@ -493,7 +483,8 @@ acre::Result CTS3Client::moveToServerChannel() { if (details.at(1) != "" && details.at(0) != "") { password = details.at(1); } - ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr); + ts3Functions.requestClientMove( + ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr); } } } @@ -506,7 +497,8 @@ acre::Result CTS3Client::moveToPreviousChannel() { anyID clientId; if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) { uint64_t currentChannelId = INVALID_TS3_CHANNEL; - if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == ERROR_ok) { + if (ts3Functions.getChannelOfClient(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, ¤tChannelId) == + ERROR_ok) { const uint64_t channelId = getPreviousChannel(); if (channelId != INVALID_TS3_CHANNEL && channelId != currentChannelId) { ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, "", nullptr); @@ -518,10 +510,10 @@ acre::Result CTS3Client::moveToPreviousChannel() { return acre::Result::ok; } -uint64_t CTS3Client::findChannelByNames(std::vector details_) { +uint64_t CTS3Client::findChannelByNames(std::vector &details_) { uint64_t *channelList; if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { - uint64_t channelId = INVALID_TS3_CHANNEL; + uint64_t channelId = INVALID_TS3_CHANNEL; uint64_t defaultChannelId = INVALID_TS3_CHANNEL; std::map channelMap; std::string name = details_.at(2); @@ -531,8 +523,9 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { while (*channelList) { channelId = *channelList; channelList++; - char* channelName; - if (ts3Functions.getChannelVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { + char *channelName; + if (ts3Functions.getChannelVariableAsString( + ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) { std::string channelNameString = std::string(channelName); if (channelNameString.find(DEFAULT_TS3_CHANNEL) != -1 || (details_.at(0) != "" && channelNameString == name)) { if (channelNameString == DEFAULT_TS3_CHANNEL) { @@ -544,9 +537,9 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { } uint64_t bestChannelId = INVALID_TS3_CHANNEL; - int32_t bestMatches = 0; - int32_t bestDistance = 10; - for (auto& element : channelMap) { + int32_t bestMatches = 0; + int32_t bestDistance = 10; + for (auto &element : channelMap) { std::string fullChannelName = element.second; // Full comparison if (fullChannelName.compare(name) == 0) { @@ -557,20 +550,20 @@ uint64_t CTS3Client::findChannelByNames(std::vector details_) { // Word comparison const int32_t matches = getWordMatches(cleanChannelName, name); if (matches > bestMatches) { - bestMatches = matches; + bestMatches = matches; bestChannelId = element.first; continue; } // Char comparison const int32_t distance = levenshteinDistance(cleanChannelName, name); if (distance <= bestDistance) { - bestDistance = distance; + bestDistance = distance; bestChannelId = element.first; } } if (bestChannelId == INVALID_TS3_CHANNEL) { - if (details_.at(0) != "") { - details_.at(0) = ""; + if (!details_.at(0).empty()) { + details_.at(0).clear(); bestChannelId = findChannelByNames(details_); } else if (defaultChannelId != INVALID_TS3_CHANNEL) { bestChannelId = defaultChannelId; diff --git a/extensions/src/ACRE2TS/TS3Client.h b/extensions/src/ACRE2TS/TS3Client.h index 8be13ca02..f2dfc0ae1 100644 --- a/extensions/src/ACRE2TS/TS3Client.h +++ b/extensions/src/ACRE2TS/TS3Client.h @@ -2,19 +2,19 @@ #include "IClient.h" #include "TsFunctions.h" -#include + #include +#include #include -class CTS3Client: public IClient { +class CTS3Client : public IClient { public: + // static TS3Functions ts3Functions; - //static TS3Functions ts3Functions; - - CTS3Client() = default; + CTS3Client() = default; ~CTS3Client() final = default; - acre::Result initialize( void ) final; + acre::Result initialize(void) final; acre::Result setMuted(const acre::id_t id_, const bool muted_) final; acre::Result setMuted(std::list idList_, const bool muted_) final; @@ -24,7 +24,7 @@ class CTS3Client: public IClient { acre::Result stop() final; acre::Result start(const acre::id_t id_) final; - acre::Result exPersistVersion( void ); + acre::Result exPersistVersion(void); acre::Result setClientMetadata(const char *const data); @@ -35,22 +35,22 @@ class CTS3Client: public IClient { bool getVAD(); /*! - * \brief Handles local player starting speaking. - * - * \param[in] speakingType_ ACRE speaking type - * - * \return acre::Result::ok if operation successful - */ + * \brief Handles local player starting speaking. + * + * \param[in] speakingType_ ACRE speaking type + * + * \return acre::Result::ok if operation successful + */ acre::Result localStartSpeaking(const acre::Speaking speakingType_) final; /*! - * \brief Handles local player starting speaking. - * - * \param[in] speakingType_ ACRE speaking type - * \param[in] radioId_ Unique radio ideintifier - * - * \return acre::Result::ok if operation successful - */ + * \brief Handles local player starting speaking. + * + * \param[in] speakingType_ ACRE speaking type + * \param[in] radioId_ Unique radio ideintifier + * + * \return acre::Result::ok if operation successful + */ acre::Result localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_) final; /*! @@ -60,29 +60,28 @@ class CTS3Client: public IClient { * * \return acre::Result::ok if operation successful */ - acre::Result localStopSpeaking(const acre::Speaking speakingType_ ) final; + acre::Result localStopSpeaking(const acre::Speaking speakingType_) final; - std::string getTempFilePath( void ) final; + std::string getTempFilePath(void) final; std::string getConfigFilePath(void) final; acre::Result playSound(std::string path_, acre::vec3_fp32_t position_, const float32_t volume_, const int32_t looping_) final; - std::string getUniqueId( ) final; + std::string getUniqueId() final; acre::Result microphoneOpen(const bool status_) final; - acre::Result unMuteAll( void ) final; + acre::Result unMuteAll(void) final; acre::Result moveToServerChannel() final; acre::Result moveToPreviousChannel() final; - uint64 findChannelByNames(std::vector details_) final; + uint64 findChannelByNames(std::vector &details_) final; acre::Result updateChannelDetails(std::vector details_) final; acre::Result updateShouldSwitchChannel(const bool state_) final; bool shouldSwitchChannel() final; private: - std::thread m_versionThreadHandle; char *m_vadLevel = nullptr; }; From ff3d45fe5b8a92c4b6aad583ca8cd962f181af5c Mon Sep 17 00:00:00 2001 From: Magnetar Date: Tue, 9 Jun 2020 10:55:08 +0200 Subject: [PATCH 043/104] Fix missing variable --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 5a3874e07..cfc0f889d 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -10,8 +10,8 @@ #pragma comment(lib, "Shlwapi.lib") -static constexpr std::int32_t = -1; -constexpr char default_mumble_channel[] = "ACRE"; +static constexpr std::int32_t invalid_mumble_channel = -1; +constexpr char default_mumble_channel[] = "ACRE"; extern MumbleAPI mumAPI; extern mumble_connection_t activeConnection; From 81a4fb0dbaff5eb1b83e264363b688e6c462aa46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Tue, 9 Jun 2020 22:07:47 +0200 Subject: [PATCH 044/104] Compile fixes --- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 4 +- extensions/src/ACRE2Shared/IClient.h | 2 +- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 2 +- extensions/src/ACRE2Steam/mumble_plugin.cpp | 114 +++++++++++++++++ extensions/src/ACRE2Steam/mumble_plugin.hpp | 118 +----------------- extensions/src/ACRE2Steam/ts3_plugin.cpp | 59 +++++++++ extensions/src/ACRE2Steam/ts3_plugin.hpp | 49 +------- extensions/src/ACRE2TS/TS3Client.cpp | 2 +- extensions/src/ACRE2TS/TS3Client.h | 2 +- 9 files changed, 185 insertions(+), 167 deletions(-) create mode 100644 extensions/src/ACRE2Steam/mumble_plugin.cpp create mode 100644 extensions/src/ACRE2Steam/ts3_plugin.cpp diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 60d8ef844..1b73b9db0 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -33,7 +33,7 @@ bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_ // if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { const std::uint32_t mixdownSampleLength = sampleCount * channelCount; - int16_t *mixdownSamples = new (nothrow) int16_t[mixdownSampleLength]; + int16_t *mixdownSamples = new (std::nothrow) int16_t[mixdownSampleLength]; if (mixdownSamples == nullptr) { return false; } @@ -84,7 +84,7 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin // if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { const uint32_t mixdownSampleLength = sampleCount * channelCount; - int16_t *mixdownSamples = new (nothrow) int16_t[mixdownSampleLength]; + int16_t *mixdownSamples = new (std::nothrow) int16_t[mixdownSampleLength]; if (mixdownSamples == nullptr) { return false; } diff --git a/extensions/src/ACRE2Shared/IClient.h b/extensions/src/ACRE2Shared/IClient.h index 38f030968..50e4bf51c 100644 --- a/extensions/src/ACRE2Shared/IClient.h +++ b/extensions/src/ACRE2Shared/IClient.h @@ -51,7 +51,7 @@ class IClient { virtual bool shouldSwitchChannel() = 0; virtual bool getVAD() = 0; - virtual std::uint64_t findChannelByNames(std::vector &details_) = 0; + virtual std::uint64_t findChannelByNames(std::vector details_) = 0; bool gethadVAD() const noexcept { return had_vad; } void sethadVAD(const bool value_) noexcept { had_vad = value_; } diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 0bd14bdfb..79ae0b94b 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -73,7 +73,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { std::string test = cmd_args.get_argument("-mumblePath"); idi::acre::TS3Plugin ts3_plugin(skip_ts_plugin); - idi::acre::Mumble_plugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); + idi::acre::MumblePlugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); switch (command) { case SteamCommand::check: { diff --git a/extensions/src/ACRE2Steam/mumble_plugin.cpp b/extensions/src/ACRE2Steam/mumble_plugin.cpp new file mode 100644 index 000000000..9643badf2 --- /dev/null +++ b/extensions/src/ACRE2Steam/mumble_plugin.cpp @@ -0,0 +1,114 @@ +#include "mumble_plugin.hpp" + +#include + +using ::idi::acre::MumblePlugin; + +bool MumblePlugin::collect_plugin_locations() noexcept { + if (get_skip_plugin()) { + return true; + } + + if (!mumble_path.empty()) { + check_plugin_locations(mumble_path); + } else { + parse_mumble_registry(false); // 32 bits + parse_mumble_registry(true); // 64 bits + + // TODO: 32 bits applications will not recognise FOLDERID_ProgramFilesX64 + std::array folder_ids = {FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64}; + for (const auto folder : folder_ids) { + wchar_t *folder_path = nullptr; + SHGetKnownFolderPath(folder, 0, nullptr, &folder_path); + + if (folder_path == nullptr) { + return false; + } + + // Convert to UTF-8 string + std::string app_data = VOIPPlugin::wide_string_to_utf8(folder_path); + + app_data.append("\\Mumble"); + check_plugin_locations(app_data); + + // Now do the same for x64 + CoTaskMemFree(folder_path); // Free it up. + } + } + + // Do not delete if we need to copy it + std::vector mumble_locations = get_plugin_locations(); + std::vector mumble_delete_locations = get_plugin_delete_locations(); + + for (const auto &location : mumble_locations) { + mumble_delete_locations.erase( + std::remove(mumble_delete_locations.begin(), mumble_delete_locations.end(), location), mumble_delete_locations.end()); + } + + // No locations to copy to. + return !get_plugin_locations().empty(); +} + +void MumblePlugin::parse_mumble_registry(const bool use_x64_) noexcept { + REGSAM sam_key = KEY_READ | KEY_WOW64_64KEY; + + if (!use_x64_) { + sam_key = KEY_READ; + } + + HKEY registry_key; + if (RegOpenKeyEx(HKEY_CURRENT_USER, get_registry_key().c_str(), 0, sam_key, ®istry_key) != ERROR_SUCCESS) { + return; + } + + DWORD num_subkeys = 0; + if (RegQueryInfoKey(registry_key, nullptr, nullptr, nullptr, &num_subkeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr) != ERROR_SUCCESS) { + RegCloseKey(registry_key); + return; + } + + for (DWORD idx = 0; idx < num_subkeys; idx++) { + TCHAR achKey[max_key_length]; + DWORD cbName = max_key_length; + if (RegEnumKeyEx(registry_key, idx, achKey, &cbName, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS) { + continue; + } + + HKEY plugin_key; + std::string name = get_registry_key() + "\\" + std::string(achKey); + if (RegOpenKeyEx(HKEY_CURRENT_USER, name.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &plugin_key) != ERROR_SUCCESS) { + continue; + } + + DWORD type; + DWORD cbData; + if (RegQueryValueEx(plugin_key, "path", nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { + RegCloseKey(plugin_key); + continue; + } + + if (type != REG_SZ) { + RegCloseKey(plugin_key); + continue; + } + + std::string file_path(cbData / sizeof(char), '\0'); + if (RegQueryValueEx(plugin_key, "path", nullptr, nullptr, reinterpret_cast(&file_path[0]), &cbData) == ERROR_SUCCESS) { + RegCloseKey(plugin_key); + + size_t first_null = file_path.find_first_of('\0'); + if (first_null != std::string::npos) { + file_path.resize(first_null); + } + + std::filesystem::path plugin_path(file_path); + if (std::filesystem::exists(plugin_path)) { + const std::string mumble_path = plugin_path.parent_path().parent_path().string(); + check_plugin_locations(mumble_path); + } + } + } + + RegCloseKey(registry_key); +} diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index 670efd774..d33b88186 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -9,131 +9,23 @@ #include "voip_plugin.hpp" #include -#include -#include #include namespace idi::acre { - class Mumble_plugin final : public VOIPPlugin { + class MumblePlugin final : public VOIPPlugin { public: - explicit Mumble_plugin(bool skip_plugin_, std::string mumble_path_ = "") noexcept + explicit MumblePlugin(bool skip_plugin_, std::string mumble_path_ = "") noexcept : VOIPPlugin(skip_plugin_, "SOFTWARE\\Mumble\\Mumble\\plugins", find_mod_file("plugin/mumble/acre2_win32.dll"), find_mod_file("plugin/mumble/acre2_win64.dll")), mumble_path(std::move(mumble_path_)) {} - ~Mumble_plugin() noexcept final = default; + ~MumblePlugin() noexcept final = default; - bool collect_plugin_locations() noexcept final { - if (get_skip_plugin()) { - return true; - } - - if (!mumble_path.empty()) { - check_plugin_locations(mumble_path); - } else { - parse_mumble_registry(false); // 32 bits - parse_mumble_registry(true); // 64 bits - - // TODO: 32 bits applications will not recognise FOLDERID_ProgramFilesX64 - std::array folder_ids = {FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64}; - for (const auto folder : folder_ids) { - wchar_t *folder_path = nullptr; - SHGetKnownFolderPath(folder, 0, nullptr, &folder_path); - - if (folder_path == nullptr) { - return false; - } - - // Convert to UTF-8 string - std::string app_data = VOIPPlugin::wide_string_to_utf8(folder_path); - - app_data.append("\\Mumble"); - check_plugin_locations(app_data); - - // Now do the same for x64 - CoTaskMemFree(folder_path); // Free it up. - } - } - - // Do not delete if we need to copy it - std::vector mumble_locations = get_plugin_locations(); - std::vector mumble_delete_locations = get_plugin_delete_locations(); - - for (const auto &location : mumble_locations) { - mumble_delete_locations.erase( - std::remove(mumble_delete_locations.begin(), mumble_delete_locations.end(), location), mumble_delete_locations.end()); - } - - // No locations to copy to. - return !get_plugin_locations().empty(); - } + bool collect_plugin_locations() noexcept final; private: - void parse_mumble_registry(const bool use_x64_) noexcept { - REGSAM sam_key = KEY_READ | KEY_WOW64_64KEY; - - if (!use_x64_) { - sam_key = KEY_READ; - } - - HKEY registry_key; - if (RegOpenKeyEx(HKEY_CURRENT_USER, get_registry_key().c_str(), 0, sam_key, ®istry_key) != ERROR_SUCCESS) { - return; - } - - DWORD num_subkeys = 0; - if (RegQueryInfoKey(registry_key, nullptr, nullptr, nullptr, &num_subkeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr) != ERROR_SUCCESS) { - RegCloseKey(registry_key); - return; - } - - for (DWORD idx = 0; idx < num_subkeys; idx++) { - TCHAR achKey[max_key_length]; - DWORD cbName = max_key_length; - if (RegEnumKeyEx(registry_key, idx, achKey, &cbName, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS) { - continue; - } - - HKEY plugin_key; - std::string name = get_registry_key() + "\\" + std::string(achKey); - if (RegOpenKeyEx(HKEY_CURRENT_USER, name.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &plugin_key) != ERROR_SUCCESS) { - continue; - } - - DWORD type; - DWORD cbData; - if (RegQueryValueEx(plugin_key, "path", nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { - RegCloseKey(plugin_key); - continue; - } - - if (type != REG_SZ) { - RegCloseKey(plugin_key); - continue; - } - - std::string file_path(cbData / sizeof(char), '\0'); - if (RegQueryValueEx(plugin_key, "path", nullptr, nullptr, reinterpret_cast(&file_path[0]), &cbData) == - ERROR_SUCCESS) { - RegCloseKey(plugin_key); - - size_t first_null = file_path.find_first_of('\0'); - if (first_null != std::string::npos) { - file_path.resize(first_null); - } - - std::filesystem::path plugin_path(file_path); - if (std::filesystem::exists(plugin_path)) { - const std::string mumble_path = plugin_path.parent_path().parent_path().string(); - check_plugin_locations(mumble_path); - } - } - } - - RegCloseKey(registry_key); - } + void parse_mumble_registry(const bool use_x64_) noexcept; static constexpr std::uint8_t max_key_length = 255U; std::string mumble_path; diff --git a/extensions/src/ACRE2Steam/ts3_plugin.cpp b/extensions/src/ACRE2Steam/ts3_plugin.cpp new file mode 100644 index 000000000..289ce7b9a --- /dev/null +++ b/extensions/src/ACRE2Steam/ts3_plugin.cpp @@ -0,0 +1,59 @@ +/** + * @author Ferran Obón Santacana (Magnetar) + * @author Cliff Foster (Nou) + * @author James Smith (Snippers) + * + * @copyright Copyright (c) 2020 International Development & Integration + * Systems LLC + * + * TeamSpeak 3 auto-plugin copy functionality. + */ +#include "ts3_plugin.hpp" + +#include + +using ::idi::acre::TS3Plugin; + +bool TS3Plugin::collect_plugin_locations() noexcept { + if (get_skip_plugin()) { + return true; + } + + // Teamspeak 3 location - Default location - Roaming Appdata. + wchar_t *app_data_roaming = nullptr; + SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &app_data_roaming); + + if (app_data_roaming == nullptr) { + return false; + } + + // Convert to UTF-8 string + std::string app_data = VOIPPlugin::wide_string_to_utf8(app_data_roaming); + + app_data.append("\\TS3Client"); + CoTaskMemFree(app_data_roaming); // Free it up. + + const std::array registry_keys = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER}; + + for (const auto &key : registry_keys) { + // 32 bits + std::string rootkey = read_reg_value(key, get_registry_key().c_str(), "", false); + check_plugin_locations(app_data, rootkey, key); + + // 64 bits + rootkey = read_reg_value(key, get_registry_key().c_str(), "", true); + check_plugin_locations(app_data, rootkey, key); + } + + // Do not delete if we need to copy it + std::vector ts3_locations = get_plugin_locations(); + std::vector ts3_delete_locations = get_plugin_delete_locations(); + + for (const auto &location : ts3_locations) { + ts3_delete_locations.erase( + std::remove(ts3_delete_locations.begin(), ts3_delete_locations.end(), location), ts3_delete_locations.end()); + } + + // No locations to copy to. + return !get_plugin_locations().empty(); +} diff --git a/extensions/src/ACRE2Steam/ts3_plugin.hpp b/extensions/src/ACRE2Steam/ts3_plugin.hpp index 0966a6f03..a6d385937 100644 --- a/extensions/src/ACRE2Steam/ts3_plugin.hpp +++ b/extensions/src/ACRE2Steam/ts3_plugin.hpp @@ -10,7 +10,6 @@ #include "voip_plugin.hpp" #include -#include #include namespace idi::acre { @@ -23,52 +22,6 @@ namespace idi::acre { find_mod_file("plugin/ts3/acre2_win64.dll")) {} ~TS3Plugin() noexcept final = default; - bool collect_plugin_locations() noexcept final { - if (get_skip_plugin()) { - return true; - } - - // Teamspeak 3 location - Default location - Roaming Appdata. - wchar_t *app_data_roaming = nullptr; - SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &app_data_roaming); - - if (app_data_roaming == nullptr) { - return false; - } - - // Convert to UTF-8 string - std::string app_data = VOIPPlugin::wide_string_to_utf8(app_data_roaming); - - app_data.append("\\TS3Client"); - CoTaskMemFree(app_data_roaming); // Free it up. - - // 32 Bit - Machine - std::string rootkey = read_reg_value(HKEY_LOCAL_MACHINE, get_registry_key().c_str(), "", false); - check_plugin_locations(app_data, rootkey, HKEY_LOCAL_MACHINE); - - // 64 Bit - Machine - rootkey = read_reg_value(HKEY_LOCAL_MACHINE, get_registry_key().c_str(), "", true); - check_plugin_locations(app_data, rootkey, HKEY_LOCAL_MACHINE); - - // 32 Bit - User - rootkey = read_reg_value(HKEY_CURRENT_USER, get_registry_key().c_str(), "", false); - check_plugin_locations(app_data, rootkey, HKEY_CURRENT_USER); - - // 64 Bit - User - rootkey = read_reg_value(HKEY_CURRENT_USER, get_registry_key().c_str(), "", true); - check_plugin_locations(app_data, rootkey, HKEY_CURRENT_USER); - - // Do not delete if we need to copy it - std::vector ts3_locations = get_plugin_locations(); - std::vector ts3_delete_locations = get_plugin_delete_locations(); - - for (const auto &location : ts3_locations) { - ts3_delete_locations.erase( - std::remove(ts3_delete_locations.begin(), ts3_delete_locations.end(), location), ts3_delete_locations.end()); - } - - // No locations to copy to. - return !get_plugin_locations().empty(); - } + bool collect_plugin_locations() noexcept final; }; } // namespace idi::acre diff --git a/extensions/src/ACRE2TS/TS3Client.cpp b/extensions/src/ACRE2TS/TS3Client.cpp index 8f5edfe78..38ad23f6c 100644 --- a/extensions/src/ACRE2TS/TS3Client.cpp +++ b/extensions/src/ACRE2TS/TS3Client.cpp @@ -510,7 +510,7 @@ acre::Result CTS3Client::moveToPreviousChannel() { return acre::Result::ok; } -uint64_t CTS3Client::findChannelByNames(std::vector &details_) { +uint64_t CTS3Client::findChannelByNames(std::vector details_) { uint64_t *channelList; if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) { uint64_t channelId = INVALID_TS3_CHANNEL; diff --git a/extensions/src/ACRE2TS/TS3Client.h b/extensions/src/ACRE2TS/TS3Client.h index f2dfc0ae1..18e75951f 100644 --- a/extensions/src/ACRE2TS/TS3Client.h +++ b/extensions/src/ACRE2TS/TS3Client.h @@ -75,7 +75,7 @@ class CTS3Client : public IClient { acre::Result moveToServerChannel() final; acre::Result moveToPreviousChannel() final; - uint64 findChannelByNames(std::vector &details_) final; + uint64 findChannelByNames(std::vector details_) final; acre::Result updateChannelDetails(std::vector details_) final; acre::Result updateShouldSwitchChannel(const bool state_) final; From 90eedf067923b08515c92ddad06691d657eb9d5e Mon Sep 17 00:00:00 2001 From: Magnetar Date: Wed, 10 Jun 2020 10:27:39 +0200 Subject: [PATCH 045/104] Minor formatting --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 79ae0b94b..497c040ee 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -106,8 +106,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { for (const auto &missing : missing_plugins) { oss << "\t" << missing << "\n"; } - oss << "\n\n" - << "The ACRE2 installation is likely corrupted. Please reinstall."; + oss << "\n\nThe ACRE2 installation is likely corrupted. Please reinstall."; const std::int32_t result = MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_OK | MB_ICONERROR); @@ -121,9 +120,9 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!ts3_locations_success && !mumble_locations_success) { const std::int32_t result = MessageBoxA(nullptr, "ACRE2 was unable to find a TeamSpeak 3 or a Mumble installation. If you do have an installation please copy the plugins " - "yourself or reinstall TeamSpeak 3. \n\n If you are sure you have Mumble and/or TeamSpeak 3 installed and wish to " - "prevent this message " - "from appearing again remove ACRE2Steam.dll and ACRE2Steam_x64.dll from your @acre2 folder.\n\nContinue anyway?", + "yourself or reinstall TeamSpeak 3.\n\nIf you are sure you have Mumble and/or TeamSpeak 3 installed and wish to " + "prevent this message from appearing again remove ACRE2Steam.dll and ACRE2Steam_x64.dll from your @acre2 " + "folder.\n\nContinue anyway?", "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); if (result == IDYES) { strncpy(output, "[-3,true]", outputSize); @@ -161,10 +160,8 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!update_ts3_ok || !update_mumble_ok) { std::ostringstream oss; oss << "ACRE2 was unable to copy the Mumble/TeamSpeak 3 plugin. Please check if you have write access to the plugin " - "folder, " - << "close any instances of Mumble and/or TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you would like " - "to close Arma 3 " - << "click Cancel. Press Continue to launch Arma 3 regardless.\n\n" + << "folder, close any instances of Mumble and/or TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you " + << "would like to close Arma 3 click Cancel. Press Continue to launch Arma 3 regardless.\n\n" << error_msg; const int32_t result = MessageBoxA( nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); @@ -230,8 +227,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { } oss << "If this is NOT valid, please uninstall all versions of Mumble and/or TeamSpeak 3 and reinstall both it and ACRE2 or " - "copy the plugins " - << "manually to your correct installation.\n\n"; + << "copy the plugins manually to your correct installation.\n\n"; oss << "If this appears to be the correct folder(s) please remember to enable the plugin in Mumble and/or TeamSpeak 3!"; const int32_t result = MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Success", MB_OK | MB_ICONINFORMATION); From 09c88bbabc3a780cee5dd9a7364b29c4dc58846d Mon Sep 17 00:00:00 2001 From: Magnetar Date: Wed, 10 Jun 2020 10:30:27 +0200 Subject: [PATCH 046/104] Forgotten string --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 497c040ee..2207f7393 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -227,8 +227,8 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { } oss << "If this is NOT valid, please uninstall all versions of Mumble and/or TeamSpeak 3 and reinstall both it and ACRE2 or " - << "copy the plugins manually to your correct installation.\n\n"; - oss << "If this appears to be the correct folder(s) please remember to enable the plugin in Mumble and/or TeamSpeak 3!"; + << "copy the plugins manually to your correct installation.\n\n" + << "If this appears to be the correct folder(s) please remember to enable the plugin in Mumble and/or TeamSpeak 3!"; const int32_t result = MessageBoxA(nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Success", MB_OK | MB_ICONINFORMATION); From a7f6e06990ba5046e2c112c991ce1dc814f54a3e Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Sun, 14 Jun 2020 22:43:51 -0700 Subject: [PATCH 047/104] Mix multichannel user audio to mono and expand back after processing. --- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 75 ++++++++++++++----- 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 1b73b9db0..e904f627d 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -30,36 +30,75 @@ bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_ } // Make this faster - - // if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { - const std::uint32_t mixdownSampleLength = sampleCount * channelCount; + const std::uint32_t mixdownSampleLength = sampleCount; int16_t *mixdownSamples = new (std::nothrow) int16_t[mixdownSampleLength]; if (mixdownSamples == nullptr) { return false; } - //} - for (std::uint32_t c = 0; c <= mixdownSampleLength - 1U; ++c) { - float sample = outputPCM[c]; - if (sample > 1.0F) { - sample = 1.0F; - } else if (sample < -1.0F) { - sample = -1.0F; + if (channelCount > 1) { + std::uint32_t c = 0; + for (std::uint32_t x = 0; x < sampleCount * channelCount; x += channelCount) { + float sample = 0.0F; + for (int i = 0; i < channelCount; i++) { + sample += outputPCM[x + i]; + } + sample = sample / static_cast(channelCount); + if (sample > 1.0F) { + sample = 1.0F; + } + else if (sample < -1.0F) { + sample = -1.0F; + } + mixdownSamples[c] = static_cast(sample * LIMITER::max()); + c++; // lulz + } + } + else { + for (std::uint32_t c = 0; c < mixdownSampleLength; ++c) { + float sample = outputPCM[c]; + if (sample > 1.0F) { + sample = 1.0F; + } + else if (sample < -1.0F) { + sample = -1.0F; + } + mixdownSamples[c] = static_cast(sample * LIMITER::max()); } - mixdownSamples[c] = static_cast(sample * LIMITER::max()); } CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent( static_cast(userID), mixdownSamples, sampleCount, channelCount); - for (std::uint32_t c = 0; c <= mixdownSampleLength - 1; ++c) { - float mixedSample = 0.0F; - if (mixdownSamples[c] > 0) { - mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); - } else { - mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); + + if (channelCount > 1) { + std::uint32_t c = 0; + for (std::uint32_t x = 0; x < sampleCount * channelCount; x += channelCount) { + float mixedSample = 0.0F; + if (mixdownSamples[c] > 0) { + mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); + } + else { + mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); + } + mixedSample = mixedSample / static_cast(channelCount); + for (int i = 0; i < channelCount; i++) { + outputPCM[x + i] = mixedSample; + } + c++; + } + } + else { + for (std::uint32_t c = 0; c < mixdownSampleLength; ++c) { + float mixedSample = 0.0F; + if (mixdownSamples[c] > 0) { + mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); + } + else { + mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); + } + outputPCM[c] = mixedSample; } - outputPCM[c] = mixedSample; } delete[] mixdownSamples; return true; From 588a56361fe6cf9e9a379c984e9fd23a570caab7 Mon Sep 17 00:00:00 2001 From: jonpas Date: Mon, 15 Jun 2020 16:06:50 +0200 Subject: [PATCH 048/104] Cleanup ACRE2Steam parameters parsing --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 238 ------------------ 1 file changed, 238 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 6e195f2e4..2207f7393 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -43,244 +43,6 @@ void __stdcall RVExtensionVersion(char *output, int outputSize) { sprintf_s(output, outputSize - 1, "%s", ACRE_VERSION); } -std::vector split(const std::string &s, char delim) { - std::vector elems; - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) { - elems.push_back(item); - } - return elems; -} - -inline std::string get_path() { - char moduleName[MAX_PATH]; - GetModuleFileNameA(nullptr, moduleName, MAX_PATH); - return std::string(moduleName); -} - -std::vector get_cmdline() { - std::vector cmdline(split(GetCommandLineA(), ' ')); - - const std::string par_opt("-par="); - std::string par_path; - for (auto const& option : cmdline) { - if (option.rfind(par_opt, 0) != std::string::npos) { - par_path = option.substr(par_opt.length()); - break; - } - } - - // Append all options from parameter file - if (!par_path.empty()) { - std::ifstream par_file(par_path); - - if (par_file.is_open()) { - std::string line; - - std::getline(par_file, line); - if (line == "class Arg") { // ignore old format - par_file.close(); - return cmdline; - } - - par_file.seekg(0, par_file.beg); - - while (std::getline(par_file, line)) { - cmdline.push_back(line); - } - - par_file.close(); - } - } - - return cmdline; -} - -inline std::string get_path(const std::string &filepath) { - char drive[_MAX_DRIVE]; - char dir [_MAX_DIR]; - - _splitpath( - filepath.c_str(), - drive, - dir, - nullptr, - nullptr - ); - - return (std::string(drive) + std::string(dir)); -} - -inline std::string get_quoted(std::string &text) { - std::string found_text = ""; - - std::string::size_type start_position = text.find("\""); - if (start_position != std::string::npos) { - ++start_position; // start after the double quotes. - // look for end position; - std::string::size_type end_position = text.find("\""); - if (end_position != std::string::npos) { - found_text = text.substr(start_position, end_position - start_position); - } - } - return found_text; -} -EXTERN_C IMAGE_DOS_HEADER __ImageBase; - -inline std::string find_mod_folder() { - char module_path[MAX_PATH]; - GetModuleFileNameA((HINSTANCE)&__ImageBase, module_path, MAX_PATH); - - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - - _splitpath( - module_path, - drive, - dir, - NULL, - NULL - ); - - return (std::string(drive) + std::string(dir)); -} - -inline std::string find_mod_file(const std::string &filename) { - std::string path = find_mod_folder() + filename; - if (!PathFileExistsA(path.c_str())) { - // No mod path was set, it means they used the mod config. It *DOES* mean it relative to a folder in our path at least. - // So, we just search all the local folders - - WIN32_FIND_DATAA data; - std::string path(""); - HANDLE hFile = FindFirstFileA(path.c_str(), &data); - - if (hFile == INVALID_HANDLE_VALUE) - return ""; - - while ((FindNextFile(hFile, &data) != 0) || (GetLastError() != ERROR_NO_MORE_FILES)) { - if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - const std::string fullpath = std::string(data.cFileName) + filename; - if (PathFileExistsA(fullpath.c_str())) { - path = fullpath; - break; - } - } - } - } - return path; -} - -std::string ReadRegValue(HKEY root, const std::string &key, const std::string &name) { - HKEY hkey; - if (RegOpenKeyExA(root, key.c_str(), 0, KEY_READ, &hkey) != ERROR_SUCCESS) { - return ""; - } - - DWORD type; - DWORD cbData; - if (RegQueryValueExA(hkey, name.c_str(), nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { - RegCloseKey(hkey); - return ""; - } - - if (type != REG_SZ) { - RegCloseKey(hkey); - return ""; - } - - std::string value(cbData / sizeof(char), '\0'); - if (RegQueryValueExA(hkey, name.c_str(), nullptr, nullptr, reinterpret_cast(&value[0]), &cbData) != ERROR_SUCCESS) { - RegCloseKey(hkey); - return ""; - } - - RegCloseKey(hkey); - - size_t firstNull = value.find_first_of('\0'); - if (firstNull != std::string::npos) { - value.resize(firstNull); - } - - return value; -} - -std::string ReadRegValue64(HKEY root, const std::string &key, const std::string &name) { - HKEY hkey; - if (RegOpenKeyExA(root, key.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hkey) != ERROR_SUCCESS) - return ""; - - DWORD type; - DWORD cbData; - if (RegQueryValueExA(hkey, name.c_str(), nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { - RegCloseKey(hkey); - return ""; - } - - if (type != REG_SZ) { - RegCloseKey(hkey); - return ""; - } - - std::string value(cbData / sizeof(char), '\0'); - if (RegQueryValueExA(hkey, name.c_str(), nullptr, nullptr, reinterpret_cast(&value[0]), &cbData) != ERROR_SUCCESS) { - RegCloseKey(hkey); - return ""; - } - - RegCloseKey(hkey); - - size_t firstNull = value.find_first_of('\0'); - if (firstNull != std::string::npos) - value.resize(firstNull); - - return value; -} - -bool compare_file(const std::string &pathA, const std::string &pathB) { - - // Open both files ath the end to check their size - std::ifstream fileA(pathA, std::ifstream::ate | std::ifstream::binary); - std::ifstream fileB(pathB, std::ifstream::ate | std::ifstream::binary); - - if (fileA.tellg() != fileB.tellg()) { - return false; - } - - // Files are of the same size. Rewind and compare file contents - fileA.seekg(0); - fileB.seekg(0); - - std::istreambuf_iterator beginA(fileA); - std::istreambuf_iterator beginB(fileB); - - return std::equal(beginA, std::istreambuf_iterator(), beginB); -} - -bool skip_plugin_copy() { - for (auto const& option : get_cmdline()) { - if (option == "-skipAcrePluginCopy") { - return true; - } - } - - return false; -} - -void checkTsLocations(const std::string &appData, const std::string &rootkey, const HKEY key, std::vector &tsLocations, std::vector &tsDeleteLocations) { - if (rootkey != "") { - const std::string configLocation = ReadRegValue64(key, "SOFTWARE\\TeamSpeak 3 Client", "ConfigLocation"); - if (configLocation == "0") { - tsLocations.push_back(appData); - tsDeleteLocations.push_back(rootkey); - } else { - tsLocations.push_back(rootkey); - tsDeleteLocations.push_back(rootkey + "\\config"); - } - } -} - void __stdcall RVExtension(char *output, int outputSize, const char *function) { size_t id_length = 1; std::string functionStr(function); From 2800b1e2b1ead173f4dc69fcce61c664c4693109 Mon Sep 17 00:00:00 2001 From: jonpas Date: Mon, 15 Jun 2020 16:39:49 +0200 Subject: [PATCH 049/104] v2.7.4.1028 --- addons/main/script_version.hpp | 2 +- extensions/src/ACRE2Shared/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index eac0a4f45..13286cf02 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 2 #define MINOR 7 #define PATCHLVL 4 -#define BUILD 1027 +#define BUILD 1028 diff --git a/extensions/src/ACRE2Shared/version.h b/extensions/src/ACRE2Shared/version.h index 939d1b78c..20c9d263b 100644 --- a/extensions/src/ACRE2Shared/version.h +++ b/extensions/src/ACRE2Shared/version.h @@ -1,4 +1,4 @@ #define ACRE_VERSION_MAJOR 2 #define ACRE_VERSION_MINOR 7 #define ACRE_VERSION_SUBMINOR 4 -#define ACRE_VERSION_BUILD 1027 +#define ACRE_VERSION_BUILD 1028 From 95096849a86023f108a86d9d6fc8d2fe32d0b71d Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Mon, 15 Jun 2020 13:32:47 -0700 Subject: [PATCH 050/104] Force channel count being 1 into ACRE sound engine. This is a mess but its legacy and a larger fix is not worth it right now. --- extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index e904f627d..7a7c3314b 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -68,7 +68,7 @@ bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_ } CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent( - static_cast(userID), mixdownSamples, sampleCount, channelCount); + static_cast(userID), mixdownSamples, sampleCount, 1); if (channelCount > 1) { From f55914f3ca0885dbfeca97c6de82e8d8392deb42 Mon Sep 17 00:00:00 2001 From: Cliff Foster Date: Mon, 15 Jun 2020 13:44:14 -0700 Subject: [PATCH 051/104] Comment --- extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 7a7c3314b..a1ef2a75b 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -67,6 +67,8 @@ bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_ } } + // should always be channel count of 1 since everything is mono and mumble is ... using stereo + // dumb legacy crap. CEngine::getInstance()->getSoundEngine()->onEditPlaybackVoiceDataEvent( static_cast(userID), mixdownSamples, sampleCount, 1); From 77c5cf927b187034d6c7edbb414af14dfe18b45c Mon Sep 17 00:00:00 2001 From: jonpas Date: Mon, 15 Jun 2020 23:20:28 +0200 Subject: [PATCH 052/104] v2.7.4.1029 --- addons/main/script_version.hpp | 2 +- extensions/src/ACRE2Shared/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index 13286cf02..716456db8 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 2 #define MINOR 7 #define PATCHLVL 4 -#define BUILD 1028 +#define BUILD 1029 diff --git a/extensions/src/ACRE2Shared/version.h b/extensions/src/ACRE2Shared/version.h index 20c9d263b..9517ac9e0 100644 --- a/extensions/src/ACRE2Shared/version.h +++ b/extensions/src/ACRE2Shared/version.h @@ -1,4 +1,4 @@ #define ACRE_VERSION_MAJOR 2 #define ACRE_VERSION_MINOR 7 #define ACRE_VERSION_SUBMINOR 4 -#define ACRE_VERSION_BUILD 1028 +#define ACRE_VERSION_BUILD 1029 From df445769cc2b2facad028c6ecaa4667d21ecf8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Mon, 22 Jun 2020 21:10:33 +0200 Subject: [PATCH 053/104] Fix string duplication when retrying --- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index a1ef2a75b..4a38422a5 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -46,21 +46,18 @@ bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_ sample = sample / static_cast(channelCount); if (sample > 1.0F) { sample = 1.0F; - } - else if (sample < -1.0F) { + } else if (sample < -1.0F) { sample = -1.0F; } mixdownSamples[c] = static_cast(sample * LIMITER::max()); c++; // lulz } - } - else { + } else { for (std::uint32_t c = 0; c < mixdownSampleLength; ++c) { float sample = outputPCM[c]; if (sample > 1.0F) { sample = 1.0F; - } - else if (sample < -1.0F) { + } else if (sample < -1.0F) { sample = -1.0F; } mixdownSamples[c] = static_cast(sample * LIMITER::max()); @@ -79,24 +76,22 @@ bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_ float mixedSample = 0.0F; if (mixdownSamples[c] > 0) { mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); - } - else { + } else { mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); } + mixedSample = mixedSample / static_cast(channelCount); for (int i = 0; i < channelCount; i++) { outputPCM[x + i] = mixedSample; } c++; } - } - else { + } else { for (std::uint32_t c = 0; c < mixdownSampleLength; ++c) { float mixedSample = 0.0F; if (mixdownSamples[c] > 0) { mixedSample = static_cast(mixdownSamples[c]) / LIMITER::max(); - } - else { + } else { mixedSample = -static_cast(mixdownSamples[c]) / LIMITER::min(); } outputPCM[c] = mixedSample; @@ -122,14 +117,11 @@ bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uin uint32_t speakerMask = SPEAKER_STEREO; // Make this faster - - // if (mixdownSamples == NULL || sampleCount * channelCount > mixdownSampleLength) { const uint32_t mixdownSampleLength = sampleCount * channelCount; int16_t *mixdownSamples = new (std::nothrow) int16_t[mixdownSampleLength]; if (mixdownSamples == nullptr) { return false; } - //} for (uint32_t c = 0; c <= mixdownSampleLength - 1U; ++c) { float sample = outputPCM[c]; From 3208d4aae5aee494624b8dc2e7e8bf3725cd074b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sun, 28 Jun 2020 13:28:51 +0200 Subject: [PATCH 054/104] Really add fix for deduplication --- extensions/src/ACRE2Steam/voip_plugin.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/extensions/src/ACRE2Steam/voip_plugin.cpp b/extensions/src/ACRE2Steam/voip_plugin.cpp index 0958ed1bb..63b9c41fb 100644 --- a/extensions/src/ACRE2Steam/voip_plugin.cpp +++ b/extensions/src/ACRE2Steam/voip_plugin.cpp @@ -170,6 +170,15 @@ idi::acre::UpdateCode VOIPPlugin::handle_update_plugin() noexcept { UpdateCode update_status = UpdateCode::update_not_necessary; + // Clean the error messages in case of retrying. + if (!last_error_msg.empty()) { + last_error_msg.clear(); + } + + if (!updated_paths.empty()) { + updated_paths.clear(); + } + for (const auto &location : plugin_locations) { std::filesystem::path plugin_folder(location + "/plugins"); From 5c84c317221181022410194a83bb73d319cb72fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sun, 28 Jun 2020 13:42:29 +0200 Subject: [PATCH 055/104] Update to latest API changes --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 2 +- .../ACRE2Mumble/mumble_includes/MumbleAPI.h | 469 +++++++------ .../mumble_includes/MumblePlugin.h | 636 +++++++++--------- .../mumble_includes/PluginComponents.h | 421 ++++++------ 4 files changed, 788 insertions(+), 740 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 1e64d694b..f83e681b4 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -38,7 +38,7 @@ void mumble_registerAPIFunctions(struct MumbleAPI api) { } } -mumble_error_t mumble_init(mumble_connection_t connection) { +mumble_error_t mumble_init(uint32_t connection) { if (connection != -1) { activeConnection = connection; } diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h index 1ef62eaa6..537a82c21 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h @@ -19,219 +19,262 @@ const version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PL struct MumbleAPI { - // -------- Memory management -------- - - /// Frees the given pointer. - /// - /// @param callerID The ID of the plugin calling this function - /// @param pointer The pointer to free - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *freeMemory)(plugin_id_t callerID, void *pointer); - - - - // -------- Getter functions -------- - - /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] connection A pointer to the memory location the ID should be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the - /// value of the provided pointer - mumble_error_t (PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t *connection); - - /// Fills in the information about the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID); - - /// Fills in the information about the given user's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The user's ID whose name should be obtained - /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getUserName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, char **userName); - - /// Fills in the information about the given channel's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The channel's ID whose name should be obtained - /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, char **channelName); - - /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter - /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the - /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users, - size_t *userCount); - - /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent - /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the - /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t **channels, size_t *channelCount); - - /// Gets the ID of the channel the given user is currently connected to. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the ID of the channel shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t *channel); - - /// Gets an array of all users in the specified channel. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The ID of the channel whose users shall be retrieved - /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has - /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function - /// returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, mumble_userid_t **userList, size_t *userCount); - - /// Gets the current transmission mode of the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t *transmissionMode); - - - - // -------- Request functions -------- - - /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set - /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of - /// restoring the previous state afterwards. - /// - /// @param callerID The ID of the plugin calling this function - /// @param transmissionMode The requested transmission mode - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); - - /// Requests Mumble to move the given user into the given channel - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param channelID The ID of the channel to move the user to - /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a - /// password for entering - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t channelID, const char *password); - - /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen - /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again - /// once it is no longer required - /// - /// @param callerID The ID of the plugin calling this function - /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); - - - - // -------- Find functions -------- - - /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userName The respective user's name - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t (PLUGIN_CALLING_CONVENTION *findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char *userName, - mumble_userid_t *userID); - - /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelName The respective channel's name - /// @param[out] channelID A pointer to the memory the channel's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t (PLUGIN_CALLING_CONVENTION *findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, - const char *channelName, mumble_channelid_t *channelID); - - - - // -------- Miscellaneous -------- - - /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active - /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data - /// must not contain sensitive information or anything else that shouldn't be known by others. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to send the data through (the server the given users are on) - /// @param users An array of user IDs to send the data to - /// @param userCount The size of the provided user-array - /// @param data The data that shall be sent as a String - /// @param dataLength The length of the data-string - /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with - /// the data - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *users, - size_t userCount, const char *data, size_t dataLength, const char *dataID); - - /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. - /// - /// @param callerID The ID of the plugin calling this function - /// @param message The message to log - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *log)(plugin_id_t callerID, const char *message); - - /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it - /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). - /// - /// @param callerID The ID of the plugin calling this function - /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *playSample)(plugin_id_t callerID, const char *samplePath); + ///////////////////////////////////////////////////////// + ////////////////////// GENERAL NOTE ///////////////////// + ///////////////////////////////////////////////////////// + // + // All functions that take in a connection as a paremeter may only be called **after** the connection + // has finished synchronizing. The only exception from this is isConnectionSynchronized. + + + // -------- Memory management -------- + + /// Frees the given pointer. + /// + /// @param callerID The ID of the plugin calling this function + /// @param pointer The pointer to free + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* freeMemory)(plugin_id_t callerID, void* pointer); + + + + // -------- Getter functions -------- + + /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] connection A pointer to the memory location the ID should be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the + /// value of the provided pointer + mumble_error_t(PLUGIN_CALLING_CONVENTION* getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t* connection); + + /// Checks whether the given connection has finished initializing yet. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished synchronization yet + /// after this function has executed successfully. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* isConnectionSynchronized)(plugin_id_t callerID, mumble_connection_t connection, bool* synchronized); + + /// Fills in the information about the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t* userID); + + /// Fills in the information about the given user's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The user's ID whose name should be obtained + /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getUserName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, char** userName); + + /// Fills in the information about the given channel's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The channel's ID whose name should be obtained + /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, char** channelName); + + /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter + /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the + /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t** users, + size_t* userCount); + + /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent + /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the + /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t** channels, size_t* channelCount); + + /// Gets the ID of the channel the given user is currently connected to. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the ID of the channel shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t* channel); + + /// Gets an array of all users in the specified channel. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The ID of the channel whose users shall be retrieved + /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has + /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function + /// returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, mumble_userid_t** userList, size_t* userCount); + + /// Gets the current transmission mode of the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t* transmissionMode); + + /// Checks whether the given user is currently locally muted. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the local mute state of that user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* isUserLocallyMuted)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, bool* muted); + + + // -------- Request functions -------- + + /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set + /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of + /// restoring the previous state afterwards. + /// + /// @param callerID The ID of the plugin calling this function + /// @param transmissionMode The requested transmission mode + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); + + /// Requests Mumble to move the given user into the given channel + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param channelID The ID of the channel to move the user to + /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a + /// password for entering + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t channelID, const char* password); + + /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen + /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again + /// once it is no longer required + /// + /// @param callerID The ID of the plugin calling this function + /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); + + /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute state + /// opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client has muted its + /// microphone and thus isn't transmitting any audio). + /// Furthermore it must be noted that muting the local user with this function does not work (it doesn't make sense). If + /// you try to do so, this function will fail. In order to make this work, this function will also fail if the server + /// has not finished synchronizing with the client yet. + /// + /// @param callerID The ID of the plugin calling this function. + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param muted Whether to locally mute the given client (opposed to unmuting it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalMute)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, bool muted); + + + + // -------- Find functions -------- + + /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userName The respective user's name + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char* userName, + mumble_userid_t* userID); + + /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelName The respective channel's name + /// @param[out] channelID A pointer to the memory the channel's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, + const char* channelName, mumble_channelid_t* channelID); + + + + // -------- Miscellaneous -------- + + /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active + /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data + /// must not contain sensitive information or anything else that shouldn't be known by others. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to send the data through (the server the given users are on) + /// @param users An array of user IDs to send the data to + /// @param userCount The size of the provided user-array + /// @param data The data that shall be sent as a String + /// @param dataLength The length of the data-string + /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with + /// the data + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t* users, + size_t userCount, const char* data, size_t dataLength, const char* dataID); + + /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. + /// + /// @param callerID The ID of the plugin calling this function + /// @param message The message to log + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* log)(plugin_id_t callerID, const char* message); + + /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it + /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). + /// + /// @param callerID The ID of the plugin calling this function + /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* playSample)(plugin_id_t callerID, const char* samplePath); }; #endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h index c6c82393d..38ddcdc28 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h @@ -15,335 +15,331 @@ #include #if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems - #define PLUGIN_EXPORT __attribute__((visibility("default"))) +#define PLUGIN_EXPORT __attribute__((visibility("default"))) #elif defined(_MSC_VER) - #define PLUGIN_EXPORT __declspec(dllexport) +#define PLUGIN_EXPORT __declspec(dllexport) #elif defined(__MINGW32__) - #define PLUGIN_EXPORT __attribute__((dllexport)) +#define PLUGIN_EXPORT __attribute__((dllexport)) #else - #error No PLUGIN_EXPORT definition available +#error No PLUGIN_EXPORT definition available #endif #ifdef __cplusplus extern "C" { #endif - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Gets called right after loading the plugin in order to let the plugin initialize. - /// - /// @param connection The ID of the server-connection this event is connected to, or its default value. - /// @returns The status of the initialization. If everything went fine, return STATUS_OK - PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_connection_t connection); - - /// Gets called when unloading the plugin in order to allow it to clean up after itself. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); - - /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied - /// for further usage though. - /// - /// @returns A pointer to the plugin name (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); - - /// Gets the Version of the plugin-API this plugin intends to use. - /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. - /// - /// @return The respective API Version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); - - /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used - /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use - /// of it at some point. - /// - /// @param api The MumbleAPI struct - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); - - - - ////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Tells the plugin some basic information about the Mumble client loading it. - /// This function will be the first one that is being called on this plugin - even before it is decided whether to load - /// the plugin at all. - /// - /// @param mumbleVersion The Version of the Mumble client - /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with - /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); - - /// Gets the Version of this plugin - /// - /// @returns The plugin's version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); - - /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the author(s) name(s) (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); - - /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the description (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); - - /// Registers the ID of this plugin. This is the ID Mumble will reference this plugin with and by which this plugin - /// can identify itself when communicating with Mumble. - /// - /// @param id The ID for this plugin - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerPluginID(uint32_t id); - - /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum - /// together. - /// - /// @returns The feature set of this plugin - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); - - /// Requests this plugin to deactivate the given (sub)set of provided features. - /// If this is not possible, the features that can't be deactivated shall be returned by this function. - /// - /// Example (check if FEATURE_POSITIONAL shall be deactivated): - /// @code - /// if (features & FEATURE_POSITIONAL) { - /// // positional shall be deactivated - /// }; - /// @endcode - /// - /// @param features The feature set that shall be deactivated - /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return - /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); - - - - ////////////////////////////////////////////////////////////////////////////////// - //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - // If this plugin wants to provide positional audio, all functions of this category - // have to be implemented - - /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently - /// able to do so and allocate memory that is needed for that process. - /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i - /// belongs to a program whose name is listed at index i in the "name-array". - /// - /// @param programNames An array of pointers to the program names - /// @param programPIDs An array of the corresponding program PIDs - /// @param programCount The length of programNames and programPIDs - /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently - /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) - /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be - /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. - PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); - - /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. - /// - /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it - /// is facing). - /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One - /// unit represents one meter of distance. - /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it - /// is facing). - /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit - /// represents one meter of distance. - /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data - /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical - /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function - /// or until shutdownPositionalData is called. - /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can - /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid - /// until the next invokation of this function or until shutdownPositionalData is called. - /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will - /// be called. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, - float *cameraAxis, const char **context, const char **identity); - - /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should - /// be freed at this point. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Called when connecting to a server. - /// - /// @param connection The ID of the newly established server-connection - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); - - /// Called when disconnecting from a server. - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); - - /// Called when the client has finished synchronizing with the server - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); - - /// Called whenever any user on the server enters a channel - /// This function will also be called when freshly connecting to a server as each user on that - /// server needs to be "added" to the respective channel as far as the local client is concerned. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user this event has been triggered for - /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user - /// freshly connected to the server) or the channel isn't available because of any other reason. - /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means - /// that the ID is invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, - mumble_channelid_t newChannelID); - - /// Called whenever a user leaves a channel. - /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user that left the channel - /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is - /// invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); - - /// Called when any user changes his/her talking state. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user whose talking state has been changed - /// @param talkingState The new TalkingState the user has switched to. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); - - /// Called whenever there is audio input. - /// - /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) - /// @returns Whether this callback has modified the audio input-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); - - /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). - /// The provided audio buffer is the raw buffer without any processing applied to it yet. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) - /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, - /// the content of this parameter is unspecified and should not be accessed - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); - - /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). - /// Note that this happens immediately before Mumble clips the audio buffer. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); - - /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the - /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended - /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. - /// - /// @param connection The ID of the server-connection the data is coming from - /// @param sender The ID of the user whose client's plugin has sent the data - /// @param data The sent data represented as a string - /// @param dataLength The length of data - /// @param dataID The ID of this data - /// @return Whether the given data has been processed by this plugin - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, - const char *dataID); - - /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the - /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this - /// method will be called for every client already on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been added - - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the - /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this - /// method will be called for every client on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local - /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been added - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local - /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also - /// considered renaming). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been renamed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a key has been pressed or released while Mumble has keyboard focus. - /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard - /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to - /// enable that. - /// - /// @param keyCode The key code of the respective key. The character codes are defined - /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform - /// to the ASCII code-page with the only difference that case is not distinguished. Therefore - /// always the upper-case letter code will be used for letters. - /// @param wasPres Whether the respective key has been pressed (instead of released) - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// This function is used to determine whether the plugin can find an update for itself that is available for download. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @return Whether the plugin was able to find an update for itself - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); - - /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. - /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure - /// though that you don't forget about the trailing null byte. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into - /// @param bufferSize The size of the buffer - /// @param offset The offset in the URL from which this functions should start writing it to the buffer - /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called - /// again with a modified offset until the URL has been completely transferred. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Gets called right after loading the plugin in order to let the plugin initialize. + /// + /// Registers the ID of this plugin. + /// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with + /// and by which this plugin can identify itself when communicating with Mumble. + /// @returns The status of the initialization. If everything went fine, return STATUS_OK + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(uint32_t id); + + /// Gets called when unloading the plugin in order to allow it to clean up after itself. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); + + /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied + /// for further usage though. + /// + /// @returns A pointer to the plugin name (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); + + /// Gets the Version of the plugin-API this plugin intends to use. + /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. + /// + /// @return The respective API Version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); + + /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used + /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use + /// of it at some point. + /// + /// @param api The MumbleAPI struct + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); + + + + ////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Tells the plugin some basic information about the Mumble client loading it. + /// This function will be the first one that is being called on this plugin - even before it is decided whether to load + /// the plugin at all. + /// + /// @param mumbleVersion The Version of the Mumble client + /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with + /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); + + /// Gets the Version of this plugin + /// + /// @returns The plugin's version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); + + /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the author(s) name(s) (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); + + /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the description (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); + + /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum + /// together. + /// + /// @returns The feature set of this plugin + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); + + /// Requests this plugin to deactivate the given (sub)set of provided features. + /// If this is not possible, the features that can't be deactivated shall be returned by this function. + /// + /// Example (check if FEATURE_POSITIONAL shall be deactivated): + /// @code + /// if (features & FEATURE_POSITIONAL) { + /// // positional shall be deactivated + /// }; + /// @endcode + /// + /// @param features The feature set that shall be deactivated + /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return + /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); + + + + ////////////////////////////////////////////////////////////////////////////////// + //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // If this plugin wants to provide positional audio, all functions of this category + // have to be implemented + + /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently + /// able to do so and allocate memory that is needed for that process. + /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i + /// belongs to a program whose name is listed at index i in the "name-array". + /// + /// @param programNames An array of pointers to the program names + /// @param programPIDs An array of the corresponding program PIDs + /// @param programCount The length of programNames and programPIDs + /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently + /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) + /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be + /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. + PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char** programNames, const uint64_t* programPIDs, size_t programCount); + + /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. + /// + /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it + /// is facing). + /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One + /// unit represents one meter of distance. + /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it + /// is facing). + /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit + /// represents one meter of distance. + /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data + /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical + /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function + /// or until shutdownPositionalData is called. + /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can + /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid + /// until the next invokation of this function or until shutdownPositionalData is called. + /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will + /// be called. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float* avatarPos, float* avatarDir, float* avatarAxis, float* cameraPos, float* cameraDir, + float* cameraAxis, const char** context, const char** identity); + + /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should + /// be freed at this point. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Called when connecting to a server. + /// + /// @param connection The ID of the newly established server-connection + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); + + /// Called when disconnecting from a server. + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); + + /// Called when the client has finished synchronizing with the server + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); + + /// Called whenever any user on the server enters a channel + /// This function will also be called when freshly connecting to a server as each user on that + /// server needs to be "added" to the respective channel as far as the local client is concerned. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user this event has been triggered for + /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user + /// freshly connected to the server) or the channel isn't available because of any other reason. + /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means + /// that the ID is invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, + mumble_channelid_t newChannelID); + + /// Called whenever a user leaves a channel. + /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user that left the channel + /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is + /// invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); + + /// Called when any user changes his/her talking state. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user whose talking state has been changed + /// @param talkingState The new TalkingState the user has switched to. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); + + /// Called whenever there is audio input. + /// + /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) + /// @returns Whether this callback has modified the audio input-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short* inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); + + /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). + /// The provided audio buffer is the raw buffer without any processing applied to it yet. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) + /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, + /// the content of this parameter is unspecified and should not be accessed + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); + + /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). + /// Note that this happens immediately before Mumble clips the audio buffer. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float* outputPCM, uint32_t sampleCount, uint16_t channelCount); + + /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the + /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended + /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. + /// + /// @param connection The ID of the server-connection the data is coming from + /// @param sender The ID of the user whose client's plugin has sent the data + /// @param data The sent data represented as a string + /// @param dataLength The length of data + /// @param dataID The ID of this data + /// @return Whether the given data has been processed by this plugin + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char* data, size_t dataLength, + const char* dataID); + + /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the + /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this + /// method will be called for every client already on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been added + + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the + /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this + /// method will be called for every client on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local + /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been added + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local + /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also + /// considered renaming). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been renamed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a key has been pressed or released while Mumble has keyboard focus. + /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard + /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to + /// enable that. + /// + /// @param keyCode The key code of the respective key. The character codes are defined + /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform + /// to the ASCII code-page with the only difference that case is not distinguished. Therefore + /// always the upper-case letter code will be used for letters. + /// @param wasPres Whether the respective key has been pressed (instead of released) + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// This function is used to determine whether the plugin can find an update for itself that is available for download. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @return Whether the plugin was able to find an update for itself + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); + + /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. + /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure + /// though that you don't forget about the trailing null byte. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into + /// @param bufferSize The size of the buffer + /// @param offset The offset in the URL from which this functions should start writing it to the buffer + /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called + /// again with a modified offset until the URL has been completely transferred. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char* buffer, uint16_t bufferSize, uint16_t offset); #ifdef __cplusplus diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h index b203eb1b7..ce684dbf9 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h @@ -13,16 +13,16 @@ #include #ifdef QT_VERSION - #include +#include #endif // define the calling convention macro based on the compiler being used #if defined(_MSC_VER) - #define PLUGIN_CALLING_CONVENTION __cdecl +#define PLUGIN_CALLING_CONVENTION __cdecl #elif defined(__MINGW32__) - #define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) +#define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) #else - #define PLUGIN_CALLING_CONVENTION +#define PLUGIN_CALLING_CONVENTION #endif @@ -35,224 +35,227 @@ /// This enum's values correspond to special feature sets a plugin may provide. /// They are meant to be or'ed together to represent the total feature set of a plugin. enum PluginFeature { - /// None of the below - FEATURE_NONE = 0, - /// The plugin provides positional data from a game - FEATURE_POSITIONAL = 1 << 0, - /// The plugin modifies the input/output audio itself - FEATURE_AUDIO = 1 << 1 + /// None of the below + FEATURE_NONE = 0, + /// The plugin provides positional data from a game + FEATURE_POSITIONAL = 1 << 0, + /// The plugin modifies the input/output audio itself + FEATURE_AUDIO = 1 << 1 }; /// This enum's values represent talking states a user can be in when using Mumble. enum TalkingState { - INVALID=-1, - PASSIVE=0, - TALKING, - WHISPERING, - SHOUTING + INVALID = -1, + PASSIVE = 0, + TALKING, + WHISPERING, + SHOUTING }; /// This enum's values represent transmission modes a user might have configured. Transmission mode /// in this context is referring to a method that determines when a user is speaking and thus when /// to transmit audio packets. enum TransmissionMode { - TM_CONTINOUS, - TM_VOICE_ACTIVATION, - TM_PUSH_TO_TALK + TM_CONTINOUS, + TM_VOICE_ACTIVATION, + TM_PUSH_TO_TALK }; /// This enum's values represent the error codes that are being used by the MumbleAPI. /// You can get a string-representation for each error code via the errorMessage function. enum ErrorCode { - EC_GENERIC_ERROR = -1, - EC_OK = 0, - EC_POINTER_NOT_FOUND, - EC_NO_ACTIVE_CONNECTION, - EC_USER_NOT_FOUND, - EC_CHANNEL_NOT_FOUND, - EC_CONNECTION_NOT_FOUND, - EC_UNKNOWN_TRANSMISSION_MODE, - EC_AUDIO_NOT_AVAILABLE, - EC_INVALID_SAMPLE, - EC_INVALID_PLUGIN_ID + EC_GENERIC_ERROR = -1, + EC_OK = 0, + EC_POINTER_NOT_FOUND, + EC_NO_ACTIVE_CONNECTION, + EC_USER_NOT_FOUND, + EC_CHANNEL_NOT_FOUND, + EC_CONNECTION_NOT_FOUND, + EC_UNKNOWN_TRANSMISSION_MODE, + EC_AUDIO_NOT_AVAILABLE, + EC_INVALID_SAMPLE, + EC_INVALID_PLUGIN_ID, + EC_INVALID_MUTE_TARGET, + EC_CONNECTION_UNSYNCHRONIZED, + EC_INVALID_API_VERSION }; /// This enum's values represent error codes specific to the framework of handling positional data /// gathering (needed for Mumble's positional audio feature). enum PositionalDataErrorCode { - /// Positional data has been initialized properly - PDEC_OK = 0, - /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be - /// at another point in time. - PDEC_ERROR_TEMP, - /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). - PDEC_ERROR_PERM + /// Positional data has been initialized properly + PDEC_OK = 0, + /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be + /// at another point in time. + PDEC_ERROR_TEMP, + /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). + PDEC_ERROR_PERM }; /// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. enum KeyCode { - KC_INVALID = -1, + KC_INVALID = -1, - // Non-printable characters first - KC_NULL = 0, - KC_END = 1, - KC_LEFT = 2, - KC_RIGHT = 4, - KC_UP = 5, - KC_DOWN = 6, - KC_DELETE = 7, - KC_BACKSPACE = 8, - KC_TAB = 9, - KC_ENTER = 10, // == '\n' - KC_ESCAPE = 27, - KC_PAGE_UP = 11, - KC_PAGE_DOWN = 12, - KC_SHIFT = 13, - KC_CONTROL = 14, - KC_META = 15, - KC_ALT = 16, - KC_ALT_GR = 17, - KC_CAPSLOCK = 18, - KC_NUMLOCK = 19, - KC_SUPER = 20, // == windows key - KC_HOME = 21, // == Pos1 - KC_PRINT = 22, - KC_SCROLLLOCK = 23, + // Non-printable characters first + KC_NULL = 0, + KC_END = 1, + KC_LEFT = 2, + KC_RIGHT = 4, + KC_UP = 5, + KC_DOWN = 6, + KC_DELETE = 7, + KC_BACKSPACE = 8, + KC_TAB = 9, + KC_ENTER = 10, // == '\n' + KC_ESCAPE = 27, + KC_PAGE_UP = 11, + KC_PAGE_DOWN = 12, + KC_SHIFT = 13, + KC_CONTROL = 14, + KC_META = 15, + KC_ALT = 16, + KC_ALT_GR = 17, + KC_CAPSLOCK = 18, + KC_NUMLOCK = 19, + KC_SUPER = 20, // == windows key + KC_HOME = 21, // == Pos1 + KC_PRINT = 22, + KC_SCROLLLOCK = 23, - // Printable characters are assigned to their ASCII code - KC_SPACE = ' ', - KC_EXCLAMATION_MARK = '!', - KC_DOUBLE_QUOTE = '"', - KC_HASHTAG = '#', - KC_DOLLAR = '$', - KC_PERCENT = '%', - KC_AMPERSAND = '&', - KC_SINGLE_QUOTE = '\'', - KC_OPEN_PARENTHESIS = '(', - KC_CLOSE_PARENTHESIS = ')', - KC_ASTERISK = '*', - KC_PLUS = '+', - KC_COMMA = ',', - KC_MINUS = '-', - KC_PERIOD = '.', - KC_SLASH = '/', - KC_0 = '0', - KC_1 = '1', - KC_2 = '2', - KC_3 = '3', - KC_4 = '4', - KC_5 = '5', - KC_6 = '6', - KC_7 = '7', - KC_8 = '8', - KC_9 = '9', - KC_COLON = ':', - KC_SEMICOLON = ';', - KC_LESS_THAN = '<', - KC_EQUALS = '=', - KC_GREATER_THAN = '>', - KC_QUESTION_MARK = '?', - KC_AT_SYMBOL = '@', - KC_A = 'A', - KC_B = 'B', - KC_C = 'C', - KC_D = 'D', - KC_E = 'E', - KC_F = 'F', - KC_G = 'G', - KC_H = 'H', - KC_I = 'I', - KC_J = 'J', - KC_K = 'K', - KC_L = 'L', - KC_M = 'M', - KC_N = 'N', - KC_O = 'O', - KC_P = 'P', - KC_Q = 'Q', - KC_R = 'R', - KC_S = 'S', - KC_T = 'T', - KC_U = 'U', - KC_V = 'V', - KC_W = 'W', - KC_X = 'X', - KC_Y = 'Y', - KC_Z = 'Z', - // leave out lowercase letters (for now) - KC_OPEN_BRACKET = '[', - KC_BACKSLASH = '\\', - KC_CLOSE_BRACKET = ']', - KC_CIRCUMFLEX = '^', - KC_UNDERSCORE = '_', - KC_GRAVE_AKCENT = '`', - KC_OPEN_BRACE = '{', - KC_VERTICAL_BAR = '|', - KC_CLOSE_BRACE = '}', - KC_TILDE = '~', + // Printable characters are assigned to their ASCII code + KC_SPACE = ' ', + KC_EXCLAMATION_MARK = '!', + KC_DOUBLE_QUOTE = '"', + KC_HASHTAG = '#', + KC_DOLLAR = '$', + KC_PERCENT = '%', + KC_AMPERSAND = '&', + KC_SINGLE_QUOTE = '\'', + KC_OPEN_PARENTHESIS = '(', + KC_CLOSE_PARENTHESIS = ')', + KC_ASTERISK = '*', + KC_PLUS = '+', + KC_COMMA = ',', + KC_MINUS = '-', + KC_PERIOD = '.', + KC_SLASH = '/', + KC_0 = '0', + KC_1 = '1', + KC_2 = '2', + KC_3 = '3', + KC_4 = '4', + KC_5 = '5', + KC_6 = '6', + KC_7 = '7', + KC_8 = '8', + KC_9 = '9', + KC_COLON = ':', + KC_SEMICOLON = ';', + KC_LESS_THAN = '<', + KC_EQUALS = '=', + KC_GREATER_THAN = '>', + KC_QUESTION_MARK = '?', + KC_AT_SYMBOL = '@', + KC_A = 'A', + KC_B = 'B', + KC_C = 'C', + KC_D = 'D', + KC_E = 'E', + KC_F = 'F', + KC_G = 'G', + KC_H = 'H', + KC_I = 'I', + KC_J = 'J', + KC_K = 'K', + KC_L = 'L', + KC_M = 'M', + KC_N = 'N', + KC_O = 'O', + KC_P = 'P', + KC_Q = 'Q', + KC_R = 'R', + KC_S = 'S', + KC_T = 'T', + KC_U = 'U', + KC_V = 'V', + KC_W = 'W', + KC_X = 'X', + KC_Y = 'Y', + KC_Z = 'Z', + // leave out lowercase letters (for now) + KC_OPEN_BRACKET = '[', + KC_BACKSLASH = '\\', + KC_CLOSE_BRACKET = ']', + KC_CIRCUMFLEX = '^', + KC_UNDERSCORE = '_', + KC_GRAVE_AKCENT = '`', + KC_OPEN_BRACE = '{', + KC_VERTICAL_BAR = '|', + KC_CLOSE_BRACE = '}', + KC_TILDE = '~', - // Some characters from the extended ASCII code - KC_DEGREE_SIGN = 176, + // Some characters from the extended ASCII code + KC_DEGREE_SIGN = 176, - // F-keys - // Start at a value of 256 as extended ASCII codes range up to 256 - KC_F1 = 256, - KC_F2 = 257, - KC_F3 = 258, - KC_F4 = 259, - KC_F5 = 260, - KC_F6 = 261, - KC_F7 = 262, - KC_F8 = 263, - KC_F9 = 264, - KC_F10 = 265, - KC_F11 = 266, - KC_F12 = 267, - KC_F13 = 268, - KC_F14 = 269, - KC_F15 = 270, - KC_F16 = 271, - KC_F17 = 272, - KC_F18 = 273, - KC_F19 = 274, + // F-keys + // Start at a value of 256 as extended ASCII codes range up to 256 + KC_F1 = 256, + KC_F2 = 257, + KC_F3 = 258, + KC_F4 = 259, + KC_F5 = 260, + KC_F6 = 261, + KC_F7 = 262, + KC_F8 = 263, + KC_F9 = 264, + KC_F10 = 265, + KC_F11 = 266, + KC_F12 = 267, + KC_F13 = 268, + KC_F14 = 269, + KC_F15 = 270, + KC_F16 = 271, + KC_F17 = 272, + KC_F18 = 273, + KC_F19 = 274, }; /// A struct for representing a version of the form major.minor.patch struct Version { - int32_t major; - int32_t minor; - int32_t patch; + int32_t major; + int32_t minor; + int32_t patch; #ifdef __cplusplus - bool operator<(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; - } + bool operator<(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; + } - bool operator>(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; - } + bool operator>(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; + } - bool operator>=(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; - } + bool operator>=(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; + } - bool operator<=(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; - } + bool operator<=(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; + } - bool operator==(const Version& other) const { - return this->major == other.major && this->minor == other.minor && this->patch == other.patch; - } + bool operator==(const Version& other) const { + return this->major == other.major && this->minor == other.minor && this->patch == other.patch; + } - operator std::string() const { - return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); - } + operator std::string() const { + return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); + } #ifdef QT_VERSION - operator QString() const { - return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); - } + operator QString() const { + return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); + } #endif #endif }; @@ -262,32 +265,38 @@ struct Version { /// is encoded as a C-string and are static meaning that it is safe to use the /// returned pointer in your code. inline const char* errorMessage(int16_t errorCode) { - switch (errorCode) { - case EC_GENERIC_ERROR: - return "Generic error"; - case EC_OK: - return "Ok - this is not an error"; - case EC_POINTER_NOT_FOUND: - return "Can't find the passed pointer"; - case EC_NO_ACTIVE_CONNECTION: - return "There is currently no active connection to a server"; - case EC_USER_NOT_FOUND: - return "Can't find the requested user"; - case EC_CHANNEL_NOT_FOUND: - return "Can't find the requested channel"; - case EC_CONNECTION_NOT_FOUND: - return "Can't identify the requested connection"; - case EC_UNKNOWN_TRANSMISSION_MODE: - return "Unknown transmission mode encountered"; - case EC_AUDIO_NOT_AVAILABLE: - return "There is currently no audio output available"; - case EC_INVALID_SAMPLE: - return "Attempted to use invalid sample (can't play it)"; - case EC_INVALID_PLUGIN_ID: - return "Used an invalid plugin ID"; - default: - return "Unknown error code"; - } + switch (errorCode) { + case EC_GENERIC_ERROR: + return "Generic error"; + case EC_OK: + return "Ok - this is not an error"; + case EC_POINTER_NOT_FOUND: + return "Can't find the passed pointer"; + case EC_NO_ACTIVE_CONNECTION: + return "There is currently no active connection to a server"; + case EC_USER_NOT_FOUND: + return "Can't find the requested user"; + case EC_CHANNEL_NOT_FOUND: + return "Can't find the requested channel"; + case EC_CONNECTION_NOT_FOUND: + return "Can't identify the requested connection"; + case EC_UNKNOWN_TRANSMISSION_MODE: + return "Unknown transmission mode encountered"; + case EC_AUDIO_NOT_AVAILABLE: + return "There is currently no audio output available"; + case EC_INVALID_SAMPLE: + return "Attempted to use invalid sample (can't play it)"; + case EC_INVALID_PLUGIN_ID: + return "Used an invalid plugin ID"; + case EC_INVALID_MUTE_TARGET: + return "Used an invalid mute-target"; + case EC_CONNECTION_UNSYNCHRONIZED: + return "The requested server connection has not yet finished synchrnonizing"; + case EC_INVALID_API_VERSION: + return "The used API version is invalid or not supported"; + default: + return "Unknown error code"; + } } From 40a0881f1e56ee3a3d85c5eecfd6c1b7acd21528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sun, 28 Jun 2020 13:48:22 +0200 Subject: [PATCH 056/104] Do not format mumble plugins --- .../ACRE2Mumble/mumble_includes/MumbleAPI.h | 512 +++++++------- .../mumble_includes/MumblePlugin.h | 632 +++++++++--------- .../mumble_includes/PluginComponents.h | 430 ++++++------ 3 files changed, 787 insertions(+), 787 deletions(-) diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h index 537a82c21..6667e712d 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h @@ -19,262 +19,262 @@ const version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PL struct MumbleAPI { - ///////////////////////////////////////////////////////// - ////////////////////// GENERAL NOTE ///////////////////// - ///////////////////////////////////////////////////////// - // - // All functions that take in a connection as a paremeter may only be called **after** the connection - // has finished synchronizing. The only exception from this is isConnectionSynchronized. - - - // -------- Memory management -------- - - /// Frees the given pointer. - /// - /// @param callerID The ID of the plugin calling this function - /// @param pointer The pointer to free - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* freeMemory)(plugin_id_t callerID, void* pointer); - - - - // -------- Getter functions -------- - - /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] connection A pointer to the memory location the ID should be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the - /// value of the provided pointer - mumble_error_t(PLUGIN_CALLING_CONVENTION* getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t* connection); - - /// Checks whether the given connection has finished initializing yet. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished synchronization yet - /// after this function has executed successfully. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* isConnectionSynchronized)(plugin_id_t callerID, mumble_connection_t connection, bool* synchronized); - - /// Fills in the information about the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t* userID); - - /// Fills in the information about the given user's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The user's ID whose name should be obtained - /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getUserName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, char** userName); - - /// Fills in the information about the given channel's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The channel's ID whose name should be obtained - /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, char** channelName); - - /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter - /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the - /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t** users, - size_t* userCount); - - /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent - /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the - /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t** channels, size_t* channelCount); - - /// Gets the ID of the channel the given user is currently connected to. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the ID of the channel shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t* channel); - - /// Gets an array of all users in the specified channel. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The ID of the channel whose users shall be retrieved - /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has - /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function - /// returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, mumble_userid_t** userList, size_t* userCount); - - /// Gets the current transmission mode of the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t* transmissionMode); - - /// Checks whether the given user is currently locally muted. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the local mute state of that user shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* isUserLocallyMuted)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, bool* muted); - - - // -------- Request functions -------- - - /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set - /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of - /// restoring the previous state afterwards. - /// - /// @param callerID The ID of the plugin calling this function - /// @param transmissionMode The requested transmission mode - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); - - /// Requests Mumble to move the given user into the given channel - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param channelID The ID of the channel to move the user to - /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a - /// password for entering - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t channelID, const char* password); - - /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen - /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again - /// once it is no longer required - /// - /// @param callerID The ID of the plugin calling this function - /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); - - /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute state - /// opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client has muted its - /// microphone and thus isn't transmitting any audio). - /// Furthermore it must be noted that muting the local user with this function does not work (it doesn't make sense). If - /// you try to do so, this function will fail. In order to make this work, this function will also fail if the server - /// has not finished synchronizing with the client yet. - /// - /// @param callerID The ID of the plugin calling this function. - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param muted Whether to locally mute the given client (opposed to unmuting it) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalMute)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, bool muted); - - - - // -------- Find functions -------- - - /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userName The respective user's name - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION* findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char* userName, - mumble_userid_t* userID); - - /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelName The respective channel's name - /// @param[out] channelID A pointer to the memory the channel's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION* findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, - const char* channelName, mumble_channelid_t* channelID); - - - - // -------- Miscellaneous -------- - - /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active - /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data - /// must not contain sensitive information or anything else that shouldn't be known by others. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to send the data through (the server the given users are on) - /// @param users An array of user IDs to send the data to - /// @param userCount The size of the provided user-array - /// @param data The data that shall be sent as a String - /// @param dataLength The length of the data-string - /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with - /// the data - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t* users, - size_t userCount, const char* data, size_t dataLength, const char* dataID); - - /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. - /// - /// @param callerID The ID of the plugin calling this function - /// @param message The message to log - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* log)(plugin_id_t callerID, const char* message); - - /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it - /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). - /// - /// @param callerID The ID of the plugin calling this function - /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* playSample)(plugin_id_t callerID, const char* samplePath); + ///////////////////////////////////////////////////////// + ////////////////////// GENERAL NOTE ///////////////////// + ///////////////////////////////////////////////////////// + // + // All functions that take in a connection as a paremeter may only be called **after** the connection + // has finished synchronizing. The only exception from this is isConnectionSynchronized. + + + // -------- Memory management -------- + + /// Frees the given pointer. + /// + /// @param callerID The ID of the plugin calling this function + /// @param pointer The pointer to free + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *freeMemory)(plugin_id_t callerID, void *pointer); + + + + // -------- Getter functions -------- + + /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] connection A pointer to the memory location the ID should be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the + /// value of the provided pointer + mumble_error_t (PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t *connection); + + /// Checks whether the given connection has finished initializing yet. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished synchronization yet + /// after this function has executed successfully. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *isConnectionSynchronized)(plugin_id_t callerID, mumble_connection_t connection, bool *synchronized); + + /// Fills in the information about the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID); + + /// Fills in the information about the given user's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The user's ID whose name should be obtained + /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getUserName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, char **userName); + + /// Fills in the information about the given channel's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The channel's ID whose name should be obtained + /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, char **channelName); + + /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter + /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the + /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users, + size_t *userCount); + + /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent + /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the + /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t **channels, size_t *channelCount); + + /// Gets the ID of the channel the given user is currently connected to. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the ID of the channel shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t *channel); + + /// Gets an array of all users in the specified channel. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The ID of the channel whose users shall be retrieved + /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has + /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function + /// returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, mumble_userid_t **userList, size_t *userCount); + + /// Gets the current transmission mode of the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t *transmissionMode); + + /// Checks whether the given user is currently locally muted. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the local mute state of that user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *isUserLocallyMuted)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, bool *muted); + + + // -------- Request functions -------- + + /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set + /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of + /// restoring the previous state afterwards. + /// + /// @param callerID The ID of the plugin calling this function + /// @param transmissionMode The requested transmission mode + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); + + /// Requests Mumble to move the given user into the given channel + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param channelID The ID of the channel to move the user to + /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a + /// password for entering + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t channelID, const char *password); + + /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen + /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again + /// once it is no longer required + /// + /// @param callerID The ID of the plugin calling this function + /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); + + /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute state + /// opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client has muted its + /// microphone and thus isn't transmitting any audio). + /// Furthermore it must be noted that muting the local user with this function does not work (it doesn't make sense). If + /// you try to do so, this function will fail. In order to make this work, this function will also fail if the server + /// has not finished synchronizing with the client yet. + /// + /// @param callerID The ID of the plugin calling this function. + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param muted Whether to locally mute the given client (opposed to unmuting it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalMute)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, bool muted); + + + + // -------- Find functions -------- + + /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userName The respective user's name + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t (PLUGIN_CALLING_CONVENTION *findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char *userName, + mumble_userid_t *userID); + + /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelName The respective channel's name + /// @param[out] channelID A pointer to the memory the channel's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t (PLUGIN_CALLING_CONVENTION *findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, + const char *channelName, mumble_channelid_t *channelID); + + + + // -------- Miscellaneous -------- + + /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active + /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data + /// must not contain sensitive information or anything else that shouldn't be known by others. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to send the data through (the server the given users are on) + /// @param users An array of user IDs to send the data to + /// @param userCount The size of the provided user-array + /// @param data The data that shall be sent as a String + /// @param dataLength The length of the data-string + /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with + /// the data + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *users, + size_t userCount, const char *data, size_t dataLength, const char *dataID); + + /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. + /// + /// @param callerID The ID of the plugin calling this function + /// @param message The message to log + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *log)(plugin_id_t callerID, const char *message); + + /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it + /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). + /// + /// @param callerID The ID of the plugin calling this function + /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *playSample)(plugin_id_t callerID, const char *samplePath); }; #endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h index 38ddcdc28..dcb6b2710 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h @@ -15,331 +15,331 @@ #include #if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems -#define PLUGIN_EXPORT __attribute__((visibility("default"))) + #define PLUGIN_EXPORT __attribute__((visibility("default"))) #elif defined(_MSC_VER) -#define PLUGIN_EXPORT __declspec(dllexport) + #define PLUGIN_EXPORT __declspec(dllexport) #elif defined(__MINGW32__) -#define PLUGIN_EXPORT __attribute__((dllexport)) + #define PLUGIN_EXPORT __attribute__((dllexport)) #else -#error No PLUGIN_EXPORT definition available + #error No PLUGIN_EXPORT definition available #endif #ifdef __cplusplus extern "C" { #endif - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Gets called right after loading the plugin in order to let the plugin initialize. - /// - /// Registers the ID of this plugin. - /// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with - /// and by which this plugin can identify itself when communicating with Mumble. - /// @returns The status of the initialization. If everything went fine, return STATUS_OK - PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(uint32_t id); - - /// Gets called when unloading the plugin in order to allow it to clean up after itself. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); - - /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied - /// for further usage though. - /// - /// @returns A pointer to the plugin name (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); - - /// Gets the Version of the plugin-API this plugin intends to use. - /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. - /// - /// @return The respective API Version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); - - /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used - /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use - /// of it at some point. - /// - /// @param api The MumbleAPI struct - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); - - - - ////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Tells the plugin some basic information about the Mumble client loading it. - /// This function will be the first one that is being called on this plugin - even before it is decided whether to load - /// the plugin at all. - /// - /// @param mumbleVersion The Version of the Mumble client - /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with - /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); - - /// Gets the Version of this plugin - /// - /// @returns The plugin's version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); - - /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the author(s) name(s) (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); - - /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the description (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); - - /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum - /// together. - /// - /// @returns The feature set of this plugin - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); - - /// Requests this plugin to deactivate the given (sub)set of provided features. - /// If this is not possible, the features that can't be deactivated shall be returned by this function. - /// - /// Example (check if FEATURE_POSITIONAL shall be deactivated): - /// @code - /// if (features & FEATURE_POSITIONAL) { - /// // positional shall be deactivated - /// }; - /// @endcode - /// - /// @param features The feature set that shall be deactivated - /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return - /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); - - - - ////////////////////////////////////////////////////////////////////////////////// - //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - // If this plugin wants to provide positional audio, all functions of this category - // have to be implemented - - /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently - /// able to do so and allocate memory that is needed for that process. - /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i - /// belongs to a program whose name is listed at index i in the "name-array". - /// - /// @param programNames An array of pointers to the program names - /// @param programPIDs An array of the corresponding program PIDs - /// @param programCount The length of programNames and programPIDs - /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently - /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) - /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be - /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. - PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char** programNames, const uint64_t* programPIDs, size_t programCount); - - /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. - /// - /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it - /// is facing). - /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One - /// unit represents one meter of distance. - /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it - /// is facing). - /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit - /// represents one meter of distance. - /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data - /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical - /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function - /// or until shutdownPositionalData is called. - /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can - /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid - /// until the next invokation of this function or until shutdownPositionalData is called. - /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will - /// be called. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float* avatarPos, float* avatarDir, float* avatarAxis, float* cameraPos, float* cameraDir, - float* cameraAxis, const char** context, const char** identity); - - /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should - /// be freed at this point. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Called when connecting to a server. - /// - /// @param connection The ID of the newly established server-connection - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); - - /// Called when disconnecting from a server. - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); - - /// Called when the client has finished synchronizing with the server - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); - - /// Called whenever any user on the server enters a channel - /// This function will also be called when freshly connecting to a server as each user on that - /// server needs to be "added" to the respective channel as far as the local client is concerned. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user this event has been triggered for - /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user - /// freshly connected to the server) or the channel isn't available because of any other reason. - /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means - /// that the ID is invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, - mumble_channelid_t newChannelID); - - /// Called whenever a user leaves a channel. - /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user that left the channel - /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is - /// invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); - - /// Called when any user changes his/her talking state. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user whose talking state has been changed - /// @param talkingState The new TalkingState the user has switched to. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); - - /// Called whenever there is audio input. - /// - /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) - /// @returns Whether this callback has modified the audio input-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short* inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); - - /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). - /// The provided audio buffer is the raw buffer without any processing applied to it yet. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) - /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, - /// the content of this parameter is unspecified and should not be accessed - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); - - /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). - /// Note that this happens immediately before Mumble clips the audio buffer. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float* outputPCM, uint32_t sampleCount, uint16_t channelCount); - - /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the - /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended - /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. - /// - /// @param connection The ID of the server-connection the data is coming from - /// @param sender The ID of the user whose client's plugin has sent the data - /// @param data The sent data represented as a string - /// @param dataLength The length of data - /// @param dataID The ID of this data - /// @return Whether the given data has been processed by this plugin - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char* data, size_t dataLength, - const char* dataID); - - /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the - /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this - /// method will be called for every client already on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been added - - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the - /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this - /// method will be called for every client on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local - /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been added - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local - /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also - /// considered renaming). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been renamed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a key has been pressed or released while Mumble has keyboard focus. - /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard - /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to - /// enable that. - /// - /// @param keyCode The key code of the respective key. The character codes are defined - /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform - /// to the ASCII code-page with the only difference that case is not distinguished. Therefore - /// always the upper-case letter code will be used for letters. - /// @param wasPres Whether the respective key has been pressed (instead of released) - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// This function is used to determine whether the plugin can find an update for itself that is available for download. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @return Whether the plugin was able to find an update for itself - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); - - /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. - /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure - /// though that you don't forget about the trailing null byte. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into - /// @param bufferSize The size of the buffer - /// @param offset The offset in the URL from which this functions should start writing it to the buffer - /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called - /// again with a modified offset until the URL has been completely transferred. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char* buffer, uint16_t bufferSize, uint16_t offset); + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Gets called right after loading the plugin in order to let the plugin initialize. + /// + /// Registers the ID of this plugin. + /// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with + /// and by which this plugin can identify itself when communicating with Mumble. + /// @returns The status of the initialization. If everything went fine, return STATUS_OK + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(uint32_t id); + + /// Gets called when unloading the plugin in order to allow it to clean up after itself. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); + + /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied + /// for further usage though. + /// + /// @returns A pointer to the plugin name (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); + + /// Gets the Version of the plugin-API this plugin intends to use. + /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. + /// + /// @return The respective API Version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); + + /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used + /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use + /// of it at some point. + /// + /// @param api The MumbleAPI struct + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); + + + + ////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Tells the plugin some basic information about the Mumble client loading it. + /// This function will be the first one that is being called on this plugin - even before it is decided whether to load + /// the plugin at all. + /// + /// @param mumbleVersion The Version of the Mumble client + /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with + /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); + + /// Gets the Version of this plugin + /// + /// @returns The plugin's version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); + + /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the author(s) name(s) (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); + + /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the description (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); + + /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum + /// together. + /// + /// @returns The feature set of this plugin + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); + + /// Requests this plugin to deactivate the given (sub)set of provided features. + /// If this is not possible, the features that can't be deactivated shall be returned by this function. + /// + /// Example (check if FEATURE_POSITIONAL shall be deactivated): + /// @code + /// if (features & FEATURE_POSITIONAL) { + /// // positional shall be deactivated + /// }; + /// @endcode + /// + /// @param features The feature set that shall be deactivated + /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return + /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); + + + + ////////////////////////////////////////////////////////////////////////////////// + //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // If this plugin wants to provide positional audio, all functions of this category + // have to be implemented + + /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently + /// able to do so and allocate memory that is needed for that process. + /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i + /// belongs to a program whose name is listed at index i in the "name-array". + /// + /// @param programNames An array of pointers to the program names + /// @param programPIDs An array of the corresponding program PIDs + /// @param programCount The length of programNames and programPIDs + /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently + /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) + /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be + /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. + PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); + + /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. + /// + /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it + /// is facing). + /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One + /// unit represents one meter of distance. + /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it + /// is facing). + /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit + /// represents one meter of distance. + /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data + /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical + /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function + /// or until shutdownPositionalData is called. + /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can + /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid + /// until the next invokation of this function or until shutdownPositionalData is called. + /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will + /// be called. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, + float *cameraAxis, const char **context, const char **identity); + + /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should + /// be freed at this point. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Called when connecting to a server. + /// + /// @param connection The ID of the newly established server-connection + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); + + /// Called when disconnecting from a server. + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); + + /// Called when the client has finished synchronizing with the server + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); + + /// Called whenever any user on the server enters a channel + /// This function will also be called when freshly connecting to a server as each user on that + /// server needs to be "added" to the respective channel as far as the local client is concerned. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user this event has been triggered for + /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user + /// freshly connected to the server) or the channel isn't available because of any other reason. + /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means + /// that the ID is invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, + mumble_channelid_t newChannelID); + + /// Called whenever a user leaves a channel. + /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user that left the channel + /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is + /// invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); + + /// Called when any user changes his/her talking state. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user whose talking state has been changed + /// @param talkingState The new TalkingState the user has switched to. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); + + /// Called whenever there is audio input. + /// + /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) + /// @returns Whether this callback has modified the audio input-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); + + /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). + /// The provided audio buffer is the raw buffer without any processing applied to it yet. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) + /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, + /// the content of this parameter is unspecified and should not be accessed + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); + + /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). + /// Note that this happens immediately before Mumble clips the audio buffer. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); + + /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the + /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended + /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. + /// + /// @param connection The ID of the server-connection the data is coming from + /// @param sender The ID of the user whose client's plugin has sent the data + /// @param data The sent data represented as a string + /// @param dataLength The length of data + /// @param dataID The ID of this data + /// @return Whether the given data has been processed by this plugin + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, + const char *dataID); + + /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the + /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this + /// method will be called for every client already on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been added + + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the + /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this + /// method will be called for every client on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local + /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been added + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local + /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also + /// considered renaming). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been renamed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a key has been pressed or released while Mumble has keyboard focus. + /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard + /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to + /// enable that. + /// + /// @param keyCode The key code of the respective key. The character codes are defined + /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform + /// to the ASCII code-page with the only difference that case is not distinguished. Therefore + /// always the upper-case letter code will be used for letters. + /// @param wasPres Whether the respective key has been pressed (instead of released) + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// This function is used to determine whether the plugin can find an update for itself that is available for download. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @return Whether the plugin was able to find an update for itself + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); + + /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. + /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure + /// though that you don't forget about the trailing null byte. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into + /// @param bufferSize The size of the buffer + /// @param offset The offset in the URL from which this functions should start writing it to the buffer + /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called + /// again with a modified offset until the URL has been completely transferred. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); #ifdef __cplusplus diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h index ce684dbf9..9f0264eb4 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h @@ -13,16 +13,16 @@ #include #ifdef QT_VERSION -#include + #include #endif // define the calling convention macro based on the compiler being used #if defined(_MSC_VER) -#define PLUGIN_CALLING_CONVENTION __cdecl + #define PLUGIN_CALLING_CONVENTION __cdecl #elif defined(__MINGW32__) -#define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) + #define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) #else -#define PLUGIN_CALLING_CONVENTION + #define PLUGIN_CALLING_CONVENTION #endif @@ -35,227 +35,227 @@ /// This enum's values correspond to special feature sets a plugin may provide. /// They are meant to be or'ed together to represent the total feature set of a plugin. enum PluginFeature { - /// None of the below - FEATURE_NONE = 0, - /// The plugin provides positional data from a game - FEATURE_POSITIONAL = 1 << 0, - /// The plugin modifies the input/output audio itself - FEATURE_AUDIO = 1 << 1 + /// None of the below + FEATURE_NONE = 0, + /// The plugin provides positional data from a game + FEATURE_POSITIONAL = 1 << 0, + /// The plugin modifies the input/output audio itself + FEATURE_AUDIO = 1 << 1 }; /// This enum's values represent talking states a user can be in when using Mumble. enum TalkingState { - INVALID = -1, - PASSIVE = 0, - TALKING, - WHISPERING, - SHOUTING + INVALID=-1, + PASSIVE=0, + TALKING, + WHISPERING, + SHOUTING }; /// This enum's values represent transmission modes a user might have configured. Transmission mode /// in this context is referring to a method that determines when a user is speaking and thus when /// to transmit audio packets. enum TransmissionMode { - TM_CONTINOUS, - TM_VOICE_ACTIVATION, - TM_PUSH_TO_TALK + TM_CONTINOUS, + TM_VOICE_ACTIVATION, + TM_PUSH_TO_TALK }; /// This enum's values represent the error codes that are being used by the MumbleAPI. /// You can get a string-representation for each error code via the errorMessage function. enum ErrorCode { - EC_GENERIC_ERROR = -1, - EC_OK = 0, - EC_POINTER_NOT_FOUND, - EC_NO_ACTIVE_CONNECTION, - EC_USER_NOT_FOUND, - EC_CHANNEL_NOT_FOUND, - EC_CONNECTION_NOT_FOUND, - EC_UNKNOWN_TRANSMISSION_MODE, - EC_AUDIO_NOT_AVAILABLE, - EC_INVALID_SAMPLE, - EC_INVALID_PLUGIN_ID, - EC_INVALID_MUTE_TARGET, - EC_CONNECTION_UNSYNCHRONIZED, - EC_INVALID_API_VERSION + EC_GENERIC_ERROR = -1, + EC_OK = 0, + EC_POINTER_NOT_FOUND, + EC_NO_ACTIVE_CONNECTION, + EC_USER_NOT_FOUND, + EC_CHANNEL_NOT_FOUND, + EC_CONNECTION_NOT_FOUND, + EC_UNKNOWN_TRANSMISSION_MODE, + EC_AUDIO_NOT_AVAILABLE, + EC_INVALID_SAMPLE, + EC_INVALID_PLUGIN_ID, + EC_INVALID_MUTE_TARGET, + EC_CONNECTION_UNSYNCHRONIZED, + EC_INVALID_API_VERSION }; /// This enum's values represent error codes specific to the framework of handling positional data /// gathering (needed for Mumble's positional audio feature). enum PositionalDataErrorCode { - /// Positional data has been initialized properly - PDEC_OK = 0, - /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be - /// at another point in time. - PDEC_ERROR_TEMP, - /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). - PDEC_ERROR_PERM + /// Positional data has been initialized properly + PDEC_OK = 0, + /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be + /// at another point in time. + PDEC_ERROR_TEMP, + /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). + PDEC_ERROR_PERM }; /// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. enum KeyCode { - KC_INVALID = -1, + KC_INVALID = -1, - // Non-printable characters first - KC_NULL = 0, - KC_END = 1, - KC_LEFT = 2, - KC_RIGHT = 4, - KC_UP = 5, - KC_DOWN = 6, - KC_DELETE = 7, - KC_BACKSPACE = 8, - KC_TAB = 9, - KC_ENTER = 10, // == '\n' - KC_ESCAPE = 27, - KC_PAGE_UP = 11, - KC_PAGE_DOWN = 12, - KC_SHIFT = 13, - KC_CONTROL = 14, - KC_META = 15, - KC_ALT = 16, - KC_ALT_GR = 17, - KC_CAPSLOCK = 18, - KC_NUMLOCK = 19, - KC_SUPER = 20, // == windows key - KC_HOME = 21, // == Pos1 - KC_PRINT = 22, - KC_SCROLLLOCK = 23, + // Non-printable characters first + KC_NULL = 0, + KC_END = 1, + KC_LEFT = 2, + KC_RIGHT = 4, + KC_UP = 5, + KC_DOWN = 6, + KC_DELETE = 7, + KC_BACKSPACE = 8, + KC_TAB = 9, + KC_ENTER = 10, // == '\n' + KC_ESCAPE = 27, + KC_PAGE_UP = 11, + KC_PAGE_DOWN = 12, + KC_SHIFT = 13, + KC_CONTROL = 14, + KC_META = 15, + KC_ALT = 16, + KC_ALT_GR = 17, + KC_CAPSLOCK = 18, + KC_NUMLOCK = 19, + KC_SUPER = 20, // == windows key + KC_HOME = 21, // == Pos1 + KC_PRINT = 22, + KC_SCROLLLOCK = 23, - // Printable characters are assigned to their ASCII code - KC_SPACE = ' ', - KC_EXCLAMATION_MARK = '!', - KC_DOUBLE_QUOTE = '"', - KC_HASHTAG = '#', - KC_DOLLAR = '$', - KC_PERCENT = '%', - KC_AMPERSAND = '&', - KC_SINGLE_QUOTE = '\'', - KC_OPEN_PARENTHESIS = '(', - KC_CLOSE_PARENTHESIS = ')', - KC_ASTERISK = '*', - KC_PLUS = '+', - KC_COMMA = ',', - KC_MINUS = '-', - KC_PERIOD = '.', - KC_SLASH = '/', - KC_0 = '0', - KC_1 = '1', - KC_2 = '2', - KC_3 = '3', - KC_4 = '4', - KC_5 = '5', - KC_6 = '6', - KC_7 = '7', - KC_8 = '8', - KC_9 = '9', - KC_COLON = ':', - KC_SEMICOLON = ';', - KC_LESS_THAN = '<', - KC_EQUALS = '=', - KC_GREATER_THAN = '>', - KC_QUESTION_MARK = '?', - KC_AT_SYMBOL = '@', - KC_A = 'A', - KC_B = 'B', - KC_C = 'C', - KC_D = 'D', - KC_E = 'E', - KC_F = 'F', - KC_G = 'G', - KC_H = 'H', - KC_I = 'I', - KC_J = 'J', - KC_K = 'K', - KC_L = 'L', - KC_M = 'M', - KC_N = 'N', - KC_O = 'O', - KC_P = 'P', - KC_Q = 'Q', - KC_R = 'R', - KC_S = 'S', - KC_T = 'T', - KC_U = 'U', - KC_V = 'V', - KC_W = 'W', - KC_X = 'X', - KC_Y = 'Y', - KC_Z = 'Z', - // leave out lowercase letters (for now) - KC_OPEN_BRACKET = '[', - KC_BACKSLASH = '\\', - KC_CLOSE_BRACKET = ']', - KC_CIRCUMFLEX = '^', - KC_UNDERSCORE = '_', - KC_GRAVE_AKCENT = '`', - KC_OPEN_BRACE = '{', - KC_VERTICAL_BAR = '|', - KC_CLOSE_BRACE = '}', - KC_TILDE = '~', + // Printable characters are assigned to their ASCII code + KC_SPACE = ' ', + KC_EXCLAMATION_MARK = '!', + KC_DOUBLE_QUOTE = '"', + KC_HASHTAG = '#', + KC_DOLLAR = '$', + KC_PERCENT = '%', + KC_AMPERSAND = '&', + KC_SINGLE_QUOTE = '\'', + KC_OPEN_PARENTHESIS = '(', + KC_CLOSE_PARENTHESIS = ')', + KC_ASTERISK = '*', + KC_PLUS = '+', + KC_COMMA = ',', + KC_MINUS = '-', + KC_PERIOD = '.', + KC_SLASH = '/', + KC_0 = '0', + KC_1 = '1', + KC_2 = '2', + KC_3 = '3', + KC_4 = '4', + KC_5 = '5', + KC_6 = '6', + KC_7 = '7', + KC_8 = '8', + KC_9 = '9', + KC_COLON = ':', + KC_SEMICOLON = ';', + KC_LESS_THAN = '<', + KC_EQUALS = '=', + KC_GREATER_THAN = '>', + KC_QUESTION_MARK = '?', + KC_AT_SYMBOL = '@', + KC_A = 'A', + KC_B = 'B', + KC_C = 'C', + KC_D = 'D', + KC_E = 'E', + KC_F = 'F', + KC_G = 'G', + KC_H = 'H', + KC_I = 'I', + KC_J = 'J', + KC_K = 'K', + KC_L = 'L', + KC_M = 'M', + KC_N = 'N', + KC_O = 'O', + KC_P = 'P', + KC_Q = 'Q', + KC_R = 'R', + KC_S = 'S', + KC_T = 'T', + KC_U = 'U', + KC_V = 'V', + KC_W = 'W', + KC_X = 'X', + KC_Y = 'Y', + KC_Z = 'Z', + // leave out lowercase letters (for now) + KC_OPEN_BRACKET = '[', + KC_BACKSLASH = '\\', + KC_CLOSE_BRACKET = ']', + KC_CIRCUMFLEX = '^', + KC_UNDERSCORE = '_', + KC_GRAVE_AKCENT = '`', + KC_OPEN_BRACE = '{', + KC_VERTICAL_BAR = '|', + KC_CLOSE_BRACE = '}', + KC_TILDE = '~', - // Some characters from the extended ASCII code - KC_DEGREE_SIGN = 176, + // Some characters from the extended ASCII code + KC_DEGREE_SIGN = 176, - // F-keys - // Start at a value of 256 as extended ASCII codes range up to 256 - KC_F1 = 256, - KC_F2 = 257, - KC_F3 = 258, - KC_F4 = 259, - KC_F5 = 260, - KC_F6 = 261, - KC_F7 = 262, - KC_F8 = 263, - KC_F9 = 264, - KC_F10 = 265, - KC_F11 = 266, - KC_F12 = 267, - KC_F13 = 268, - KC_F14 = 269, - KC_F15 = 270, - KC_F16 = 271, - KC_F17 = 272, - KC_F18 = 273, - KC_F19 = 274, + // F-keys + // Start at a value of 256 as extended ASCII codes range up to 256 + KC_F1 = 256, + KC_F2 = 257, + KC_F3 = 258, + KC_F4 = 259, + KC_F5 = 260, + KC_F6 = 261, + KC_F7 = 262, + KC_F8 = 263, + KC_F9 = 264, + KC_F10 = 265, + KC_F11 = 266, + KC_F12 = 267, + KC_F13 = 268, + KC_F14 = 269, + KC_F15 = 270, + KC_F16 = 271, + KC_F17 = 272, + KC_F18 = 273, + KC_F19 = 274, }; /// A struct for representing a version of the form major.minor.patch struct Version { - int32_t major; - int32_t minor; - int32_t patch; + int32_t major; + int32_t minor; + int32_t patch; #ifdef __cplusplus - bool operator<(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; - } + bool operator<(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; + } - bool operator>(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; - } + bool operator>(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; + } - bool operator>=(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; - } + bool operator>=(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; + } - bool operator<=(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; - } + bool operator<=(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; + } - bool operator==(const Version& other) const { - return this->major == other.major && this->minor == other.minor && this->patch == other.patch; - } + bool operator==(const Version& other) const { + return this->major == other.major && this->minor == other.minor && this->patch == other.patch; + } - operator std::string() const { - return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); - } + operator std::string() const { + return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); + } #ifdef QT_VERSION - operator QString() const { - return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); - } + operator QString() const { + return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); + } #endif #endif }; @@ -265,38 +265,38 @@ struct Version { /// is encoded as a C-string and are static meaning that it is safe to use the /// returned pointer in your code. inline const char* errorMessage(int16_t errorCode) { - switch (errorCode) { - case EC_GENERIC_ERROR: - return "Generic error"; - case EC_OK: - return "Ok - this is not an error"; - case EC_POINTER_NOT_FOUND: - return "Can't find the passed pointer"; - case EC_NO_ACTIVE_CONNECTION: - return "There is currently no active connection to a server"; - case EC_USER_NOT_FOUND: - return "Can't find the requested user"; - case EC_CHANNEL_NOT_FOUND: - return "Can't find the requested channel"; - case EC_CONNECTION_NOT_FOUND: - return "Can't identify the requested connection"; - case EC_UNKNOWN_TRANSMISSION_MODE: - return "Unknown transmission mode encountered"; - case EC_AUDIO_NOT_AVAILABLE: - return "There is currently no audio output available"; - case EC_INVALID_SAMPLE: - return "Attempted to use invalid sample (can't play it)"; - case EC_INVALID_PLUGIN_ID: - return "Used an invalid plugin ID"; - case EC_INVALID_MUTE_TARGET: - return "Used an invalid mute-target"; - case EC_CONNECTION_UNSYNCHRONIZED: - return "The requested server connection has not yet finished synchrnonizing"; - case EC_INVALID_API_VERSION: - return "The used API version is invalid or not supported"; - default: - return "Unknown error code"; - } + switch (errorCode) { + case EC_GENERIC_ERROR: + return "Generic error"; + case EC_OK: + return "Ok - this is not an error"; + case EC_POINTER_NOT_FOUND: + return "Can't find the passed pointer"; + case EC_NO_ACTIVE_CONNECTION: + return "There is currently no active connection to a server"; + case EC_USER_NOT_FOUND: + return "Can't find the requested user"; + case EC_CHANNEL_NOT_FOUND: + return "Can't find the requested channel"; + case EC_CONNECTION_NOT_FOUND: + return "Can't identify the requested connection"; + case EC_UNKNOWN_TRANSMISSION_MODE: + return "Unknown transmission mode encountered"; + case EC_AUDIO_NOT_AVAILABLE: + return "There is currently no audio output available"; + case EC_INVALID_SAMPLE: + return "Attempted to use invalid sample (can't play it)"; + case EC_INVALID_PLUGIN_ID: + return "Used an invalid plugin ID"; + case EC_INVALID_MUTE_TARGET: + return "Used an invalid mute-target"; + case EC_CONNECTION_UNSYNCHRONIZED: + return "The requested server connection has not yet finished synchrnonizing"; + case EC_INVALID_API_VERSION: + return "The used API version is invalid or not supported"; + default: + return "Unknown error code"; + } } From 17ff04a297575c1b4caf289635e7c2c6661daa4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Sun, 28 Jun 2020 14:10:35 +0200 Subject: [PATCH 057/104] Adjust to new API --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index f83e681b4..b8dfeb807 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -13,10 +13,6 @@ extern MumbleAPI mumAPI; mumble_connection_t activeConnection = -1; plugin_id_t pluginID = -1; -void mumble_registerPluginID(plugin_id_t id) { - pluginID = id; -} - uint32_t mumble_getFeatures() { return FEATURE_AUDIO; } @@ -38,10 +34,8 @@ void mumble_registerAPIFunctions(struct MumbleAPI api) { } } -mumble_error_t mumble_init(uint32_t connection) { - if (connection != -1) { - activeConnection = connection; - } +mumble_error_t mumble_init(uint32_t id) { + pluginID = id; return STATUS_OK; } @@ -61,6 +55,12 @@ void mumble_onServerSynchronized(mumble_connection_t connection) { } } +void mumble_onServerConnected(mumble_connection_t connection) { + if (connection != -1) { + activeConnection = connection; + } +} + void mumble_onServerDisconnected(mumble_connection_t connection) { activeConnection = -1; From 0f2bfd2c38e5599db25ba337706fc123eac2329b Mon Sep 17 00:00:00 2001 From: jonpas Date: Mon, 13 Jul 2020 19:47:24 +0200 Subject: [PATCH 058/104] Remove MumbleTest plugin and rename generalised file --- extensions/CMakeLists.txt | 2 - extensions/src/ACRE2Core/Engine.cpp | 2 +- ...s3ChannelDetails.h => setChannelDetails.h} | 0 extensions/src/MumbleTest/CMakeLists.txt | 14 - extensions/src/MumbleTest/MumbleAPI.h | 237 ------------ extensions/src/MumbleTest/MumblePlugin.h | 354 ----------------- extensions/src/MumbleTest/PluginComponents.h | 313 --------------- .../src/MumbleTest/testPlugin/testPlugin.cpp | 364 ------------------ .../src/MumbleTest/testPlugin/testPlugin.pro | 9 - 9 files changed, 1 insertion(+), 1294 deletions(-) rename extensions/src/ACRE2Core/{setTs3ChannelDetails.h => setChannelDetails.h} (100%) delete mode 100644 extensions/src/MumbleTest/CMakeLists.txt delete mode 100644 extensions/src/MumbleTest/MumbleAPI.h delete mode 100644 extensions/src/MumbleTest/MumblePlugin.h delete mode 100644 extensions/src/MumbleTest/PluginComponents.h delete mode 100644 extensions/src/MumbleTest/testPlugin/testPlugin.cpp delete mode 100644 extensions/src/MumbleTest/testPlugin/testPlugin.pro diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index 18385e677..deb3e89d5 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -74,5 +74,3 @@ add_subdirectory(src/ACRE2Mumble) #Extras add_subdirectory(src/Wav2B64) add_subdirectory(src/ACRE2DistortionTestPlugin) -add_subdirectory(src/MumbleTest) - diff --git a/extensions/src/ACRE2Core/Engine.cpp b/extensions/src/ACRE2Core/Engine.cpp index b9d12f68a..b28f37e4b 100644 --- a/extensions/src/ACRE2Core/Engine.cpp +++ b/extensions/src/ACRE2Core/Engine.cpp @@ -26,7 +26,7 @@ #include "updateSelf.h" #include "setSelectableVoiceCurve.h" #include "setSetting.h" -#include "setTs3ChannelDetails.h" +#include "setChannelDetails.h" acre::Result CEngine::initialize(IClient *client, IServer *externalServer, std::string fromPipeName, std::string toPipeName) { diff --git a/extensions/src/ACRE2Core/setTs3ChannelDetails.h b/extensions/src/ACRE2Core/setChannelDetails.h similarity index 100% rename from extensions/src/ACRE2Core/setTs3ChannelDetails.h rename to extensions/src/ACRE2Core/setChannelDetails.h diff --git a/extensions/src/MumbleTest/CMakeLists.txt b/extensions/src/MumbleTest/CMakeLists.txt deleted file mode 100644 index da29f28cc..000000000 --- a/extensions/src/MumbleTest/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -cmake_minimum_required (VERSION 3.0) - -set(ACRE_NAME "MumbleTest") - -acre_set_build_output() -acre_set_linker_options() - -enable_language(ASM_MASM) -file(GLOB_RECURSE SOURCES *.h *.hpp *.c *.cpp *.asm testPlugin/*) - -include_directories(testPlugin) - -add_library( ${ACRE_NAME} MODULE ${SOURCES} ${GLOBAL_SOURCES}) -set_target_properties(${ACRE_NAME} PROPERTIES FOLDER Extras LINK_FLAGS -SAFESEH:NO) diff --git a/extensions/src/MumbleTest/MumbleAPI.h b/extensions/src/MumbleTest/MumbleAPI.h deleted file mode 100644 index 1ef62eaa6..000000000 --- a/extensions/src/MumbleTest/MumbleAPI.h +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2019-2020 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -/// This header file contains the definition of Mumble's API - -#ifndef MUMBLE_PLUGIN_API_H_ -#define MUMBLE_PLUGIN_API_H_ - -#include "PluginComponents.h" -#include - -// API version -const int32_t MUMBLE_PLUGIN_API_MAJOR = 1; -const int32_t MUMBLE_PLUGIN_API_MINOR = 0; -const int32_t MUMBLE_PLUGIN_API_PATCH = 0; -const version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PLUGIN_API_MINOR, MUMBLE_PLUGIN_API_PATCH }; - - -struct MumbleAPI { - // -------- Memory management -------- - - /// Frees the given pointer. - /// - /// @param callerID The ID of the plugin calling this function - /// @param pointer The pointer to free - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *freeMemory)(plugin_id_t callerID, void *pointer); - - - - // -------- Getter functions -------- - - /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] connection A pointer to the memory location the ID should be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the - /// value of the provided pointer - mumble_error_t (PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t *connection); - - /// Fills in the information about the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID); - - /// Fills in the information about the given user's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The user's ID whose name should be obtained - /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getUserName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, char **userName); - - /// Fills in the information about the given channel's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The channel's ID whose name should be obtained - /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, char **channelName); - - /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter - /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the - /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users, - size_t *userCount); - - /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent - /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the - /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t **channels, size_t *channelCount); - - /// Gets the ID of the channel the given user is currently connected to. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the ID of the channel shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t *channel); - - /// Gets an array of all users in the specified channel. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The ID of the channel whose users shall be retrieved - /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has - /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function - /// returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, mumble_userid_t **userList, size_t *userCount); - - /// Gets the current transmission mode of the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t *transmissionMode); - - - - // -------- Request functions -------- - - /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set - /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of - /// restoring the previous state afterwards. - /// - /// @param callerID The ID of the plugin calling this function - /// @param transmissionMode The requested transmission mode - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); - - /// Requests Mumble to move the given user into the given channel - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param channelID The ID of the channel to move the user to - /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a - /// password for entering - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t channelID, const char *password); - - /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen - /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again - /// once it is no longer required - /// - /// @param callerID The ID of the plugin calling this function - /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); - - - - // -------- Find functions -------- - - /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userName The respective user's name - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t (PLUGIN_CALLING_CONVENTION *findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char *userName, - mumble_userid_t *userID); - - /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelName The respective channel's name - /// @param[out] channelID A pointer to the memory the channel's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t (PLUGIN_CALLING_CONVENTION *findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, - const char *channelName, mumble_channelid_t *channelID); - - - - // -------- Miscellaneous -------- - - /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active - /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data - /// must not contain sensitive information or anything else that shouldn't be known by others. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to send the data through (the server the given users are on) - /// @param users An array of user IDs to send the data to - /// @param userCount The size of the provided user-array - /// @param data The data that shall be sent as a String - /// @param dataLength The length of the data-string - /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with - /// the data - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *users, - size_t userCount, const char *data, size_t dataLength, const char *dataID); - - /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. - /// - /// @param callerID The ID of the plugin calling this function - /// @param message The message to log - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *log)(plugin_id_t callerID, const char *message); - - /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it - /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). - /// - /// @param callerID The ID of the plugin calling this function - /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *playSample)(plugin_id_t callerID, const char *samplePath); -}; - -#endif diff --git a/extensions/src/MumbleTest/MumblePlugin.h b/extensions/src/MumbleTest/MumblePlugin.h deleted file mode 100644 index c6c82393d..000000000 --- a/extensions/src/MumbleTest/MumblePlugin.h +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2019-2020 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -/// This header file specifies the Mumble plugin interface - -#ifndef EXTERNAL_MUMBLE_PLUGIN_H_ -#define EXTERNAL_MUMBLE_PLUGIN_H_ - -#include "PluginComponents.h" -#include "MumbleAPI.h" -#include -#include -#include - -#if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems - #define PLUGIN_EXPORT __attribute__((visibility("default"))) -#elif defined(_MSC_VER) - #define PLUGIN_EXPORT __declspec(dllexport) -#elif defined(__MINGW32__) - #define PLUGIN_EXPORT __attribute__((dllexport)) -#else - #error No PLUGIN_EXPORT definition available -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Gets called right after loading the plugin in order to let the plugin initialize. - /// - /// @param connection The ID of the server-connection this event is connected to, or its default value. - /// @returns The status of the initialization. If everything went fine, return STATUS_OK - PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_connection_t connection); - - /// Gets called when unloading the plugin in order to allow it to clean up after itself. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); - - /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied - /// for further usage though. - /// - /// @returns A pointer to the plugin name (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); - - /// Gets the Version of the plugin-API this plugin intends to use. - /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. - /// - /// @return The respective API Version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); - - /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used - /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use - /// of it at some point. - /// - /// @param api The MumbleAPI struct - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); - - - - ////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Tells the plugin some basic information about the Mumble client loading it. - /// This function will be the first one that is being called on this plugin - even before it is decided whether to load - /// the plugin at all. - /// - /// @param mumbleVersion The Version of the Mumble client - /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with - /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); - - /// Gets the Version of this plugin - /// - /// @returns The plugin's version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); - - /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the author(s) name(s) (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); - - /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the description (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); - - /// Registers the ID of this plugin. This is the ID Mumble will reference this plugin with and by which this plugin - /// can identify itself when communicating with Mumble. - /// - /// @param id The ID for this plugin - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerPluginID(uint32_t id); - - /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum - /// together. - /// - /// @returns The feature set of this plugin - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); - - /// Requests this plugin to deactivate the given (sub)set of provided features. - /// If this is not possible, the features that can't be deactivated shall be returned by this function. - /// - /// Example (check if FEATURE_POSITIONAL shall be deactivated): - /// @code - /// if (features & FEATURE_POSITIONAL) { - /// // positional shall be deactivated - /// }; - /// @endcode - /// - /// @param features The feature set that shall be deactivated - /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return - /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); - - - - ////////////////////////////////////////////////////////////////////////////////// - //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - // If this plugin wants to provide positional audio, all functions of this category - // have to be implemented - - /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently - /// able to do so and allocate memory that is needed for that process. - /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i - /// belongs to a program whose name is listed at index i in the "name-array". - /// - /// @param programNames An array of pointers to the program names - /// @param programPIDs An array of the corresponding program PIDs - /// @param programCount The length of programNames and programPIDs - /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently - /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) - /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be - /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. - PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); - - /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. - /// - /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it - /// is facing). - /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One - /// unit represents one meter of distance. - /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it - /// is facing). - /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit - /// represents one meter of distance. - /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data - /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical - /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function - /// or until shutdownPositionalData is called. - /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can - /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid - /// until the next invokation of this function or until shutdownPositionalData is called. - /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will - /// be called. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, - float *cameraAxis, const char **context, const char **identity); - - /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should - /// be freed at this point. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Called when connecting to a server. - /// - /// @param connection The ID of the newly established server-connection - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); - - /// Called when disconnecting from a server. - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); - - /// Called when the client has finished synchronizing with the server - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); - - /// Called whenever any user on the server enters a channel - /// This function will also be called when freshly connecting to a server as each user on that - /// server needs to be "added" to the respective channel as far as the local client is concerned. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user this event has been triggered for - /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user - /// freshly connected to the server) or the channel isn't available because of any other reason. - /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means - /// that the ID is invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, - mumble_channelid_t newChannelID); - - /// Called whenever a user leaves a channel. - /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user that left the channel - /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is - /// invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); - - /// Called when any user changes his/her talking state. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user whose talking state has been changed - /// @param talkingState The new TalkingState the user has switched to. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); - - /// Called whenever there is audio input. - /// - /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) - /// @returns Whether this callback has modified the audio input-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); - - /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). - /// The provided audio buffer is the raw buffer without any processing applied to it yet. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) - /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, - /// the content of this parameter is unspecified and should not be accessed - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); - - /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). - /// Note that this happens immediately before Mumble clips the audio buffer. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); - - /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the - /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended - /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. - /// - /// @param connection The ID of the server-connection the data is coming from - /// @param sender The ID of the user whose client's plugin has sent the data - /// @param data The sent data represented as a string - /// @param dataLength The length of data - /// @param dataID The ID of this data - /// @return Whether the given data has been processed by this plugin - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, - const char *dataID); - - /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the - /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this - /// method will be called for every client already on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been added - - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the - /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this - /// method will be called for every client on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local - /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been added - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local - /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also - /// considered renaming). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been renamed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a key has been pressed or released while Mumble has keyboard focus. - /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard - /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to - /// enable that. - /// - /// @param keyCode The key code of the respective key. The character codes are defined - /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform - /// to the ASCII code-page with the only difference that case is not distinguished. Therefore - /// always the upper-case letter code will be used for letters. - /// @param wasPres Whether the respective key has been pressed (instead of released) - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// This function is used to determine whether the plugin can find an update for itself that is available for download. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @return Whether the plugin was able to find an update for itself - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); - - /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. - /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure - /// though that you don't forget about the trailing null byte. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into - /// @param bufferSize The size of the buffer - /// @param offset The offset in the URL from which this functions should start writing it to the buffer - /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called - /// again with a modified offset until the URL has been completely transferred. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/extensions/src/MumbleTest/PluginComponents.h b/extensions/src/MumbleTest/PluginComponents.h deleted file mode 100644 index b203eb1b7..000000000 --- a/extensions/src/MumbleTest/PluginComponents.h +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2019-2020 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -/// This header file contains definitions of types and other components used in Mumble's plugin system - -#ifndef MUMBLE_PLUGINCOMPONENT_H_ -#define MUMBLE_PLUGINCOMPONENT_H_ - -#include -#include -#include - -#ifdef QT_VERSION - #include -#endif - -// define the calling convention macro based on the compiler being used -#if defined(_MSC_VER) - #define PLUGIN_CALLING_CONVENTION __cdecl -#elif defined(__MINGW32__) - #define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) -#else - #define PLUGIN_CALLING_CONVENTION -#endif - - -/// A macro holding the exit status of a successful operation -#define STATUS_OK EC_OK -/// A macro holding the version object that is considered to correspond to an unknown version -#define VERSION_UNKNOWN Version({0,0,0}) - - -/// This enum's values correspond to special feature sets a plugin may provide. -/// They are meant to be or'ed together to represent the total feature set of a plugin. -enum PluginFeature { - /// None of the below - FEATURE_NONE = 0, - /// The plugin provides positional data from a game - FEATURE_POSITIONAL = 1 << 0, - /// The plugin modifies the input/output audio itself - FEATURE_AUDIO = 1 << 1 -}; - -/// This enum's values represent talking states a user can be in when using Mumble. -enum TalkingState { - INVALID=-1, - PASSIVE=0, - TALKING, - WHISPERING, - SHOUTING -}; - -/// This enum's values represent transmission modes a user might have configured. Transmission mode -/// in this context is referring to a method that determines when a user is speaking and thus when -/// to transmit audio packets. -enum TransmissionMode { - TM_CONTINOUS, - TM_VOICE_ACTIVATION, - TM_PUSH_TO_TALK -}; - -/// This enum's values represent the error codes that are being used by the MumbleAPI. -/// You can get a string-representation for each error code via the errorMessage function. -enum ErrorCode { - EC_GENERIC_ERROR = -1, - EC_OK = 0, - EC_POINTER_NOT_FOUND, - EC_NO_ACTIVE_CONNECTION, - EC_USER_NOT_FOUND, - EC_CHANNEL_NOT_FOUND, - EC_CONNECTION_NOT_FOUND, - EC_UNKNOWN_TRANSMISSION_MODE, - EC_AUDIO_NOT_AVAILABLE, - EC_INVALID_SAMPLE, - EC_INVALID_PLUGIN_ID -}; - -/// This enum's values represent error codes specific to the framework of handling positional data -/// gathering (needed for Mumble's positional audio feature). -enum PositionalDataErrorCode { - /// Positional data has been initialized properly - PDEC_OK = 0, - /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be - /// at another point in time. - PDEC_ERROR_TEMP, - /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). - PDEC_ERROR_PERM -}; - -/// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. -enum KeyCode { - KC_INVALID = -1, - - // Non-printable characters first - KC_NULL = 0, - KC_END = 1, - KC_LEFT = 2, - KC_RIGHT = 4, - KC_UP = 5, - KC_DOWN = 6, - KC_DELETE = 7, - KC_BACKSPACE = 8, - KC_TAB = 9, - KC_ENTER = 10, // == '\n' - KC_ESCAPE = 27, - KC_PAGE_UP = 11, - KC_PAGE_DOWN = 12, - KC_SHIFT = 13, - KC_CONTROL = 14, - KC_META = 15, - KC_ALT = 16, - KC_ALT_GR = 17, - KC_CAPSLOCK = 18, - KC_NUMLOCK = 19, - KC_SUPER = 20, // == windows key - KC_HOME = 21, // == Pos1 - KC_PRINT = 22, - KC_SCROLLLOCK = 23, - - // Printable characters are assigned to their ASCII code - KC_SPACE = ' ', - KC_EXCLAMATION_MARK = '!', - KC_DOUBLE_QUOTE = '"', - KC_HASHTAG = '#', - KC_DOLLAR = '$', - KC_PERCENT = '%', - KC_AMPERSAND = '&', - KC_SINGLE_QUOTE = '\'', - KC_OPEN_PARENTHESIS = '(', - KC_CLOSE_PARENTHESIS = ')', - KC_ASTERISK = '*', - KC_PLUS = '+', - KC_COMMA = ',', - KC_MINUS = '-', - KC_PERIOD = '.', - KC_SLASH = '/', - KC_0 = '0', - KC_1 = '1', - KC_2 = '2', - KC_3 = '3', - KC_4 = '4', - KC_5 = '5', - KC_6 = '6', - KC_7 = '7', - KC_8 = '8', - KC_9 = '9', - KC_COLON = ':', - KC_SEMICOLON = ';', - KC_LESS_THAN = '<', - KC_EQUALS = '=', - KC_GREATER_THAN = '>', - KC_QUESTION_MARK = '?', - KC_AT_SYMBOL = '@', - KC_A = 'A', - KC_B = 'B', - KC_C = 'C', - KC_D = 'D', - KC_E = 'E', - KC_F = 'F', - KC_G = 'G', - KC_H = 'H', - KC_I = 'I', - KC_J = 'J', - KC_K = 'K', - KC_L = 'L', - KC_M = 'M', - KC_N = 'N', - KC_O = 'O', - KC_P = 'P', - KC_Q = 'Q', - KC_R = 'R', - KC_S = 'S', - KC_T = 'T', - KC_U = 'U', - KC_V = 'V', - KC_W = 'W', - KC_X = 'X', - KC_Y = 'Y', - KC_Z = 'Z', - // leave out lowercase letters (for now) - KC_OPEN_BRACKET = '[', - KC_BACKSLASH = '\\', - KC_CLOSE_BRACKET = ']', - KC_CIRCUMFLEX = '^', - KC_UNDERSCORE = '_', - KC_GRAVE_AKCENT = '`', - KC_OPEN_BRACE = '{', - KC_VERTICAL_BAR = '|', - KC_CLOSE_BRACE = '}', - KC_TILDE = '~', - - // Some characters from the extended ASCII code - KC_DEGREE_SIGN = 176, - - - - // F-keys - // Start at a value of 256 as extended ASCII codes range up to 256 - KC_F1 = 256, - KC_F2 = 257, - KC_F3 = 258, - KC_F4 = 259, - KC_F5 = 260, - KC_F6 = 261, - KC_F7 = 262, - KC_F8 = 263, - KC_F9 = 264, - KC_F10 = 265, - KC_F11 = 266, - KC_F12 = 267, - KC_F13 = 268, - KC_F14 = 269, - KC_F15 = 270, - KC_F16 = 271, - KC_F17 = 272, - KC_F18 = 273, - KC_F19 = 274, -}; - -/// A struct for representing a version of the form major.minor.patch -struct Version { - int32_t major; - int32_t minor; - int32_t patch; -#ifdef __cplusplus - bool operator<(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; - } - - bool operator>(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; - } - - bool operator>=(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; - } - - bool operator<=(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; - } - - bool operator==(const Version& other) const { - return this->major == other.major && this->minor == other.minor && this->patch == other.patch; - } - - operator std::string() const { - return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); - } - -#ifdef QT_VERSION - operator QString() const { - return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); - } -#endif -#endif -}; - -/// @param errorCode The error code to get a message for -/// @returns The error message coresponding to the given error code. The message -/// is encoded as a C-string and are static meaning that it is safe to use the -/// returned pointer in your code. -inline const char* errorMessage(int16_t errorCode) { - switch (errorCode) { - case EC_GENERIC_ERROR: - return "Generic error"; - case EC_OK: - return "Ok - this is not an error"; - case EC_POINTER_NOT_FOUND: - return "Can't find the passed pointer"; - case EC_NO_ACTIVE_CONNECTION: - return "There is currently no active connection to a server"; - case EC_USER_NOT_FOUND: - return "Can't find the requested user"; - case EC_CHANNEL_NOT_FOUND: - return "Can't find the requested channel"; - case EC_CONNECTION_NOT_FOUND: - return "Can't identify the requested connection"; - case EC_UNKNOWN_TRANSMISSION_MODE: - return "Unknown transmission mode encountered"; - case EC_AUDIO_NOT_AVAILABLE: - return "There is currently no audio output available"; - case EC_INVALID_SAMPLE: - return "Attempted to use invalid sample (can't play it)"; - case EC_INVALID_PLUGIN_ID: - return "Used an invalid plugin ID"; - default: - return "Unknown error code"; - } -} - - -/// Typedef for the type of a talking state -typedef enum TalkingState talking_state_t; -/// Typedef for the type of a transmission mode -typedef enum TransmissionMode transmission_mode_t; -/// Typedef for the type of a version -typedef struct Version version_t; -/// Typedef for the type of a connection -typedef int32_t mumble_connection_t; -/// Typedef for the type of a user -typedef uint32_t mumble_userid_t; -/// Typedef for the type of a channel -typedef int32_t mumble_channelid_t; -/// Typedef for the type of an error (code) -typedef enum ErrorCode mumble_error_t; -/// Typedef for the type of a plugin ID -typedef uint32_t plugin_id_t; -/// Typedef for the type of a key-code -typedef KeyCode keycode_t; - -#endif // MUMBLE_PLUGINCOMPONENT_H_ diff --git a/extensions/src/MumbleTest/testPlugin/testPlugin.cpp b/extensions/src/MumbleTest/testPlugin/testPlugin.cpp deleted file mode 100644 index 6cb2ad535..000000000 --- a/extensions/src/MumbleTest/testPlugin/testPlugin.cpp +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright 2019-2020 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -// Include the definitions of the plugin functions -// Not that this will also include ../PluginComponents.h -#include "../MumblePlugin.h" -#include "../MumbleAPI.h" - -#include -#include - -// These are just some utility functions facilitating writing logs and the like -// The actual implementation of the plugin is further down -std::ostream& pLog() { - std::cout << "TestPlugin: "; - return std::cout; -} - -template -void pluginLog(T log) { - pLog() << log << std::endl; -} - -std::ostream& operator<<(std::ostream& stream, const version_t version) { - stream << "v" << version.major << "." << version.minor << "." << version.patch; - return stream; -} - - -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// -//////////////////// PLUGIN IMPLEMENTATION /////////////////// -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// - -MumbleAPI mumAPI; -mumble_connection_t activeConnection; -plugin_id_t ownID; - -////////////////////////////////////////////////////////////// -//////////////////// OBLIGATORY FUNCTIONS //////////////////// -////////////////////////////////////////////////////////////// -// All of the following function must be implemented in order for Mumble to load the plugin - -mumble_error_t mumble_init(mumble_connection_t connection) { - pluginLog("Initialized plugin"); - - // Print the connection ID at initialization. If not connected to a server it should be -1. - pLog() << "Connection ID at initialization: " << connection << std::endl; - - // STATUS_OK is a macro set to the appropriate status flag (ErrorCode) - // If you need to return any other status have a look at the ErrorCode enum - // inside PluginComponents.h and use one of its values - return STATUS_OK; -} - -void mumble_shutdown() { - pluginLog("Shutdown plugin"); - - mumAPI.log(ownID, "Shutdown"); -} - -const char* mumble_getName() { - // The pointer returned by this functions has to remain valid forever and it must be able to return - // one even if the plugin hasn't loaded (yet). Thus it may not require any variables that are only set - // once the plugin is initialized - // For most cases returning a hard-coded String-literal should be what you aim for - return "TestPlugin"; -} - -version_t mumble_getAPIVersion() { - // MUMBLE_PLUGIN_API_VERSION will always contain the API version of the used header file (the one used to build - // this plugin against). Thus you should always return that here in order to no have to worry about it. - return MUMBLE_PLUGIN_API_VERSION; -} - -void mumble_registerAPIFunctions(MumbleAPI api) { - // In this function the plugin is presented with a struct of function pointers that can be used - // to interact with Mumble. Thus you should store it somewhere safe for later usage. - mumAPI = api; - - pluginLog("Registered Mumble's API functions"); - - mumAPI.log(ownID, "Received API functions"); -} - - -////////////////////////////////////////////////////////////// -///////////////////// OPTIONAL FUNCTIONS ///////////////////// -////////////////////////////////////////////////////////////// -// The implementation of below functions is optional. If you don't need them, don't include them in your -// plugin - -void mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion) { - // this function will always be the first one to be called. Even before init() - // In here you can get info about the Mumble version this plugin is about to run in. - pLog() << "Mumble version: " << mumbleVersion << "; Mumble API-Version: " << mumbleAPIVersion << "; Minimal expected API-Version: " - << minimalExpectedAPIVersion << std::endl; -} - -version_t mumble_getVersion() { - // Mumble uses semantic versioning (see https://semver.org/) - // { major, minor, patch } - return { 1, 0, 0 }; -} - -const char* mumble_getAuthor() { - // For the returned pointer the same rules as for getName() apply - // In short: in the vast majority of cases you'll want to return a hard-coded String-literal - return "MumbleDevelopers"; -} - -const char* mumble_getDescription() { - // For the returned pointer the same rules as for getName() apply - // In short: in the vast majority of cases you'll want to return a hard-coded String-literal - return "This plugin is merely a reference implementation without any real functionality. It shouldn't be included in the release build of Mumble"; -} - -void mumble_registerPluginID(plugin_id_t id) { - // This ID serves as an identifier for this plugin as far as Mumble is concerned - // It might be a good idea to store it somewhere for later use - pLog() << "Registered ID: " << id << std::endl; - - ownID = id; -} - -uint32_t mumble_getFeatures() { - // Tells Mumble whether this plugin delivers some known common functionality. See the PluginFeature enum in - // PluginComponents.h for what is available. - // If you want your plugin to deliver positional data, you'll want to return FEATURE_POSITIONAL - return FEATURE_NONE; -} - -uint32_t mumble_deactivateFeatures(uint32_t features) { - pLog() << "Asked to deactivate feature set " << features << std::endl; - - // All features that can't be deactivated should be returned - return features; -} - -uint8_t mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount) { - std::ostream& stream = pLog() << "Got " << programCount << " programs to init positional data."; - - if (programCount > 0) { - stream << " The first name is " << programNames[0] << " and has PID " << programPIDs[0]; - } - - stream << std::endl; - - // As this plugin doesn't provide PD, we return PDEC_ERROR_PERM to indicate that even in the future we won't do so - // If your plugin is indeed delivering positional data but is only temporarily unaible to do so, return PDEC_ERROR_TEMP - // and if you deliver PD and succeeded initializing return PDEC_OK. - return PDEC_ERROR_PERM; -} - -#define SET_TO_ZERO(name) name[0] = 0.0f; name[1] = 0.0f; name[2] = 0.0f -bool mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, - float *cameraAxis, const char **context, const char **identity) { - pluginLog("Has been asked to deliver positional data"); - - // If unable to provide positional data, this function should return false and reset all given values to 0/empty Strings - SET_TO_ZERO(avatarPos); - SET_TO_ZERO(avatarDir); - SET_TO_ZERO(avatarAxis); - SET_TO_ZERO(cameraPos); - SET_TO_ZERO(cameraDir); - SET_TO_ZERO(cameraAxis); - *context = ""; - *identity = ""; - - // This function returns whether it can continue to deliver positional data - return false; -} - -void mumble_shutdownPositionalData() { - pluginLog("Shutting down positional data"); -} - -void mumble_onServerConnected(mumble_connection_t connection) { - activeConnection = connection; - - pLog() << "Established server-connection with ID " << connection << std::endl; -} - -void mumble_onServerDisconnected(mumble_connection_t connection) { - activeConnection = -1; - - pLog() << "Disconnected from server-connection with ID " << connection << std::endl; -} - -void mumble_onServerSynchronized(mumble_connection_t connection) { - // The client has finished synchronizing with the server. Thus we can now obtain a list of all users on this server - pLog() << "Server has finished synchronizing (ServerConnection: " << connection << ")" << std::endl ; - - size_t userCount; - mumble_userid_t *userIDs; - - if (mumAPI.getAllUsers(ownID, activeConnection, &userIDs, &userCount) != STATUS_OK) { - pluginLog("[ERROR]: Can't obtain user list"); - return; - } - - pLog() << "There are " << userCount << " users on this server. Their names are:" << std::endl; - - for(size_t i=0; i= 0) { - stream << " He came from channel with ID " << previousChannelID << "."; - } - - stream << " (ServerConnection: " << connection << ")" << std::endl; -} - -void mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID) { - pLog() << "User with ID " << userID << " has left channel with ID " << channelID << ". (ServerConnection: " << connection << ")" << std::endl; -} - -void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState) { - std::ostream& stream = pLog() << "User with ID " << userID << " changed his talking state to "; - - // The possible values are contained in the TalkingState enum inside PluginComponent.h - switch(talkingState) { - case INVALID: - stream << "Invalid"; - break; - case PASSIVE: - stream << "Passive"; - break; - case TALKING: - stream << "Talking"; - break; - case WHISPERING: - stream << "Whispering"; - break; - case SHOUTING: - stream << "Shouting"; - break; - default: - stream << "Unknown (" << talkingState << ")"; - } - - stream << ". (ServerConnection: " << connection << ")" << std::endl; -} - -bool mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech) { - pLog() << "Audio input with " << channelCount << " channels and " << sampleCount << " samples per channel encountered. IsSpeech: " - << isSpeech << std::endl; - - // mark inputPCM as unused - (void) inputPCM; - - // This function returns whether it has modified the audio stream - return false; -} - -bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID) { - std::ostream& stream = pLog() << "Audio output source with " << channelCount << " channels and " << sampleCount << " samples per channel fetched."; - - if (isSpeech) { - stream << " The output is speech from user with ID " << userID << "."; - } - - stream << std::endl; - - // Mark ouputPCM as unused - (void) outputPCM; - - // This function returns whether it has modified the audio stream - return false; -} - -bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount) { - pLog() << "The resulting audio output has " << channelCount << " channels with " << sampleCount << " samples per channel" << std::endl; - - // mark outputPCM as unused - (void) outputPCM; - - // This function returns whether it has modified the audio stream - return false; -} - -bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, const char *dataID) { - pLog() << "Received data with ID \"" << dataID << "\" from user with ID " << sender << ". Its length is " << dataLength - << ". (ServerConnection:" << connection << ")" << std::endl; - - if (std::strcmp(dataID, "testMsg") == 0) { - pLog() << "The received data: " << data << std::endl; - } - - // This function returns whether it has processed the data (preventing further plugins from seeing it) - return false; -} - -void mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID) { - pLog() << "Added user with ID " << userID << " (ServerConnection: " << connection << ")" << std::endl; -} - -void mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID) { - pLog() << "Removed user with ID " << userID << " (ServerConnection: " << connection << ")" << std::endl; -} - -void mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID) { - pLog() << "Added channel with ID " << channelID << " (ServerConnection: " << connection << ")" << std::endl; -} - -void mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID) { - pLog() << "Removed channel with ID " << channelID << " (ServerConnection: " << connection << ")" << std::endl; -} - -void mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID) { - pLog() << "Renamed channel with ID " << channelID << " (ServerConnection: " << connection << ")" << std::endl; -} - -void mumble_onKeyEvent(uint32_t keyCode, bool wasPress) { - pLog() << "Encountered key " << (wasPress ? "press" : "release") << " of key with code " << keyCode << std::endl; -} - -bool mumble_hasUpdate() { - // This plugin never has an update - return false; -} - -bool mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset) { - static std::string url = "https://i.dont.exist/testplugin.zip"; - - size_t writtenChars = url.copy(buffer, bufferSize, offset); - - if (writtenChars < bufferSize) { - // URL has fit into the buffer -> append null byte and be done with it - buffer[writtenChars] = '\0'; - return true; - } else { - std::cout << "Overflow" << std::endl; - return false; - } -} diff --git a/extensions/src/MumbleTest/testPlugin/testPlugin.pro b/extensions/src/MumbleTest/testPlugin/testPlugin.pro deleted file mode 100644 index 55c306d3f..000000000 --- a/extensions/src/MumbleTest/testPlugin/testPlugin.pro +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2019-2020 The Mumble Developers. All rights reserved. -# Use of this source code is governed by a BSD-style license -# that can be found in the LICENSE file at the root of the -# Mumble source tree or at . - -include(../plugins.pri) - -TARGET = testPlugin -SOURCES = testPlugin.cpp From 0ec16c78cad311de5b9c0ad141aa6323e1476b38 Mon Sep 17 00:00:00 2001 From: jonpas Date: Mon, 13 Jul 2020 19:52:13 +0200 Subject: [PATCH 059/104] Fix function example --- addons/sys_io/fnc_voipChannelMove.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sys_io/fnc_voipChannelMove.sqf b/addons/sys_io/fnc_voipChannelMove.sqf index bfac67425..d4a25215c 100644 --- a/addons/sys_io/fnc_voipChannelMove.sqf +++ b/addons/sys_io/fnc_voipChannelMove.sqf @@ -10,7 +10,7 @@ * None * * Example: - * [] call acre_sys_io_fnc_voipChannelCheck + * [] call acre_sys_io_fnc_voipChannelMove * * Public: No */ From f9cc7d70165c8d0e8323cb807b07566c80c63c96 Mon Sep 17 00:00:00 2001 From: jonpas Date: Tue, 14 Jul 2020 22:29:15 +0200 Subject: [PATCH 060/104] Revert "Adjust to new API" This reverts commit 17ff04a297575c1b4caf289635e7c2c6661daa4f. --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index b8dfeb807..f83e681b4 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -13,6 +13,10 @@ extern MumbleAPI mumAPI; mumble_connection_t activeConnection = -1; plugin_id_t pluginID = -1; +void mumble_registerPluginID(plugin_id_t id) { + pluginID = id; +} + uint32_t mumble_getFeatures() { return FEATURE_AUDIO; } @@ -34,8 +38,10 @@ void mumble_registerAPIFunctions(struct MumbleAPI api) { } } -mumble_error_t mumble_init(uint32_t id) { - pluginID = id; +mumble_error_t mumble_init(uint32_t connection) { + if (connection != -1) { + activeConnection = connection; + } return STATUS_OK; } @@ -55,12 +61,6 @@ void mumble_onServerSynchronized(mumble_connection_t connection) { } } -void mumble_onServerConnected(mumble_connection_t connection) { - if (connection != -1) { - activeConnection = connection; - } -} - void mumble_onServerDisconnected(mumble_connection_t connection) { activeConnection = -1; From 301659dc4d26c21ee3ff4a94d4dea1ee19e69865 Mon Sep 17 00:00:00 2001 From: jonpas Date: Tue, 14 Jul 2020 22:29:16 +0200 Subject: [PATCH 061/104] Revert "Do not format mumble plugins" This reverts commit 40a0881f1e56ee3a3d85c5eecfd6c1b7acd21528. --- .../ACRE2Mumble/mumble_includes/MumbleAPI.h | 512 +++++++------- .../mumble_includes/MumblePlugin.h | 632 +++++++++--------- .../mumble_includes/PluginComponents.h | 430 ++++++------ 3 files changed, 787 insertions(+), 787 deletions(-) diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h index 6667e712d..537a82c21 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h @@ -19,262 +19,262 @@ const version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PL struct MumbleAPI { - ///////////////////////////////////////////////////////// - ////////////////////// GENERAL NOTE ///////////////////// - ///////////////////////////////////////////////////////// - // - // All functions that take in a connection as a paremeter may only be called **after** the connection - // has finished synchronizing. The only exception from this is isConnectionSynchronized. - - - // -------- Memory management -------- - - /// Frees the given pointer. - /// - /// @param callerID The ID of the plugin calling this function - /// @param pointer The pointer to free - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *freeMemory)(plugin_id_t callerID, void *pointer); - - - - // -------- Getter functions -------- - - /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] connection A pointer to the memory location the ID should be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the - /// value of the provided pointer - mumble_error_t (PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t *connection); - - /// Checks whether the given connection has finished initializing yet. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished synchronization yet - /// after this function has executed successfully. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *isConnectionSynchronized)(plugin_id_t callerID, mumble_connection_t connection, bool *synchronized); - - /// Fills in the information about the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID); - - /// Fills in the information about the given user's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The user's ID whose name should be obtained - /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getUserName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, char **userName); - - /// Fills in the information about the given channel's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The channel's ID whose name should be obtained - /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, char **channelName); - - /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter - /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the - /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users, - size_t *userCount); - - /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent - /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the - /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t **channels, size_t *channelCount); - - /// Gets the ID of the channel the given user is currently connected to. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the ID of the channel shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t *channel); - - /// Gets an array of all users in the specified channel. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The ID of the channel whose users shall be retrieved - /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has - /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function - /// returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, mumble_userid_t **userList, size_t *userCount); - - /// Gets the current transmission mode of the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t *transmissionMode); - - /// Checks whether the given user is currently locally muted. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the local mute state of that user shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *isUserLocallyMuted)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, bool *muted); - - - // -------- Request functions -------- - - /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set - /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of - /// restoring the previous state afterwards. - /// - /// @param callerID The ID of the plugin calling this function - /// @param transmissionMode The requested transmission mode - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); - - /// Requests Mumble to move the given user into the given channel - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param channelID The ID of the channel to move the user to - /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a - /// password for entering - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t channelID, const char *password); - - /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen - /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again - /// once it is no longer required - /// - /// @param callerID The ID of the plugin calling this function - /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); - - /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute state - /// opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client has muted its - /// microphone and thus isn't transmitting any audio). - /// Furthermore it must be noted that muting the local user with this function does not work (it doesn't make sense). If - /// you try to do so, this function will fail. In order to make this work, this function will also fail if the server - /// has not finished synchronizing with the client yet. - /// - /// @param callerID The ID of the plugin calling this function. - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param muted Whether to locally mute the given client (opposed to unmuting it) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalMute)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, bool muted); - - - - // -------- Find functions -------- - - /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userName The respective user's name - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t (PLUGIN_CALLING_CONVENTION *findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char *userName, - mumble_userid_t *userID); - - /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelName The respective channel's name - /// @param[out] channelID A pointer to the memory the channel's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t (PLUGIN_CALLING_CONVENTION *findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, - const char *channelName, mumble_channelid_t *channelID); - - - - // -------- Miscellaneous -------- - - /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active - /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data - /// must not contain sensitive information or anything else that shouldn't be known by others. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to send the data through (the server the given users are on) - /// @param users An array of user IDs to send the data to - /// @param userCount The size of the provided user-array - /// @param data The data that shall be sent as a String - /// @param dataLength The length of the data-string - /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with - /// the data - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *users, - size_t userCount, const char *data, size_t dataLength, const char *dataID); - - /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. - /// - /// @param callerID The ID of the plugin calling this function - /// @param message The message to log - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *log)(plugin_id_t callerID, const char *message); - - /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it - /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). - /// - /// @param callerID The ID of the plugin calling this function - /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *playSample)(plugin_id_t callerID, const char *samplePath); + ///////////////////////////////////////////////////////// + ////////////////////// GENERAL NOTE ///////////////////// + ///////////////////////////////////////////////////////// + // + // All functions that take in a connection as a paremeter may only be called **after** the connection + // has finished synchronizing. The only exception from this is isConnectionSynchronized. + + + // -------- Memory management -------- + + /// Frees the given pointer. + /// + /// @param callerID The ID of the plugin calling this function + /// @param pointer The pointer to free + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* freeMemory)(plugin_id_t callerID, void* pointer); + + + + // -------- Getter functions -------- + + /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] connection A pointer to the memory location the ID should be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the + /// value of the provided pointer + mumble_error_t(PLUGIN_CALLING_CONVENTION* getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t* connection); + + /// Checks whether the given connection has finished initializing yet. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished synchronization yet + /// after this function has executed successfully. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* isConnectionSynchronized)(plugin_id_t callerID, mumble_connection_t connection, bool* synchronized); + + /// Fills in the information about the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t* userID); + + /// Fills in the information about the given user's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The user's ID whose name should be obtained + /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getUserName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, char** userName); + + /// Fills in the information about the given channel's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The channel's ID whose name should be obtained + /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, char** channelName); + + /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter + /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the + /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t** users, + size_t* userCount); + + /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent + /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the + /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t** channels, size_t* channelCount); + + /// Gets the ID of the channel the given user is currently connected to. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the ID of the channel shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t* channel); + + /// Gets an array of all users in the specified channel. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The ID of the channel whose users shall be retrieved + /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has + /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function + /// returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, mumble_userid_t** userList, size_t* userCount); + + /// Gets the current transmission mode of the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t* transmissionMode); + + /// Checks whether the given user is currently locally muted. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the local mute state of that user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* isUserLocallyMuted)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, bool* muted); + + + // -------- Request functions -------- + + /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set + /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of + /// restoring the previous state afterwards. + /// + /// @param callerID The ID of the plugin calling this function + /// @param transmissionMode The requested transmission mode + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); + + /// Requests Mumble to move the given user into the given channel + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param channelID The ID of the channel to move the user to + /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a + /// password for entering + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t channelID, const char* password); + + /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen + /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again + /// once it is no longer required + /// + /// @param callerID The ID of the plugin calling this function + /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); + + /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute state + /// opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client has muted its + /// microphone and thus isn't transmitting any audio). + /// Furthermore it must be noted that muting the local user with this function does not work (it doesn't make sense). If + /// you try to do so, this function will fail. In order to make this work, this function will also fail if the server + /// has not finished synchronizing with the client yet. + /// + /// @param callerID The ID of the plugin calling this function. + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param muted Whether to locally mute the given client (opposed to unmuting it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalMute)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, bool muted); + + + + // -------- Find functions -------- + + /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userName The respective user's name + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char* userName, + mumble_userid_t* userID); + + /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelName The respective channel's name + /// @param[out] channelID A pointer to the memory the channel's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, + const char* channelName, mumble_channelid_t* channelID); + + + + // -------- Miscellaneous -------- + + /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active + /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data + /// must not contain sensitive information or anything else that shouldn't be known by others. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to send the data through (the server the given users are on) + /// @param users An array of user IDs to send the data to + /// @param userCount The size of the provided user-array + /// @param data The data that shall be sent as a String + /// @param dataLength The length of the data-string + /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with + /// the data + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t* users, + size_t userCount, const char* data, size_t dataLength, const char* dataID); + + /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. + /// + /// @param callerID The ID of the plugin calling this function + /// @param message The message to log + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* log)(plugin_id_t callerID, const char* message); + + /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it + /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). + /// + /// @param callerID The ID of the plugin calling this function + /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* playSample)(plugin_id_t callerID, const char* samplePath); }; #endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h index dcb6b2710..38ddcdc28 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h @@ -15,331 +15,331 @@ #include #if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems - #define PLUGIN_EXPORT __attribute__((visibility("default"))) +#define PLUGIN_EXPORT __attribute__((visibility("default"))) #elif defined(_MSC_VER) - #define PLUGIN_EXPORT __declspec(dllexport) +#define PLUGIN_EXPORT __declspec(dllexport) #elif defined(__MINGW32__) - #define PLUGIN_EXPORT __attribute__((dllexport)) +#define PLUGIN_EXPORT __attribute__((dllexport)) #else - #error No PLUGIN_EXPORT definition available +#error No PLUGIN_EXPORT definition available #endif #ifdef __cplusplus extern "C" { #endif - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Gets called right after loading the plugin in order to let the plugin initialize. - /// - /// Registers the ID of this plugin. - /// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with - /// and by which this plugin can identify itself when communicating with Mumble. - /// @returns The status of the initialization. If everything went fine, return STATUS_OK - PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(uint32_t id); - - /// Gets called when unloading the plugin in order to allow it to clean up after itself. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); - - /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied - /// for further usage though. - /// - /// @returns A pointer to the plugin name (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); - - /// Gets the Version of the plugin-API this plugin intends to use. - /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. - /// - /// @return The respective API Version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); - - /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used - /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use - /// of it at some point. - /// - /// @param api The MumbleAPI struct - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); - - - - ////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Tells the plugin some basic information about the Mumble client loading it. - /// This function will be the first one that is being called on this plugin - even before it is decided whether to load - /// the plugin at all. - /// - /// @param mumbleVersion The Version of the Mumble client - /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with - /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); - - /// Gets the Version of this plugin - /// - /// @returns The plugin's version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); - - /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the author(s) name(s) (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); - - /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the description (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); - - /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum - /// together. - /// - /// @returns The feature set of this plugin - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); - - /// Requests this plugin to deactivate the given (sub)set of provided features. - /// If this is not possible, the features that can't be deactivated shall be returned by this function. - /// - /// Example (check if FEATURE_POSITIONAL shall be deactivated): - /// @code - /// if (features & FEATURE_POSITIONAL) { - /// // positional shall be deactivated - /// }; - /// @endcode - /// - /// @param features The feature set that shall be deactivated - /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return - /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); - - - - ////////////////////////////////////////////////////////////////////////////////// - //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - // If this plugin wants to provide positional audio, all functions of this category - // have to be implemented - - /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently - /// able to do so and allocate memory that is needed for that process. - /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i - /// belongs to a program whose name is listed at index i in the "name-array". - /// - /// @param programNames An array of pointers to the program names - /// @param programPIDs An array of the corresponding program PIDs - /// @param programCount The length of programNames and programPIDs - /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently - /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) - /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be - /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. - PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); - - /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. - /// - /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it - /// is facing). - /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One - /// unit represents one meter of distance. - /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it - /// is facing). - /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit - /// represents one meter of distance. - /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data - /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical - /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function - /// or until shutdownPositionalData is called. - /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can - /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid - /// until the next invokation of this function or until shutdownPositionalData is called. - /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will - /// be called. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, - float *cameraAxis, const char **context, const char **identity); - - /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should - /// be freed at this point. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Called when connecting to a server. - /// - /// @param connection The ID of the newly established server-connection - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); - - /// Called when disconnecting from a server. - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); - - /// Called when the client has finished synchronizing with the server - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); - - /// Called whenever any user on the server enters a channel - /// This function will also be called when freshly connecting to a server as each user on that - /// server needs to be "added" to the respective channel as far as the local client is concerned. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user this event has been triggered for - /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user - /// freshly connected to the server) or the channel isn't available because of any other reason. - /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means - /// that the ID is invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, - mumble_channelid_t newChannelID); - - /// Called whenever a user leaves a channel. - /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user that left the channel - /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is - /// invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); - - /// Called when any user changes his/her talking state. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user whose talking state has been changed - /// @param talkingState The new TalkingState the user has switched to. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); - - /// Called whenever there is audio input. - /// - /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) - /// @returns Whether this callback has modified the audio input-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); - - /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). - /// The provided audio buffer is the raw buffer without any processing applied to it yet. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) - /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, - /// the content of this parameter is unspecified and should not be accessed - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); - - /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). - /// Note that this happens immediately before Mumble clips the audio buffer. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); - - /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the - /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended - /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. - /// - /// @param connection The ID of the server-connection the data is coming from - /// @param sender The ID of the user whose client's plugin has sent the data - /// @param data The sent data represented as a string - /// @param dataLength The length of data - /// @param dataID The ID of this data - /// @return Whether the given data has been processed by this plugin - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, - const char *dataID); - - /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the - /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this - /// method will be called for every client already on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been added - - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the - /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this - /// method will be called for every client on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local - /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been added - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local - /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also - /// considered renaming). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been renamed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a key has been pressed or released while Mumble has keyboard focus. - /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard - /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to - /// enable that. - /// - /// @param keyCode The key code of the respective key. The character codes are defined - /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform - /// to the ASCII code-page with the only difference that case is not distinguished. Therefore - /// always the upper-case letter code will be used for letters. - /// @param wasPres Whether the respective key has been pressed (instead of released) - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// This function is used to determine whether the plugin can find an update for itself that is available for download. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @return Whether the plugin was able to find an update for itself - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); - - /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. - /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure - /// though that you don't forget about the trailing null byte. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into - /// @param bufferSize The size of the buffer - /// @param offset The offset in the URL from which this functions should start writing it to the buffer - /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called - /// again with a modified offset until the URL has been completely transferred. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Gets called right after loading the plugin in order to let the plugin initialize. + /// + /// Registers the ID of this plugin. + /// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with + /// and by which this plugin can identify itself when communicating with Mumble. + /// @returns The status of the initialization. If everything went fine, return STATUS_OK + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(uint32_t id); + + /// Gets called when unloading the plugin in order to allow it to clean up after itself. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); + + /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied + /// for further usage though. + /// + /// @returns A pointer to the plugin name (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); + + /// Gets the Version of the plugin-API this plugin intends to use. + /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. + /// + /// @return The respective API Version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); + + /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used + /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use + /// of it at some point. + /// + /// @param api The MumbleAPI struct + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); + + + + ////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Tells the plugin some basic information about the Mumble client loading it. + /// This function will be the first one that is being called on this plugin - even before it is decided whether to load + /// the plugin at all. + /// + /// @param mumbleVersion The Version of the Mumble client + /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with + /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); + + /// Gets the Version of this plugin + /// + /// @returns The plugin's version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); + + /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the author(s) name(s) (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); + + /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the description (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); + + /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum + /// together. + /// + /// @returns The feature set of this plugin + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); + + /// Requests this plugin to deactivate the given (sub)set of provided features. + /// If this is not possible, the features that can't be deactivated shall be returned by this function. + /// + /// Example (check if FEATURE_POSITIONAL shall be deactivated): + /// @code + /// if (features & FEATURE_POSITIONAL) { + /// // positional shall be deactivated + /// }; + /// @endcode + /// + /// @param features The feature set that shall be deactivated + /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return + /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); + + + + ////////////////////////////////////////////////////////////////////////////////// + //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // If this plugin wants to provide positional audio, all functions of this category + // have to be implemented + + /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently + /// able to do so and allocate memory that is needed for that process. + /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i + /// belongs to a program whose name is listed at index i in the "name-array". + /// + /// @param programNames An array of pointers to the program names + /// @param programPIDs An array of the corresponding program PIDs + /// @param programCount The length of programNames and programPIDs + /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently + /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) + /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be + /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. + PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char** programNames, const uint64_t* programPIDs, size_t programCount); + + /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. + /// + /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it + /// is facing). + /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One + /// unit represents one meter of distance. + /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it + /// is facing). + /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit + /// represents one meter of distance. + /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data + /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical + /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function + /// or until shutdownPositionalData is called. + /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can + /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid + /// until the next invokation of this function or until shutdownPositionalData is called. + /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will + /// be called. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float* avatarPos, float* avatarDir, float* avatarAxis, float* cameraPos, float* cameraDir, + float* cameraAxis, const char** context, const char** identity); + + /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should + /// be freed at this point. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Called when connecting to a server. + /// + /// @param connection The ID of the newly established server-connection + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); + + /// Called when disconnecting from a server. + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); + + /// Called when the client has finished synchronizing with the server + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); + + /// Called whenever any user on the server enters a channel + /// This function will also be called when freshly connecting to a server as each user on that + /// server needs to be "added" to the respective channel as far as the local client is concerned. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user this event has been triggered for + /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user + /// freshly connected to the server) or the channel isn't available because of any other reason. + /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means + /// that the ID is invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, + mumble_channelid_t newChannelID); + + /// Called whenever a user leaves a channel. + /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user that left the channel + /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is + /// invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); + + /// Called when any user changes his/her talking state. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user whose talking state has been changed + /// @param talkingState The new TalkingState the user has switched to. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); + + /// Called whenever there is audio input. + /// + /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) + /// @returns Whether this callback has modified the audio input-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short* inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); + + /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). + /// The provided audio buffer is the raw buffer without any processing applied to it yet. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) + /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, + /// the content of this parameter is unspecified and should not be accessed + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); + + /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). + /// Note that this happens immediately before Mumble clips the audio buffer. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float* outputPCM, uint32_t sampleCount, uint16_t channelCount); + + /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the + /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended + /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. + /// + /// @param connection The ID of the server-connection the data is coming from + /// @param sender The ID of the user whose client's plugin has sent the data + /// @param data The sent data represented as a string + /// @param dataLength The length of data + /// @param dataID The ID of this data + /// @return Whether the given data has been processed by this plugin + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char* data, size_t dataLength, + const char* dataID); + + /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the + /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this + /// method will be called for every client already on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been added + + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the + /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this + /// method will be called for every client on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local + /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been added + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local + /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also + /// considered renaming). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been renamed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a key has been pressed or released while Mumble has keyboard focus. + /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard + /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to + /// enable that. + /// + /// @param keyCode The key code of the respective key. The character codes are defined + /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform + /// to the ASCII code-page with the only difference that case is not distinguished. Therefore + /// always the upper-case letter code will be used for letters. + /// @param wasPres Whether the respective key has been pressed (instead of released) + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// This function is used to determine whether the plugin can find an update for itself that is available for download. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @return Whether the plugin was able to find an update for itself + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); + + /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. + /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure + /// though that you don't forget about the trailing null byte. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into + /// @param bufferSize The size of the buffer + /// @param offset The offset in the URL from which this functions should start writing it to the buffer + /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called + /// again with a modified offset until the URL has been completely transferred. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char* buffer, uint16_t bufferSize, uint16_t offset); #ifdef __cplusplus diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h index 9f0264eb4..ce684dbf9 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h @@ -13,16 +13,16 @@ #include #ifdef QT_VERSION - #include +#include #endif // define the calling convention macro based on the compiler being used #if defined(_MSC_VER) - #define PLUGIN_CALLING_CONVENTION __cdecl +#define PLUGIN_CALLING_CONVENTION __cdecl #elif defined(__MINGW32__) - #define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) +#define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) #else - #define PLUGIN_CALLING_CONVENTION +#define PLUGIN_CALLING_CONVENTION #endif @@ -35,227 +35,227 @@ /// This enum's values correspond to special feature sets a plugin may provide. /// They are meant to be or'ed together to represent the total feature set of a plugin. enum PluginFeature { - /// None of the below - FEATURE_NONE = 0, - /// The plugin provides positional data from a game - FEATURE_POSITIONAL = 1 << 0, - /// The plugin modifies the input/output audio itself - FEATURE_AUDIO = 1 << 1 + /// None of the below + FEATURE_NONE = 0, + /// The plugin provides positional data from a game + FEATURE_POSITIONAL = 1 << 0, + /// The plugin modifies the input/output audio itself + FEATURE_AUDIO = 1 << 1 }; /// This enum's values represent talking states a user can be in when using Mumble. enum TalkingState { - INVALID=-1, - PASSIVE=0, - TALKING, - WHISPERING, - SHOUTING + INVALID = -1, + PASSIVE = 0, + TALKING, + WHISPERING, + SHOUTING }; /// This enum's values represent transmission modes a user might have configured. Transmission mode /// in this context is referring to a method that determines when a user is speaking and thus when /// to transmit audio packets. enum TransmissionMode { - TM_CONTINOUS, - TM_VOICE_ACTIVATION, - TM_PUSH_TO_TALK + TM_CONTINOUS, + TM_VOICE_ACTIVATION, + TM_PUSH_TO_TALK }; /// This enum's values represent the error codes that are being used by the MumbleAPI. /// You can get a string-representation for each error code via the errorMessage function. enum ErrorCode { - EC_GENERIC_ERROR = -1, - EC_OK = 0, - EC_POINTER_NOT_FOUND, - EC_NO_ACTIVE_CONNECTION, - EC_USER_NOT_FOUND, - EC_CHANNEL_NOT_FOUND, - EC_CONNECTION_NOT_FOUND, - EC_UNKNOWN_TRANSMISSION_MODE, - EC_AUDIO_NOT_AVAILABLE, - EC_INVALID_SAMPLE, - EC_INVALID_PLUGIN_ID, - EC_INVALID_MUTE_TARGET, - EC_CONNECTION_UNSYNCHRONIZED, - EC_INVALID_API_VERSION + EC_GENERIC_ERROR = -1, + EC_OK = 0, + EC_POINTER_NOT_FOUND, + EC_NO_ACTIVE_CONNECTION, + EC_USER_NOT_FOUND, + EC_CHANNEL_NOT_FOUND, + EC_CONNECTION_NOT_FOUND, + EC_UNKNOWN_TRANSMISSION_MODE, + EC_AUDIO_NOT_AVAILABLE, + EC_INVALID_SAMPLE, + EC_INVALID_PLUGIN_ID, + EC_INVALID_MUTE_TARGET, + EC_CONNECTION_UNSYNCHRONIZED, + EC_INVALID_API_VERSION }; /// This enum's values represent error codes specific to the framework of handling positional data /// gathering (needed for Mumble's positional audio feature). enum PositionalDataErrorCode { - /// Positional data has been initialized properly - PDEC_OK = 0, - /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be - /// at another point in time. - PDEC_ERROR_TEMP, - /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). - PDEC_ERROR_PERM + /// Positional data has been initialized properly + PDEC_OK = 0, + /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be + /// at another point in time. + PDEC_ERROR_TEMP, + /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). + PDEC_ERROR_PERM }; /// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. enum KeyCode { - KC_INVALID = -1, + KC_INVALID = -1, - // Non-printable characters first - KC_NULL = 0, - KC_END = 1, - KC_LEFT = 2, - KC_RIGHT = 4, - KC_UP = 5, - KC_DOWN = 6, - KC_DELETE = 7, - KC_BACKSPACE = 8, - KC_TAB = 9, - KC_ENTER = 10, // == '\n' - KC_ESCAPE = 27, - KC_PAGE_UP = 11, - KC_PAGE_DOWN = 12, - KC_SHIFT = 13, - KC_CONTROL = 14, - KC_META = 15, - KC_ALT = 16, - KC_ALT_GR = 17, - KC_CAPSLOCK = 18, - KC_NUMLOCK = 19, - KC_SUPER = 20, // == windows key - KC_HOME = 21, // == Pos1 - KC_PRINT = 22, - KC_SCROLLLOCK = 23, + // Non-printable characters first + KC_NULL = 0, + KC_END = 1, + KC_LEFT = 2, + KC_RIGHT = 4, + KC_UP = 5, + KC_DOWN = 6, + KC_DELETE = 7, + KC_BACKSPACE = 8, + KC_TAB = 9, + KC_ENTER = 10, // == '\n' + KC_ESCAPE = 27, + KC_PAGE_UP = 11, + KC_PAGE_DOWN = 12, + KC_SHIFT = 13, + KC_CONTROL = 14, + KC_META = 15, + KC_ALT = 16, + KC_ALT_GR = 17, + KC_CAPSLOCK = 18, + KC_NUMLOCK = 19, + KC_SUPER = 20, // == windows key + KC_HOME = 21, // == Pos1 + KC_PRINT = 22, + KC_SCROLLLOCK = 23, - // Printable characters are assigned to their ASCII code - KC_SPACE = ' ', - KC_EXCLAMATION_MARK = '!', - KC_DOUBLE_QUOTE = '"', - KC_HASHTAG = '#', - KC_DOLLAR = '$', - KC_PERCENT = '%', - KC_AMPERSAND = '&', - KC_SINGLE_QUOTE = '\'', - KC_OPEN_PARENTHESIS = '(', - KC_CLOSE_PARENTHESIS = ')', - KC_ASTERISK = '*', - KC_PLUS = '+', - KC_COMMA = ',', - KC_MINUS = '-', - KC_PERIOD = '.', - KC_SLASH = '/', - KC_0 = '0', - KC_1 = '1', - KC_2 = '2', - KC_3 = '3', - KC_4 = '4', - KC_5 = '5', - KC_6 = '6', - KC_7 = '7', - KC_8 = '8', - KC_9 = '9', - KC_COLON = ':', - KC_SEMICOLON = ';', - KC_LESS_THAN = '<', - KC_EQUALS = '=', - KC_GREATER_THAN = '>', - KC_QUESTION_MARK = '?', - KC_AT_SYMBOL = '@', - KC_A = 'A', - KC_B = 'B', - KC_C = 'C', - KC_D = 'D', - KC_E = 'E', - KC_F = 'F', - KC_G = 'G', - KC_H = 'H', - KC_I = 'I', - KC_J = 'J', - KC_K = 'K', - KC_L = 'L', - KC_M = 'M', - KC_N = 'N', - KC_O = 'O', - KC_P = 'P', - KC_Q = 'Q', - KC_R = 'R', - KC_S = 'S', - KC_T = 'T', - KC_U = 'U', - KC_V = 'V', - KC_W = 'W', - KC_X = 'X', - KC_Y = 'Y', - KC_Z = 'Z', - // leave out lowercase letters (for now) - KC_OPEN_BRACKET = '[', - KC_BACKSLASH = '\\', - KC_CLOSE_BRACKET = ']', - KC_CIRCUMFLEX = '^', - KC_UNDERSCORE = '_', - KC_GRAVE_AKCENT = '`', - KC_OPEN_BRACE = '{', - KC_VERTICAL_BAR = '|', - KC_CLOSE_BRACE = '}', - KC_TILDE = '~', + // Printable characters are assigned to their ASCII code + KC_SPACE = ' ', + KC_EXCLAMATION_MARK = '!', + KC_DOUBLE_QUOTE = '"', + KC_HASHTAG = '#', + KC_DOLLAR = '$', + KC_PERCENT = '%', + KC_AMPERSAND = '&', + KC_SINGLE_QUOTE = '\'', + KC_OPEN_PARENTHESIS = '(', + KC_CLOSE_PARENTHESIS = ')', + KC_ASTERISK = '*', + KC_PLUS = '+', + KC_COMMA = ',', + KC_MINUS = '-', + KC_PERIOD = '.', + KC_SLASH = '/', + KC_0 = '0', + KC_1 = '1', + KC_2 = '2', + KC_3 = '3', + KC_4 = '4', + KC_5 = '5', + KC_6 = '6', + KC_7 = '7', + KC_8 = '8', + KC_9 = '9', + KC_COLON = ':', + KC_SEMICOLON = ';', + KC_LESS_THAN = '<', + KC_EQUALS = '=', + KC_GREATER_THAN = '>', + KC_QUESTION_MARK = '?', + KC_AT_SYMBOL = '@', + KC_A = 'A', + KC_B = 'B', + KC_C = 'C', + KC_D = 'D', + KC_E = 'E', + KC_F = 'F', + KC_G = 'G', + KC_H = 'H', + KC_I = 'I', + KC_J = 'J', + KC_K = 'K', + KC_L = 'L', + KC_M = 'M', + KC_N = 'N', + KC_O = 'O', + KC_P = 'P', + KC_Q = 'Q', + KC_R = 'R', + KC_S = 'S', + KC_T = 'T', + KC_U = 'U', + KC_V = 'V', + KC_W = 'W', + KC_X = 'X', + KC_Y = 'Y', + KC_Z = 'Z', + // leave out lowercase letters (for now) + KC_OPEN_BRACKET = '[', + KC_BACKSLASH = '\\', + KC_CLOSE_BRACKET = ']', + KC_CIRCUMFLEX = '^', + KC_UNDERSCORE = '_', + KC_GRAVE_AKCENT = '`', + KC_OPEN_BRACE = '{', + KC_VERTICAL_BAR = '|', + KC_CLOSE_BRACE = '}', + KC_TILDE = '~', - // Some characters from the extended ASCII code - KC_DEGREE_SIGN = 176, + // Some characters from the extended ASCII code + KC_DEGREE_SIGN = 176, - // F-keys - // Start at a value of 256 as extended ASCII codes range up to 256 - KC_F1 = 256, - KC_F2 = 257, - KC_F3 = 258, - KC_F4 = 259, - KC_F5 = 260, - KC_F6 = 261, - KC_F7 = 262, - KC_F8 = 263, - KC_F9 = 264, - KC_F10 = 265, - KC_F11 = 266, - KC_F12 = 267, - KC_F13 = 268, - KC_F14 = 269, - KC_F15 = 270, - KC_F16 = 271, - KC_F17 = 272, - KC_F18 = 273, - KC_F19 = 274, + // F-keys + // Start at a value of 256 as extended ASCII codes range up to 256 + KC_F1 = 256, + KC_F2 = 257, + KC_F3 = 258, + KC_F4 = 259, + KC_F5 = 260, + KC_F6 = 261, + KC_F7 = 262, + KC_F8 = 263, + KC_F9 = 264, + KC_F10 = 265, + KC_F11 = 266, + KC_F12 = 267, + KC_F13 = 268, + KC_F14 = 269, + KC_F15 = 270, + KC_F16 = 271, + KC_F17 = 272, + KC_F18 = 273, + KC_F19 = 274, }; /// A struct for representing a version of the form major.minor.patch struct Version { - int32_t major; - int32_t minor; - int32_t patch; + int32_t major; + int32_t minor; + int32_t patch; #ifdef __cplusplus - bool operator<(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; - } + bool operator<(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; + } - bool operator>(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; - } + bool operator>(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; + } - bool operator>=(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; - } + bool operator>=(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; + } - bool operator<=(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; - } + bool operator<=(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; + } - bool operator==(const Version& other) const { - return this->major == other.major && this->minor == other.minor && this->patch == other.patch; - } + bool operator==(const Version& other) const { + return this->major == other.major && this->minor == other.minor && this->patch == other.patch; + } - operator std::string() const { - return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); - } + operator std::string() const { + return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); + } #ifdef QT_VERSION - operator QString() const { - return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); - } + operator QString() const { + return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); + } #endif #endif }; @@ -265,38 +265,38 @@ struct Version { /// is encoded as a C-string and are static meaning that it is safe to use the /// returned pointer in your code. inline const char* errorMessage(int16_t errorCode) { - switch (errorCode) { - case EC_GENERIC_ERROR: - return "Generic error"; - case EC_OK: - return "Ok - this is not an error"; - case EC_POINTER_NOT_FOUND: - return "Can't find the passed pointer"; - case EC_NO_ACTIVE_CONNECTION: - return "There is currently no active connection to a server"; - case EC_USER_NOT_FOUND: - return "Can't find the requested user"; - case EC_CHANNEL_NOT_FOUND: - return "Can't find the requested channel"; - case EC_CONNECTION_NOT_FOUND: - return "Can't identify the requested connection"; - case EC_UNKNOWN_TRANSMISSION_MODE: - return "Unknown transmission mode encountered"; - case EC_AUDIO_NOT_AVAILABLE: - return "There is currently no audio output available"; - case EC_INVALID_SAMPLE: - return "Attempted to use invalid sample (can't play it)"; - case EC_INVALID_PLUGIN_ID: - return "Used an invalid plugin ID"; - case EC_INVALID_MUTE_TARGET: - return "Used an invalid mute-target"; - case EC_CONNECTION_UNSYNCHRONIZED: - return "The requested server connection has not yet finished synchrnonizing"; - case EC_INVALID_API_VERSION: - return "The used API version is invalid or not supported"; - default: - return "Unknown error code"; - } + switch (errorCode) { + case EC_GENERIC_ERROR: + return "Generic error"; + case EC_OK: + return "Ok - this is not an error"; + case EC_POINTER_NOT_FOUND: + return "Can't find the passed pointer"; + case EC_NO_ACTIVE_CONNECTION: + return "There is currently no active connection to a server"; + case EC_USER_NOT_FOUND: + return "Can't find the requested user"; + case EC_CHANNEL_NOT_FOUND: + return "Can't find the requested channel"; + case EC_CONNECTION_NOT_FOUND: + return "Can't identify the requested connection"; + case EC_UNKNOWN_TRANSMISSION_MODE: + return "Unknown transmission mode encountered"; + case EC_AUDIO_NOT_AVAILABLE: + return "There is currently no audio output available"; + case EC_INVALID_SAMPLE: + return "Attempted to use invalid sample (can't play it)"; + case EC_INVALID_PLUGIN_ID: + return "Used an invalid plugin ID"; + case EC_INVALID_MUTE_TARGET: + return "Used an invalid mute-target"; + case EC_CONNECTION_UNSYNCHRONIZED: + return "The requested server connection has not yet finished synchrnonizing"; + case EC_INVALID_API_VERSION: + return "The used API version is invalid or not supported"; + default: + return "Unknown error code"; + } } From a4d3f346bde66ba0b2c10769690668b6cb4d4208 Mon Sep 17 00:00:00 2001 From: jonpas Date: Tue, 14 Jul 2020 22:29:17 +0200 Subject: [PATCH 062/104] Revert "Update to latest API changes" This reverts commit 5c84c317221181022410194a83bb73d319cb72fd. --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 2 +- .../ACRE2Mumble/mumble_includes/MumbleAPI.h | 469 ++++++------- .../mumble_includes/MumblePlugin.h | 636 +++++++++--------- .../mumble_includes/PluginComponents.h | 421 ++++++------ 4 files changed, 740 insertions(+), 788 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index f83e681b4..1e64d694b 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -38,7 +38,7 @@ void mumble_registerAPIFunctions(struct MumbleAPI api) { } } -mumble_error_t mumble_init(uint32_t connection) { +mumble_error_t mumble_init(mumble_connection_t connection) { if (connection != -1) { activeConnection = connection; } diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h index 537a82c21..1ef62eaa6 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h @@ -19,262 +19,219 @@ const version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PL struct MumbleAPI { - ///////////////////////////////////////////////////////// - ////////////////////// GENERAL NOTE ///////////////////// - ///////////////////////////////////////////////////////// - // - // All functions that take in a connection as a paremeter may only be called **after** the connection - // has finished synchronizing. The only exception from this is isConnectionSynchronized. - - - // -------- Memory management -------- - - /// Frees the given pointer. - /// - /// @param callerID The ID of the plugin calling this function - /// @param pointer The pointer to free - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* freeMemory)(plugin_id_t callerID, void* pointer); - - - - // -------- Getter functions -------- - - /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] connection A pointer to the memory location the ID should be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the - /// value of the provided pointer - mumble_error_t(PLUGIN_CALLING_CONVENTION* getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t* connection); - - /// Checks whether the given connection has finished initializing yet. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished synchronization yet - /// after this function has executed successfully. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* isConnectionSynchronized)(plugin_id_t callerID, mumble_connection_t connection, bool* synchronized); - - /// Fills in the information about the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t* userID); - - /// Fills in the information about the given user's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The user's ID whose name should be obtained - /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getUserName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, char** userName); - - /// Fills in the information about the given channel's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The channel's ID whose name should be obtained - /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, char** channelName); - - /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter - /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the - /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t** users, - size_t* userCount); - - /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent - /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the - /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t** channels, size_t* channelCount); - - /// Gets the ID of the channel the given user is currently connected to. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the ID of the channel shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t* channel); - - /// Gets an array of all users in the specified channel. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The ID of the channel whose users shall be retrieved - /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has - /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function - /// returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, mumble_userid_t** userList, size_t* userCount); - - /// Gets the current transmission mode of the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t* transmissionMode); - - /// Checks whether the given user is currently locally muted. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the local mute state of that user shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION* isUserLocallyMuted)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, bool* muted); - - - // -------- Request functions -------- - - /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set - /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of - /// restoring the previous state afterwards. - /// - /// @param callerID The ID of the plugin calling this function - /// @param transmissionMode The requested transmission mode - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); - - /// Requests Mumble to move the given user into the given channel - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param channelID The ID of the channel to move the user to - /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a - /// password for entering - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t channelID, const char* password); - - /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen - /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again - /// once it is no longer required - /// - /// @param callerID The ID of the plugin calling this function - /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); - - /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute state - /// opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client has muted its - /// microphone and thus isn't transmitting any audio). - /// Furthermore it must be noted that muting the local user with this function does not work (it doesn't make sense). If - /// you try to do so, this function will fail. In order to make this work, this function will also fail if the server - /// has not finished synchronizing with the client yet. - /// - /// @param callerID The ID of the plugin calling this function. - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param muted Whether to locally mute the given client (opposed to unmuting it) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalMute)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, bool muted); - - - - // -------- Find functions -------- - - /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userName The respective user's name - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION* findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char* userName, - mumble_userid_t* userID); - - /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelName The respective channel's name - /// @param[out] channelID A pointer to the memory the channel's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION* findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, - const char* channelName, mumble_channelid_t* channelID); - - - - // -------- Miscellaneous -------- - - /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active - /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data - /// must not contain sensitive information or anything else that shouldn't be known by others. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to send the data through (the server the given users are on) - /// @param users An array of user IDs to send the data to - /// @param userCount The size of the provided user-array - /// @param data The data that shall be sent as a String - /// @param dataLength The length of the data-string - /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with - /// the data - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t* users, - size_t userCount, const char* data, size_t dataLength, const char* dataID); - - /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. - /// - /// @param callerID The ID of the plugin calling this function - /// @param message The message to log - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* log)(plugin_id_t callerID, const char* message); - - /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it - /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). - /// - /// @param callerID The ID of the plugin calling this function - /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION* playSample)(plugin_id_t callerID, const char* samplePath); + // -------- Memory management -------- + + /// Frees the given pointer. + /// + /// @param callerID The ID of the plugin calling this function + /// @param pointer The pointer to free + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *freeMemory)(plugin_id_t callerID, void *pointer); + + + + // -------- Getter functions -------- + + /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] connection A pointer to the memory location the ID should be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the + /// value of the provided pointer + mumble_error_t (PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t *connection); + + /// Fills in the information about the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID); + + /// Fills in the information about the given user's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The user's ID whose name should be obtained + /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getUserName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, char **userName); + + /// Fills in the information about the given channel's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The channel's ID whose name should be obtained + /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelName)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, char **channelName); + + /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter + /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the + /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users, + size_t *userCount); + + /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent + /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the + /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t **channels, size_t *channelCount); + + /// Gets the ID of the channel the given user is currently connected to. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the ID of the channel shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t *channel); + + /// Gets an array of all users in the specified channel. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The ID of the channel whose users shall be retrieved + /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has + /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function + /// returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, + mumble_channelid_t channelID, mumble_userid_t **userList, size_t *userCount); + + /// Gets the current transmission mode of the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t *transmissionMode); + + + + // -------- Request functions -------- + + /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set + /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of + /// restoring the previous state afterwards. + /// + /// @param callerID The ID of the plugin calling this function + /// @param transmissionMode The requested transmission mode + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); + + /// Requests Mumble to move the given user into the given channel + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param channelID The ID of the channel to move the user to + /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a + /// password for entering + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t channelID, const char *password); + + /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen + /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again + /// once it is no longer required + /// + /// @param callerID The ID of the plugin calling this function + /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); + + + + // -------- Find functions -------- + + /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userName The respective user's name + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t (PLUGIN_CALLING_CONVENTION *findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char *userName, + mumble_userid_t *userID); + + /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelName The respective channel's name + /// @param[out] channelID A pointer to the memory the channel's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t (PLUGIN_CALLING_CONVENTION *findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, + const char *channelName, mumble_channelid_t *channelID); + + + + // -------- Miscellaneous -------- + + /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active + /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data + /// must not contain sensitive information or anything else that shouldn't be known by others. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to send the data through (the server the given users are on) + /// @param users An array of user IDs to send the data to + /// @param userCount The size of the provided user-array + /// @param data The data that shall be sent as a String + /// @param dataLength The length of the data-string + /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with + /// the data + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *users, + size_t userCount, const char *data, size_t dataLength, const char *dataID); + + /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. + /// + /// @param callerID The ID of the plugin calling this function + /// @param message The message to log + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *log)(plugin_id_t callerID, const char *message); + + /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it + /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). + /// + /// @param callerID The ID of the plugin calling this function + /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t (PLUGIN_CALLING_CONVENTION *playSample)(plugin_id_t callerID, const char *samplePath); }; #endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h index 38ddcdc28..c6c82393d 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h @@ -15,331 +15,335 @@ #include #if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems -#define PLUGIN_EXPORT __attribute__((visibility("default"))) + #define PLUGIN_EXPORT __attribute__((visibility("default"))) #elif defined(_MSC_VER) -#define PLUGIN_EXPORT __declspec(dllexport) + #define PLUGIN_EXPORT __declspec(dllexport) #elif defined(__MINGW32__) -#define PLUGIN_EXPORT __attribute__((dllexport)) + #define PLUGIN_EXPORT __attribute__((dllexport)) #else -#error No PLUGIN_EXPORT definition available + #error No PLUGIN_EXPORT definition available #endif #ifdef __cplusplus extern "C" { #endif - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Gets called right after loading the plugin in order to let the plugin initialize. - /// - /// Registers the ID of this plugin. - /// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with - /// and by which this plugin can identify itself when communicating with Mumble. - /// @returns The status of the initialization. If everything went fine, return STATUS_OK - PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(uint32_t id); - - /// Gets called when unloading the plugin in order to allow it to clean up after itself. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); - - /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied - /// for further usage though. - /// - /// @returns A pointer to the plugin name (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); - - /// Gets the Version of the plugin-API this plugin intends to use. - /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. - /// - /// @return The respective API Version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); - - /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used - /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use - /// of it at some point. - /// - /// @param api The MumbleAPI struct - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); - - - - ////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Tells the plugin some basic information about the Mumble client loading it. - /// This function will be the first one that is being called on this plugin - even before it is decided whether to load - /// the plugin at all. - /// - /// @param mumbleVersion The Version of the Mumble client - /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with - /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); - - /// Gets the Version of this plugin - /// - /// @returns The plugin's version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); - - /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the author(s) name(s) (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); - - /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the description (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); - - /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum - /// together. - /// - /// @returns The feature set of this plugin - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); - - /// Requests this plugin to deactivate the given (sub)set of provided features. - /// If this is not possible, the features that can't be deactivated shall be returned by this function. - /// - /// Example (check if FEATURE_POSITIONAL shall be deactivated): - /// @code - /// if (features & FEATURE_POSITIONAL) { - /// // positional shall be deactivated - /// }; - /// @endcode - /// - /// @param features The feature set that shall be deactivated - /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return - /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); - - - - ////////////////////////////////////////////////////////////////////////////////// - //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - // If this plugin wants to provide positional audio, all functions of this category - // have to be implemented - - /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently - /// able to do so and allocate memory that is needed for that process. - /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i - /// belongs to a program whose name is listed at index i in the "name-array". - /// - /// @param programNames An array of pointers to the program names - /// @param programPIDs An array of the corresponding program PIDs - /// @param programCount The length of programNames and programPIDs - /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently - /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) - /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be - /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. - PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char** programNames, const uint64_t* programPIDs, size_t programCount); - - /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. - /// - /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it - /// is facing). - /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One - /// unit represents one meter of distance. - /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it - /// is facing). - /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit - /// represents one meter of distance. - /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data - /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical - /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function - /// or until shutdownPositionalData is called. - /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can - /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid - /// until the next invokation of this function or until shutdownPositionalData is called. - /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will - /// be called. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float* avatarPos, float* avatarDir, float* avatarAxis, float* cameraPos, float* cameraDir, - float* cameraAxis, const char** context, const char** identity); - - /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should - /// be freed at this point. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Called when connecting to a server. - /// - /// @param connection The ID of the newly established server-connection - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); - - /// Called when disconnecting from a server. - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); - - /// Called when the client has finished synchronizing with the server - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); - - /// Called whenever any user on the server enters a channel - /// This function will also be called when freshly connecting to a server as each user on that - /// server needs to be "added" to the respective channel as far as the local client is concerned. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user this event has been triggered for - /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user - /// freshly connected to the server) or the channel isn't available because of any other reason. - /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means - /// that the ID is invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, - mumble_channelid_t newChannelID); - - /// Called whenever a user leaves a channel. - /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user that left the channel - /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is - /// invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); - - /// Called when any user changes his/her talking state. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user whose talking state has been changed - /// @param talkingState The new TalkingState the user has switched to. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); - - /// Called whenever there is audio input. - /// - /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) - /// @returns Whether this callback has modified the audio input-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short* inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); - - /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). - /// The provided audio buffer is the raw buffer without any processing applied to it yet. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) - /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, - /// the content of this parameter is unspecified and should not be accessed - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); - - /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). - /// Note that this happens immediately before Mumble clips the audio buffer. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float* outputPCM, uint32_t sampleCount, uint16_t channelCount); - - /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the - /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended - /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. - /// - /// @param connection The ID of the server-connection the data is coming from - /// @param sender The ID of the user whose client's plugin has sent the data - /// @param data The sent data represented as a string - /// @param dataLength The length of data - /// @param dataID The ID of this data - /// @return Whether the given data has been processed by this plugin - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char* data, size_t dataLength, - const char* dataID); - - /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the - /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this - /// method will be called for every client already on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been added - - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the - /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this - /// method will be called for every client on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local - /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been added - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local - /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also - /// considered renaming). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been renamed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a key has been pressed or released while Mumble has keyboard focus. - /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard - /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to - /// enable that. - /// - /// @param keyCode The key code of the respective key. The character codes are defined - /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform - /// to the ASCII code-page with the only difference that case is not distinguished. Therefore - /// always the upper-case letter code will be used for letters. - /// @param wasPres Whether the respective key has been pressed (instead of released) - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// This function is used to determine whether the plugin can find an update for itself that is available for download. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @return Whether the plugin was able to find an update for itself - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); - - /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. - /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure - /// though that you don't forget about the trailing null byte. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into - /// @param bufferSize The size of the buffer - /// @param offset The offset in the URL from which this functions should start writing it to the buffer - /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called - /// again with a modified offset until the URL has been completely transferred. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char* buffer, uint16_t bufferSize, uint16_t offset); + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Gets called right after loading the plugin in order to let the plugin initialize. + /// + /// @param connection The ID of the server-connection this event is connected to, or its default value. + /// @returns The status of the initialization. If everything went fine, return STATUS_OK + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_connection_t connection); + + /// Gets called when unloading the plugin in order to allow it to clean up after itself. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); + + /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied + /// for further usage though. + /// + /// @returns A pointer to the plugin name (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); + + /// Gets the Version of the plugin-API this plugin intends to use. + /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. + /// + /// @return The respective API Version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); + + /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used + /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use + /// of it at some point. + /// + /// @param api The MumbleAPI struct + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); + + + + ////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Tells the plugin some basic information about the Mumble client loading it. + /// This function will be the first one that is being called on this plugin - even before it is decided whether to load + /// the plugin at all. + /// + /// @param mumbleVersion The Version of the Mumble client + /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with + /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); + + /// Gets the Version of this plugin + /// + /// @returns The plugin's version + PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); + + /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the author(s) name(s) (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); + + /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will + /// be copied for further usage though. + /// + /// @returns A pointer to the description (encoded as a C-String) + PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); + + /// Registers the ID of this plugin. This is the ID Mumble will reference this plugin with and by which this plugin + /// can identify itself when communicating with Mumble. + /// + /// @param id The ID for this plugin + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerPluginID(uint32_t id); + + /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum + /// together. + /// + /// @returns The feature set of this plugin + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); + + /// Requests this plugin to deactivate the given (sub)set of provided features. + /// If this is not possible, the features that can't be deactivated shall be returned by this function. + /// + /// Example (check if FEATURE_POSITIONAL shall be deactivated): + /// @code + /// if (features & FEATURE_POSITIONAL) { + /// // positional shall be deactivated + /// }; + /// @endcode + /// + /// @param features The feature set that shall be deactivated + /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return + /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); + + + + ////////////////////////////////////////////////////////////////////////////////// + //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // If this plugin wants to provide positional audio, all functions of this category + // have to be implemented + + /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently + /// able to do so and allocate memory that is needed for that process. + /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i + /// belongs to a program whose name is listed at index i in the "name-array". + /// + /// @param programNames An array of pointers to the program names + /// @param programPIDs An array of the corresponding program PIDs + /// @param programCount The length of programNames and programPIDs + /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently + /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) + /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be + /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. + PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); + + /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. + /// + /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it + /// is facing). + /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One + /// unit represents one meter of distance. + /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it + /// is facing). + /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit + /// represents one meter of distance. + /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data + /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical + /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function + /// or until shutdownPositionalData is called. + /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can + /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid + /// until the next invokation of this function or until shutdownPositionalData is called. + /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will + /// be called. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, + float *cameraAxis, const char **context, const char **identity); + + /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should + /// be freed at this point. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Called when connecting to a server. + /// + /// @param connection The ID of the newly established server-connection + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); + + /// Called when disconnecting from a server. + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); + + /// Called when the client has finished synchronizing with the server + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); + + /// Called whenever any user on the server enters a channel + /// This function will also be called when freshly connecting to a server as each user on that + /// server needs to be "added" to the respective channel as far as the local client is concerned. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user this event has been triggered for + /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user + /// freshly connected to the server) or the channel isn't available because of any other reason. + /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means + /// that the ID is invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, + mumble_channelid_t newChannelID); + + /// Called whenever a user leaves a channel. + /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user that left the channel + /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is + /// invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); + + /// Called when any user changes his/her talking state. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user whose talking state has been changed + /// @param talkingState The new TalkingState the user has switched to. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); + + /// Called whenever there is audio input. + /// + /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) + /// @returns Whether this callback has modified the audio input-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); + + /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). + /// The provided audio buffer is the raw buffer without any processing applied to it yet. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) + /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, + /// the content of this parameter is unspecified and should not be accessed + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); + + /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). + /// Note that this happens immediately before Mumble clips the audio buffer. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length + /// is sampleCount * channelCount. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); + + /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the + /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended + /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. + /// + /// @param connection The ID of the server-connection the data is coming from + /// @param sender The ID of the user whose client's plugin has sent the data + /// @param data The sent data represented as a string + /// @param dataLength The length of data + /// @param dataID The ID of this data + /// @return Whether the given data has been processed by this plugin + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, + const char *dataID); + + /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the + /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this + /// method will be called for every client already on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been added + + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the + /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this + /// method will be called for every client on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local + /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been added + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local + /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case + /// this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also + /// considered renaming). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been renamed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); + + /// Called when a key has been pressed or released while Mumble has keyboard focus. + /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard + /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to + /// enable that. + /// + /// @param keyCode The key code of the respective key. The character codes are defined + /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform + /// to the ASCII code-page with the only difference that case is not distinguished. Therefore + /// always the upper-case letter code will be used for letters. + /// @param wasPres Whether the respective key has been pressed (instead of released) + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// This function is used to determine whether the plugin can find an update for itself that is available for download. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @return Whether the plugin was able to find an update for itself + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); + + /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. + /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure + /// though that you don't forget about the trailing null byte. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into + /// @param bufferSize The size of the buffer + /// @param offset The offset in the URL from which this functions should start writing it to the buffer + /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called + /// again with a modified offset until the URL has been completely transferred. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); #ifdef __cplusplus diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h index ce684dbf9..b203eb1b7 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h @@ -13,16 +13,16 @@ #include #ifdef QT_VERSION -#include + #include #endif // define the calling convention macro based on the compiler being used #if defined(_MSC_VER) -#define PLUGIN_CALLING_CONVENTION __cdecl + #define PLUGIN_CALLING_CONVENTION __cdecl #elif defined(__MINGW32__) -#define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) + #define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) #else -#define PLUGIN_CALLING_CONVENTION + #define PLUGIN_CALLING_CONVENTION #endif @@ -35,227 +35,224 @@ /// This enum's values correspond to special feature sets a plugin may provide. /// They are meant to be or'ed together to represent the total feature set of a plugin. enum PluginFeature { - /// None of the below - FEATURE_NONE = 0, - /// The plugin provides positional data from a game - FEATURE_POSITIONAL = 1 << 0, - /// The plugin modifies the input/output audio itself - FEATURE_AUDIO = 1 << 1 + /// None of the below + FEATURE_NONE = 0, + /// The plugin provides positional data from a game + FEATURE_POSITIONAL = 1 << 0, + /// The plugin modifies the input/output audio itself + FEATURE_AUDIO = 1 << 1 }; /// This enum's values represent talking states a user can be in when using Mumble. enum TalkingState { - INVALID = -1, - PASSIVE = 0, - TALKING, - WHISPERING, - SHOUTING + INVALID=-1, + PASSIVE=0, + TALKING, + WHISPERING, + SHOUTING }; /// This enum's values represent transmission modes a user might have configured. Transmission mode /// in this context is referring to a method that determines when a user is speaking and thus when /// to transmit audio packets. enum TransmissionMode { - TM_CONTINOUS, - TM_VOICE_ACTIVATION, - TM_PUSH_TO_TALK + TM_CONTINOUS, + TM_VOICE_ACTIVATION, + TM_PUSH_TO_TALK }; /// This enum's values represent the error codes that are being used by the MumbleAPI. /// You can get a string-representation for each error code via the errorMessage function. enum ErrorCode { - EC_GENERIC_ERROR = -1, - EC_OK = 0, - EC_POINTER_NOT_FOUND, - EC_NO_ACTIVE_CONNECTION, - EC_USER_NOT_FOUND, - EC_CHANNEL_NOT_FOUND, - EC_CONNECTION_NOT_FOUND, - EC_UNKNOWN_TRANSMISSION_MODE, - EC_AUDIO_NOT_AVAILABLE, - EC_INVALID_SAMPLE, - EC_INVALID_PLUGIN_ID, - EC_INVALID_MUTE_TARGET, - EC_CONNECTION_UNSYNCHRONIZED, - EC_INVALID_API_VERSION + EC_GENERIC_ERROR = -1, + EC_OK = 0, + EC_POINTER_NOT_FOUND, + EC_NO_ACTIVE_CONNECTION, + EC_USER_NOT_FOUND, + EC_CHANNEL_NOT_FOUND, + EC_CONNECTION_NOT_FOUND, + EC_UNKNOWN_TRANSMISSION_MODE, + EC_AUDIO_NOT_AVAILABLE, + EC_INVALID_SAMPLE, + EC_INVALID_PLUGIN_ID }; /// This enum's values represent error codes specific to the framework of handling positional data /// gathering (needed for Mumble's positional audio feature). enum PositionalDataErrorCode { - /// Positional data has been initialized properly - PDEC_OK = 0, - /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be - /// at another point in time. - PDEC_ERROR_TEMP, - /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). - PDEC_ERROR_PERM + /// Positional data has been initialized properly + PDEC_OK = 0, + /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be + /// at another point in time. + PDEC_ERROR_TEMP, + /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). + PDEC_ERROR_PERM }; /// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. enum KeyCode { - KC_INVALID = -1, + KC_INVALID = -1, - // Non-printable characters first - KC_NULL = 0, - KC_END = 1, - KC_LEFT = 2, - KC_RIGHT = 4, - KC_UP = 5, - KC_DOWN = 6, - KC_DELETE = 7, - KC_BACKSPACE = 8, - KC_TAB = 9, - KC_ENTER = 10, // == '\n' - KC_ESCAPE = 27, - KC_PAGE_UP = 11, - KC_PAGE_DOWN = 12, - KC_SHIFT = 13, - KC_CONTROL = 14, - KC_META = 15, - KC_ALT = 16, - KC_ALT_GR = 17, - KC_CAPSLOCK = 18, - KC_NUMLOCK = 19, - KC_SUPER = 20, // == windows key - KC_HOME = 21, // == Pos1 - KC_PRINT = 22, - KC_SCROLLLOCK = 23, + // Non-printable characters first + KC_NULL = 0, + KC_END = 1, + KC_LEFT = 2, + KC_RIGHT = 4, + KC_UP = 5, + KC_DOWN = 6, + KC_DELETE = 7, + KC_BACKSPACE = 8, + KC_TAB = 9, + KC_ENTER = 10, // == '\n' + KC_ESCAPE = 27, + KC_PAGE_UP = 11, + KC_PAGE_DOWN = 12, + KC_SHIFT = 13, + KC_CONTROL = 14, + KC_META = 15, + KC_ALT = 16, + KC_ALT_GR = 17, + KC_CAPSLOCK = 18, + KC_NUMLOCK = 19, + KC_SUPER = 20, // == windows key + KC_HOME = 21, // == Pos1 + KC_PRINT = 22, + KC_SCROLLLOCK = 23, - // Printable characters are assigned to their ASCII code - KC_SPACE = ' ', - KC_EXCLAMATION_MARK = '!', - KC_DOUBLE_QUOTE = '"', - KC_HASHTAG = '#', - KC_DOLLAR = '$', - KC_PERCENT = '%', - KC_AMPERSAND = '&', - KC_SINGLE_QUOTE = '\'', - KC_OPEN_PARENTHESIS = '(', - KC_CLOSE_PARENTHESIS = ')', - KC_ASTERISK = '*', - KC_PLUS = '+', - KC_COMMA = ',', - KC_MINUS = '-', - KC_PERIOD = '.', - KC_SLASH = '/', - KC_0 = '0', - KC_1 = '1', - KC_2 = '2', - KC_3 = '3', - KC_4 = '4', - KC_5 = '5', - KC_6 = '6', - KC_7 = '7', - KC_8 = '8', - KC_9 = '9', - KC_COLON = ':', - KC_SEMICOLON = ';', - KC_LESS_THAN = '<', - KC_EQUALS = '=', - KC_GREATER_THAN = '>', - KC_QUESTION_MARK = '?', - KC_AT_SYMBOL = '@', - KC_A = 'A', - KC_B = 'B', - KC_C = 'C', - KC_D = 'D', - KC_E = 'E', - KC_F = 'F', - KC_G = 'G', - KC_H = 'H', - KC_I = 'I', - KC_J = 'J', - KC_K = 'K', - KC_L = 'L', - KC_M = 'M', - KC_N = 'N', - KC_O = 'O', - KC_P = 'P', - KC_Q = 'Q', - KC_R = 'R', - KC_S = 'S', - KC_T = 'T', - KC_U = 'U', - KC_V = 'V', - KC_W = 'W', - KC_X = 'X', - KC_Y = 'Y', - KC_Z = 'Z', - // leave out lowercase letters (for now) - KC_OPEN_BRACKET = '[', - KC_BACKSLASH = '\\', - KC_CLOSE_BRACKET = ']', - KC_CIRCUMFLEX = '^', - KC_UNDERSCORE = '_', - KC_GRAVE_AKCENT = '`', - KC_OPEN_BRACE = '{', - KC_VERTICAL_BAR = '|', - KC_CLOSE_BRACE = '}', - KC_TILDE = '~', + // Printable characters are assigned to their ASCII code + KC_SPACE = ' ', + KC_EXCLAMATION_MARK = '!', + KC_DOUBLE_QUOTE = '"', + KC_HASHTAG = '#', + KC_DOLLAR = '$', + KC_PERCENT = '%', + KC_AMPERSAND = '&', + KC_SINGLE_QUOTE = '\'', + KC_OPEN_PARENTHESIS = '(', + KC_CLOSE_PARENTHESIS = ')', + KC_ASTERISK = '*', + KC_PLUS = '+', + KC_COMMA = ',', + KC_MINUS = '-', + KC_PERIOD = '.', + KC_SLASH = '/', + KC_0 = '0', + KC_1 = '1', + KC_2 = '2', + KC_3 = '3', + KC_4 = '4', + KC_5 = '5', + KC_6 = '6', + KC_7 = '7', + KC_8 = '8', + KC_9 = '9', + KC_COLON = ':', + KC_SEMICOLON = ';', + KC_LESS_THAN = '<', + KC_EQUALS = '=', + KC_GREATER_THAN = '>', + KC_QUESTION_MARK = '?', + KC_AT_SYMBOL = '@', + KC_A = 'A', + KC_B = 'B', + KC_C = 'C', + KC_D = 'D', + KC_E = 'E', + KC_F = 'F', + KC_G = 'G', + KC_H = 'H', + KC_I = 'I', + KC_J = 'J', + KC_K = 'K', + KC_L = 'L', + KC_M = 'M', + KC_N = 'N', + KC_O = 'O', + KC_P = 'P', + KC_Q = 'Q', + KC_R = 'R', + KC_S = 'S', + KC_T = 'T', + KC_U = 'U', + KC_V = 'V', + KC_W = 'W', + KC_X = 'X', + KC_Y = 'Y', + KC_Z = 'Z', + // leave out lowercase letters (for now) + KC_OPEN_BRACKET = '[', + KC_BACKSLASH = '\\', + KC_CLOSE_BRACKET = ']', + KC_CIRCUMFLEX = '^', + KC_UNDERSCORE = '_', + KC_GRAVE_AKCENT = '`', + KC_OPEN_BRACE = '{', + KC_VERTICAL_BAR = '|', + KC_CLOSE_BRACE = '}', + KC_TILDE = '~', - // Some characters from the extended ASCII code - KC_DEGREE_SIGN = 176, + // Some characters from the extended ASCII code + KC_DEGREE_SIGN = 176, - // F-keys - // Start at a value of 256 as extended ASCII codes range up to 256 - KC_F1 = 256, - KC_F2 = 257, - KC_F3 = 258, - KC_F4 = 259, - KC_F5 = 260, - KC_F6 = 261, - KC_F7 = 262, - KC_F8 = 263, - KC_F9 = 264, - KC_F10 = 265, - KC_F11 = 266, - KC_F12 = 267, - KC_F13 = 268, - KC_F14 = 269, - KC_F15 = 270, - KC_F16 = 271, - KC_F17 = 272, - KC_F18 = 273, - KC_F19 = 274, + // F-keys + // Start at a value of 256 as extended ASCII codes range up to 256 + KC_F1 = 256, + KC_F2 = 257, + KC_F3 = 258, + KC_F4 = 259, + KC_F5 = 260, + KC_F6 = 261, + KC_F7 = 262, + KC_F8 = 263, + KC_F9 = 264, + KC_F10 = 265, + KC_F11 = 266, + KC_F12 = 267, + KC_F13 = 268, + KC_F14 = 269, + KC_F15 = 270, + KC_F16 = 271, + KC_F17 = 272, + KC_F18 = 273, + KC_F19 = 274, }; /// A struct for representing a version of the form major.minor.patch struct Version { - int32_t major; - int32_t minor; - int32_t patch; + int32_t major; + int32_t minor; + int32_t patch; #ifdef __cplusplus - bool operator<(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; - } + bool operator<(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; + } - bool operator>(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; - } + bool operator>(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; + } - bool operator>=(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; - } + bool operator>=(const Version& other) const { + return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; + } - bool operator<=(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; - } + bool operator<=(const Version& other) const { + return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; + } - bool operator==(const Version& other) const { - return this->major == other.major && this->minor == other.minor && this->patch == other.patch; - } + bool operator==(const Version& other) const { + return this->major == other.major && this->minor == other.minor && this->patch == other.patch; + } - operator std::string() const { - return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); - } + operator std::string() const { + return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); + } #ifdef QT_VERSION - operator QString() const { - return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); - } + operator QString() const { + return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); + } #endif #endif }; @@ -265,38 +262,32 @@ struct Version { /// is encoded as a C-string and are static meaning that it is safe to use the /// returned pointer in your code. inline const char* errorMessage(int16_t errorCode) { - switch (errorCode) { - case EC_GENERIC_ERROR: - return "Generic error"; - case EC_OK: - return "Ok - this is not an error"; - case EC_POINTER_NOT_FOUND: - return "Can't find the passed pointer"; - case EC_NO_ACTIVE_CONNECTION: - return "There is currently no active connection to a server"; - case EC_USER_NOT_FOUND: - return "Can't find the requested user"; - case EC_CHANNEL_NOT_FOUND: - return "Can't find the requested channel"; - case EC_CONNECTION_NOT_FOUND: - return "Can't identify the requested connection"; - case EC_UNKNOWN_TRANSMISSION_MODE: - return "Unknown transmission mode encountered"; - case EC_AUDIO_NOT_AVAILABLE: - return "There is currently no audio output available"; - case EC_INVALID_SAMPLE: - return "Attempted to use invalid sample (can't play it)"; - case EC_INVALID_PLUGIN_ID: - return "Used an invalid plugin ID"; - case EC_INVALID_MUTE_TARGET: - return "Used an invalid mute-target"; - case EC_CONNECTION_UNSYNCHRONIZED: - return "The requested server connection has not yet finished synchrnonizing"; - case EC_INVALID_API_VERSION: - return "The used API version is invalid or not supported"; - default: - return "Unknown error code"; - } + switch (errorCode) { + case EC_GENERIC_ERROR: + return "Generic error"; + case EC_OK: + return "Ok - this is not an error"; + case EC_POINTER_NOT_FOUND: + return "Can't find the passed pointer"; + case EC_NO_ACTIVE_CONNECTION: + return "There is currently no active connection to a server"; + case EC_USER_NOT_FOUND: + return "Can't find the requested user"; + case EC_CHANNEL_NOT_FOUND: + return "Can't find the requested channel"; + case EC_CONNECTION_NOT_FOUND: + return "Can't identify the requested connection"; + case EC_UNKNOWN_TRANSMISSION_MODE: + return "Unknown transmission mode encountered"; + case EC_AUDIO_NOT_AVAILABLE: + return "There is currently no audio output available"; + case EC_INVALID_SAMPLE: + return "Attempted to use invalid sample (can't play it)"; + case EC_INVALID_PLUGIN_ID: + return "Used an invalid plugin ID"; + default: + return "Unknown error code"; + } } From 79c833824d504fb6f8695280cfac0e74be07d2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Wed, 15 Jul 2020 22:12:48 +0200 Subject: [PATCH 063/104] Add missing zeus functionality --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index cfc0f889d..48ad884b4 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -111,6 +111,10 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } } + if (!this->getVAD() && (speakingType_ == acre::Speaking::direct)) { + this->microphoneOpen(true); + } + if (stopDirectSpeaking) { CEngine::getInstance()->localStopSpeaking(); } From 3ce84d4d378c1aa5c81058f0a9b4fe09a48fa678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Wed, 15 Jul 2020 22:39:40 +0200 Subject: [PATCH 064/104] LOG to TRACE --- extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp | 2 +- extensions/src/ACRE2Mumble/MumbleClient.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index fe3489ae9..ba47450f2 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -9,7 +9,7 @@ // Mumble Speaking callbacks // void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t status) { - LOG("mumble_onUserTalkingStateChanged ENTER: %d", status); + TRACE("mumble_onUserTalkingStateChanged ENTER: %d", status); if (static_cast(userID) != CEngine::getInstance()->getSelf()->getId()) { return; } diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 48ad884b4..fc756850a 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -237,7 +237,7 @@ acre::Result CMumbleClient::unMuteAll(void) { } acre::Result CMumbleClient::moveToServerChannel() { - LOG("moveToServerChannel ENTER"); + TRACE("moveToServerChannel ENTER"); if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { mumble_userid_t clientId; std::vector details = getChannelDetails(); @@ -267,7 +267,7 @@ acre::Result CMumbleClient::moveToServerChannel() { } acre::Result CMumbleClient::moveToPreviousChannel() { - LOG("moveToPreviousChannel ENTER"); + TRACE("moveToPreviousChannel ENTER"); if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { mumble_userid_t clientId = -1; @@ -288,7 +288,7 @@ acre::Result CMumbleClient::moveToPreviousChannel() { } uint64_t CMumbleClient::findChannelByNames(std::vector details_) { - LOG("findChannelByNames ENTER"); + TRACE("findChannelByNames ENTER"); mumble_channelid_t *channelList = nullptr; std::size_t channelCount = 0U; From f3975b8e300129af1faa404aa650d57ad2af073b Mon Sep 17 00:00:00 2001 From: jonpas Date: Thu, 16 Jul 2020 14:21:18 +0200 Subject: [PATCH 065/104] v2.7.4.1031 --- addons/main/script_version.hpp | 2 +- extensions/src/ACRE2Shared/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index 3f6d38417..b0f55a227 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 2 #define MINOR 7 #define PATCHLVL 4 -#define BUILD 1030 +#define BUILD 1031 diff --git a/extensions/src/ACRE2Shared/version.h b/extensions/src/ACRE2Shared/version.h index b572beed3..4a0d9efe5 100644 --- a/extensions/src/ACRE2Shared/version.h +++ b/extensions/src/ACRE2Shared/version.h @@ -1,4 +1,4 @@ #define ACRE_VERSION_MAJOR 2 #define ACRE_VERSION_MINOR 7 #define ACRE_VERSION_SUBMINOR 4 -#define ACRE_VERSION_BUILD 1030 +#define ACRE_VERSION_BUILD 1031 From e048fdc8f27c73dffe0cbd52ea873e77f8a0e827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferran=20Ob=C3=B3n?= Date: Thu, 16 Jul 2020 22:57:16 +0200 Subject: [PATCH 066/104] Cleanup --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 25 +++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index fc756850a..c98057a0b 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -86,6 +86,9 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType_, std::string radioId_) { bool stopDirectSpeaking = false; + const bool VADactive = this->getVAD(); + const std::int32_t speakingState = this->getSpeakingState(); + /* Open or close the microphone. If the microphone is still active, stop direct speaking before * starting the new PTT method: radio speaking. In theory this would not be needed for intercom since * at the moment it is a direct speak with audio effect. However, it is planned to have intercoms converted @@ -99,19 +102,18 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType this->setIntercomPTTDown(true); } - if (!this->getVAD()) { + if (!VADactive) { if (!this->getDirectFirst()) { this->microphoneOpen(true); } else { stopDirectSpeaking = true; } - } else if (this->getVAD() && - (this->getSpeakingState() != TalkingState::PASSIVE && this->getSpeakingState() != TalkingState::INVALID)) { + } else if (VADactive && (speakingState != TalkingState::PASSIVE) && (speakingState != TalkingState::INVALID)) { stopDirectSpeaking = true; } } - if (!this->getVAD() && (speakingType_ == acre::Speaking::direct)) { + if (!VADactive && (speakingType_ == acre::Speaking::direct)) { this->microphoneOpen(true); } @@ -124,9 +126,11 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_) { bool resendDirectSpeaking = false; + + const bool VADactive = this->getVAD(); switch (speakingType_) { case acre::Speaking::direct: - if (!this->getVAD()) { + if (!VADactive) { this->microphoneOpen(false); } break; @@ -145,7 +149,7 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ } if (this->getOnRadio()) { - if (!this->getVAD()) { + if (!VADactive) { if ((speakingType_ == acre::Speaking::radio) && this->getDirectFirst()) { this->setOnRadio(false); resendDirectSpeaking = true; @@ -158,18 +162,21 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ } } else { this->setOnRadio(false); - if (this->getSpeakingState() == 1) { + const std::int32_t speakingState = this->getSpeakingState(); + + if ((speakingState != TalkingState::PASSIVE) && (speakingState != TalkingState::INVALID)) { resendDirectSpeaking = true; } } } else if (speakingType_ == acre::Speaking::intercom) { - if (!this->getVAD()) { + const std::int32_t speakingState = this->getSpeakingState(); + if (!VADactive) { if (!CEngine::getInstance()->getClient()->getIntercomPTTDown()) { this->microphoneOpen(false); } else { resendDirectSpeaking = true; } - } else if (this->getSpeakingState() == 1) { + } else if ((speakingState != TalkingState::PASSIVE) && (speakingState != TalkingState::INVALID)) { resendDirectSpeaking = true; } } From a023131f7cfe9cf1b675303dd43af9161e5a8a74 Mon Sep 17 00:00:00 2001 From: jonpas Date: Mon, 3 Aug 2020 21:41:33 +0200 Subject: [PATCH 067/104] Temporarily disable Zeus PTT functionality (workaround 'stuck PTT' bug) --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index c98057a0b..275d47846 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -113,9 +113,10 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } } - if (!VADactive && (speakingType_ == acre::Speaking::direct)) { + // TODO Fix - mumble_onUserTalkingStateChanged stops being thrown after microphoneOpen(true) + /*if (!VADactive && (speakingType_ == acre::Speaking::direct)) { this->microphoneOpen(true); - } + }*/ if (stopDirectSpeaking) { CEngine::getInstance()->localStopSpeaking(); From 98e6e0a74c959797819f8d04488034713685a142 Mon Sep 17 00:00:00 2001 From: jonpas Date: Tue, 4 Aug 2020 22:42:48 +0200 Subject: [PATCH 068/104] Fix stuck PTT bug properly (new speaking type 'god') --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 275d47846..a6833e05c 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -113,10 +113,9 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } } - // TODO Fix - mumble_onUserTalkingStateChanged stops being thrown after microphoneOpen(true) - /*if (!VADactive && (speakingType_ == acre::Speaking::direct)) { + if ((speakingType_ == acre::Speaking::god) && !VADactive) { this->microphoneOpen(true); - }*/ + } if (stopDirectSpeaking) { CEngine::getInstance()->localStopSpeaking(); @@ -131,6 +130,8 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ const bool VADactive = this->getVAD(); switch (speakingType_) { case acre::Speaking::direct: + break; + case acre::Speaking::god: if (!VADactive) { this->microphoneOpen(false); } From 2f5d53c881fb56afcb418ee4862f03dd4675b804 Mon Sep 17 00:00:00 2001 From: jonpas Date: Tue, 4 Aug 2020 22:44:31 +0200 Subject: [PATCH 069/104] v2.7.4.1033 --- addons/main/script_version.hpp | 2 +- extensions/src/ACRE2Shared/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index e2faca15b..4996d9706 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 2 #define MINOR 7 #define PATCHLVL 4 -#define BUILD 1032 +#define BUILD 1033 diff --git a/extensions/src/ACRE2Shared/version.h b/extensions/src/ACRE2Shared/version.h index 094037579..2f230bcbf 100644 --- a/extensions/src/ACRE2Shared/version.h +++ b/extensions/src/ACRE2Shared/version.h @@ -1,4 +1,4 @@ #define ACRE_VERSION_MAJOR 2 #define ACRE_VERSION_MINOR 7 #define ACRE_VERSION_SUBMINOR 4 -#define ACRE_VERSION_BUILD 1032 +#define ACRE_VERSION_BUILD 1033 From 157e3fff60ca31582857bc99ad521c1d8872c5c4 Mon Sep 17 00:00:00 2001 From: jonpas Date: Wed, 5 Aug 2020 23:52:14 +0200 Subject: [PATCH 070/104] Fix Zeus speaking using wrong speaking type --- extensions/src/ACRE2Core/startZeusSpeaking.h | 2 +- extensions/src/ACRE2Core/stopZeusSpeaking.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/src/ACRE2Core/startZeusSpeaking.h b/extensions/src/ACRE2Core/startZeusSpeaking.h index 444252538..7fce8342e 100644 --- a/extensions/src/ACRE2Core/startZeusSpeaking.h +++ b/extensions/src/ACRE2Core/startZeusSpeaking.h @@ -13,7 +13,7 @@ RPC_FUNCTION(startZeusSpeaking) { - CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::direct); + CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::god); return acre::Result::ok; } diff --git a/extensions/src/ACRE2Core/stopZeusSpeaking.h b/extensions/src/ACRE2Core/stopZeusSpeaking.h index 8c1561640..b30fef1a8 100644 --- a/extensions/src/ACRE2Core/stopZeusSpeaking.h +++ b/extensions/src/ACRE2Core/stopZeusSpeaking.h @@ -13,7 +13,7 @@ RPC_FUNCTION(stopZeusSpeaking) { - CEngine::getInstance()->getClient()->localStopSpeaking(acre::Speaking::direct); + CEngine::getInstance()->getClient()->localStopSpeaking(acre::Speaking::god); return acre::Result::ok; } From 2512ad6bda218bba7cee5fe19fdf927ddc2c6ccc Mon Sep 17 00:00:00 2001 From: jonpas Date: Fri, 14 Aug 2020 00:33:39 +0200 Subject: [PATCH 071/104] Newer ts3id to voipId --- addons/sys_godmode/XEH_postInit.sqf | 2 +- addons/sys_godmode/fnc_handlePttKeyPress.sqf | 2 +- addons/sys_godmode/fnc_handlePttKeyPressUp.sqf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/sys_godmode/XEH_postInit.sqf b/addons/sys_godmode/XEH_postInit.sqf index e39ed3061..641a53169 100644 --- a/addons/sys_godmode/XEH_postInit.sqf +++ b/addons/sys_godmode/XEH_postInit.sqf @@ -8,7 +8,7 @@ if (!hasInterface) exitWith {}; params ["_speakingId", "_speakingName", "_channel", "_channelEx"]; #ifndef ALLOW_SELF_RX - if (_speakingId == EGVAR(sys_core,ts3id)) exitWith {}; + if (_speakingId == EGVAR(sys_core,voipId)) exitWith {}; #endif GVAR(speakingGods) pushBackUnique _speakingId; diff --git a/addons/sys_godmode/fnc_handlePttKeyPress.sqf b/addons/sys_godmode/fnc_handlePttKeyPress.sqf index 039761d72..3f8a96c62 100644 --- a/addons/sys_godmode/fnc_handlePttKeyPress.sqf +++ b/addons/sys_godmode/fnc_handlePttKeyPress.sqf @@ -79,7 +79,7 @@ GVAR(targetUnits) = GVAR(targetUnits) apply { }; }; -[QGVAR(startSpeaking), [EGVAR(sys_core,ts3id), profileName, _channel, _channelEx], GVAR(targetUnits)] call CBA_fnc_targetEvent; +[QGVAR(startSpeaking), [EGVAR(sys_core,voipId), profileName, _channel, _channelEx], GVAR(targetUnits)] call CBA_fnc_targetEvent; ["startGodModeSpeaking", ""] call EFUNC(sys_rpc,callRemoteProcedure); diff --git a/addons/sys_godmode/fnc_handlePttKeyPressUp.sqf b/addons/sys_godmode/fnc_handlePttKeyPressUp.sqf index 29e207573..8e2e2e749 100644 --- a/addons/sys_godmode/fnc_handlePttKeyPressUp.sqf +++ b/addons/sys_godmode/fnc_handlePttKeyPressUp.sqf @@ -19,7 +19,7 @@ params ["_group"]; if !([_group] call FUNC(accessAllowed)) exitWith { false }; -[QGVAR(stopSpeaking), [EGVAR(sys_core,ts3id)], GVAR(targetUnits)] call CBA_fnc_targetEvent; +[QGVAR(stopSpeaking), [EGVAR(sys_core,voipId)], GVAR(targetUnits)] call CBA_fnc_targetEvent; GVAR(targetUnits) = []; ["stopGodModeSpeaking", ""] call EFUNC(sys_rpc,callRemoteProcedure); From 5cd75f5344a82304e28d371b0c308761839802db Mon Sep 17 00:00:00 2001 From: jonpas Date: Fri, 14 Aug 2020 00:38:32 +0200 Subject: [PATCH 072/104] Bring Mumble plugin up-to-date --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index a6833e05c..a9b9bf7dd 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -113,8 +113,10 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } } - if ((speakingType_ == acre::Speaking::god) && !VADactive) { - this->microphoneOpen(true); + if ((speakingType_ == acre::Speaking::god) || (speakingType_ == acre::Speaking::zeus)) { + if (!VADactive) { + this->microphoneOpen(true); + } } if (stopDirectSpeaking) { @@ -132,6 +134,8 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ case acre::Speaking::direct: break; case acre::Speaking::god: + [[fallthrough]]; + case acre::Speaking::zeus: if (!VADactive) { this->microphoneOpen(false); } From f5ad9b1c61de9b46b7f40e125753880b93e05538 Mon Sep 17 00:00:00 2001 From: jonpas Date: Mon, 17 Aug 2020 12:09:13 +0200 Subject: [PATCH 073/104] v2.7.4.1035 --- addons/main/script_version.hpp | 2 +- extensions/src/ACRE2Shared/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index f4bee6c0d..6316a7983 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 2 #define MINOR 7 #define PATCHLVL 4 -#define BUILD 1034 +#define BUILD 1035 diff --git a/extensions/src/ACRE2Shared/version.h b/extensions/src/ACRE2Shared/version.h index 4743b485d..aa2b377af 100644 --- a/extensions/src/ACRE2Shared/version.h +++ b/extensions/src/ACRE2Shared/version.h @@ -1,4 +1,4 @@ #define ACRE_VERSION_MAJOR 2 #define ACRE_VERSION_MINOR 7 #define ACRE_VERSION_SUBMINOR 4 -#define ACRE_VERSION_BUILD 1034 +#define ACRE_VERSION_BUILD 1035 From 29f9684925127e33d4dba2ec292ba335f263b65f Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 23 May 2021 19:02:22 +0200 Subject: [PATCH 074/104] WIP: Update to latest Mumble API spec --- .../MumbleCallbacks_channelEvents.cpp | 2 +- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 21 +- .../MumbleCallbacks_pluginEvents.cpp | 3 +- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 9 +- .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 1 + .../ACRE2Mumble/MumbleCallbacks_static.cpp | 17 +- extensions/src/ACRE2Mumble/MumbleClient.cpp | 8 +- .../src/ACRE2Mumble/MumbleCommandServer.cpp | 2 +- .../src/ACRE2Mumble/MumbleCommandServer.h | 6 +- extensions/src/ACRE2Mumble/MumbleFunctions.h | 4 +- .../ACRE2Mumble/mumble_includes/MumbleAPI.h | 237 -------- .../mumble_includes/MumbleAPI_v_1_0_x.h | 530 ++++++++++++++++++ .../mumble_includes/MumblePlugin.h | 354 ------------ .../mumble_includes/MumblePlugin_v_1_0_x.h | 428 ++++++++++++++ .../mumble_includes/PluginComponents.h | 313 ----------- .../PluginComponents_v_1_0_x.h | 401 +++++++++++++ 16 files changed, 1403 insertions(+), 933 deletions(-) delete mode 100644 extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h create mode 100644 extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h delete mode 100644 extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h create mode 100644 extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_0_x.h delete mode 100644 extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h create mode 100644 extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp index 4979c24fa..de6f63beb 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp @@ -5,7 +5,7 @@ #include "Types.h" #include "compat.h" -extern MumbleAPI mumAPI; +extern MumbleAPI_v_1_0_x mumAPI; extern mumble_connection_t activeConnection; extern plugin_id_t pluginID; diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 1e64d694b..5c9b47fb2 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -9,20 +9,17 @@ #define FROM_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_fromTS" #define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toTS" -extern MumbleAPI mumAPI; +extern MumbleAPI_v_1_0_x mumAPI; +// TODO: Should these special values be a named variable? mumble_connection_t activeConnection = -1; plugin_id_t pluginID = -1; -void mumble_registerPluginID(plugin_id_t id) { - pluginID = id; -} - uint32_t mumble_getFeatures() { return FEATURE_AUDIO; } -void mumble_registerAPIFunctions(struct MumbleAPI api) { - mumAPI = api; +void mumble_registerAPIFunctions(void *apiStruct) { + mumAPI = MUMBLE_API_CAST(apiStruct); CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); if (CEngine::getInstance() != NULL) { if (((CMumbleCommandServer *) CEngine::getInstance()->getExternalServer()) != NULL) { @@ -38,10 +35,11 @@ void mumble_registerAPIFunctions(struct MumbleAPI api) { } } -mumble_error_t mumble_init(mumble_connection_t connection) { - if (connection != -1) { - activeConnection = connection; - } +mumble_error_t mumble_init(mumble_plugin_id_t id) { + pluginID = id; + + // TODO: Is initializing the active server connection required at this point? + // If so it must be done via an API call return STATUS_OK; } @@ -51,6 +49,7 @@ void mumble_onServerSynchronized(mumble_connection_t connection) { // set ID on every new connection acre::id_t clientId = 0; + // TODO: Missing error handling of API call mumAPI.getLocalUserID(pluginID, activeConnection, (mumble_userid_t *) &clientId); CEngine::getInstance()->getSelf()->setId(clientId); CEngine::getInstance()->getExternalServer()->setId(clientId); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp index 730587eb8..f242f1456 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp @@ -6,8 +6,9 @@ // // Handle a command event // -bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, const char *dataID) { +bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const uint8_t *data, size_t dataLength, const char *dataID) { if ((dataLength > 0U) && CEngine::getInstance()->getExternalServer()) { + // TODO: Cast is probably unnecessary CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *) data, dataLength); return true; } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 4a38422a5..372a83a91 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -16,7 +16,10 @@ using LIMITER = std::numeric_limits; -bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID) { +bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, uint32_t sampleRate, bool isSpeech, mumble_userid_t userID) { + // TODO: Do you need this for something? + (void) sampleRate; + if (CEngine::getInstance()->getSoundSystemOverride()) { return false; } @@ -101,7 +104,9 @@ bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_ return true; } -bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount) { +bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, uint32_t sampleRate) { + (void) sampleRate; + if (CEngine::getInstance()->getSoundSystemOverride()) { return false; } diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index 9a743fe8d..043d95d7c 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -40,6 +40,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use return; } + // TODO: Is the TalkingState enum defined somewhere in ACRE? 'cause it is not defined in Mumble if (status == TalkingState::PASSIVE || status == TalkingState::INVALID) { if ((!CEngine::getInstance()->getClient()->getRadioPTTDown()) && (!CEngine::getInstance()->getClient()->getGodPTTDown()) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp index 531c0f89e..36ca681bf 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -11,14 +11,21 @@ #include "Log.h" -const char *mumble_getName() { - return ACRE_NAME; +struct MumbleStringWrapper mumble_getName() { + static const char *name = ACRE_NAME; + + MumbleStringWrapper wrapper; + wrapper.data = name; + wrapper.size = strlen(name); + wrapper.needsReleasing = false; + + return wrapper; } -version_t mumble_getAPIVersion() { +mumble_version_t mumble_getAPIVersion() { return MUMBLE_PLUGIN_API_VERSION; } -version_t mumble_getVersion() { - return version_t{ACRE_VERSION_MAJOR, ACRE_VERSION_MINOR, ACRE_VERSION_SUBMINOR}; +mumble_version_t mumble_getVersion() { + return mumble_version_t{ACRE_VERSION_MAJOR, ACRE_VERSION_MINOR, ACRE_VERSION_SUBMINOR}; } diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 0f4a5148a..a3e5b74e0 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -13,9 +13,9 @@ static constexpr std::int32_t invalid_mumble_channel = -1; constexpr char default_mumble_channel[] = "ACRE"; -extern MumbleAPI mumAPI; +extern MumbleAPI_v_1_0_x mumAPI; extern mumble_connection_t activeConnection; -extern plugin_id_t pluginID; +extern mumble_plugin_id_t pluginID; acre::Result CMumbleClient::initialize() { setPreviousChannel(invalid_mumble_channel); @@ -71,12 +71,13 @@ acre::Result CMumbleClient::start(const acre::id_t id_) { } bool CMumbleClient::getVAD() { - transmission_mode_t transmitMode; + mumble_transmission_mode_t transmitMode; const mumble_error_t err = mumAPI.getLocalUserTransmissionMode(pluginID, &transmitMode); if (err != ErrorCode::EC_OK) { return false; } + // TODO: Is this enum defined somewhere in ACRE? return transmitMode == TransmissionMode::TM_VOICE_ACTIVATION; } @@ -324,6 +325,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { char *channelName = nullptr; if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == STATUS_OK) { + // TODO: Does std::string take care of deleting the allocated name? std::string channelNameString(channelName); if (channelNameString.find(default_mumble_channel) != -1 || (!details_.at(0).empty() && channelNameString == name)) { if (channelNameString == default_mumble_channel) { diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index 8de2c5c18..f033b38c6 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -39,7 +39,7 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg) { return acre::Result::error; } - err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const char *) msg->getData(), msg->getLength(), "ACRE2"); + err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const uint8_t *) msg->getData(), msg->getLength(), "ACRE2"); if (err != ErrorCode::EC_OK) { LOG("ERROR, UNABLE TO SEND MESSAGE DATA: %d", err); return acre::Result::error; diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.h b/extensions/src/ACRE2Mumble/MumbleCommandServer.h index 828344662..f34a4a110 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.h +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.h @@ -24,8 +24,8 @@ class CMumbleCommandServer : public IServer, public CLockable { acre::Result release(void) final; - inline void setCommandId(plugin_id_t value) noexcept { m_commandId = value; } - inline plugin_id_t getCommandId() const noexcept { return m_commandId; } + inline void setCommandId(mumble_plugin_id_t value) noexcept { m_commandId = value; } + inline mumble_plugin_id_t getCommandId() const noexcept { return m_commandId; } inline void setConnected(const bool value) final { m_connected = value; } inline bool getConnected() const final { return m_connected; } @@ -36,5 +36,5 @@ class CMumbleCommandServer : public IServer, public CLockable { private: acre::id_t m_id; bool m_connected; - plugin_id_t m_commandId; + mumble_plugin_id_t m_commandId; }; diff --git a/extensions/src/ACRE2Mumble/MumbleFunctions.h b/extensions/src/ACRE2Mumble/MumbleFunctions.h index d51907a77..9a7725877 100644 --- a/extensions/src/ACRE2Mumble/MumbleFunctions.h +++ b/extensions/src/ACRE2Mumble/MumbleFunctions.h @@ -1,4 +1,4 @@ #pragma once -#include "MumbleAPI.h" -#include "MumblePlugin.h" +#include "MumbleAPI_v_1_0_x.h" +#include "MumblePlugin_v_1_0_x.h" diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h deleted file mode 100644 index 1ef62eaa6..000000000 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI.h +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2019-2020 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -/// This header file contains the definition of Mumble's API - -#ifndef MUMBLE_PLUGIN_API_H_ -#define MUMBLE_PLUGIN_API_H_ - -#include "PluginComponents.h" -#include - -// API version -const int32_t MUMBLE_PLUGIN_API_MAJOR = 1; -const int32_t MUMBLE_PLUGIN_API_MINOR = 0; -const int32_t MUMBLE_PLUGIN_API_PATCH = 0; -const version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PLUGIN_API_MINOR, MUMBLE_PLUGIN_API_PATCH }; - - -struct MumbleAPI { - // -------- Memory management -------- - - /// Frees the given pointer. - /// - /// @param callerID The ID of the plugin calling this function - /// @param pointer The pointer to free - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *freeMemory)(plugin_id_t callerID, void *pointer); - - - - // -------- Getter functions -------- - - /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] connection A pointer to the memory location the ID should be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access the - /// value of the provided pointer - mumble_error_t (PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(plugin_id_t callerID, mumble_connection_t *connection); - - /// Fills in the information about the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserID)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID); - - /// Fills in the information about the given user's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The user's ID whose name should be obtained - /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getUserName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, char **userName); - - /// Fills in the information about the given channel's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The channel's ID whose name should be obtained - /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelName)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, char **channelName); - - /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the out-parameter - /// will prevent that property to be set/allocated. If you are only interested in the user count you can thus pass nullptr as the - /// users parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllUsers)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users, - size_t *userCount); - - /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent - /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as the - /// channels parameter and save time on allocating + freeing the channels-array while still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getAllChannels)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t **channels, size_t *channelCount); - - /// Gets the ID of the channel the given user is currently connected to. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the ID of the channel shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getChannelOfUser)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t *channel); - - /// Gets an array of all users in the specified channel. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The ID of the channel whose users shall be retrieved - /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated memory has - /// to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if this function - /// returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getUsersInChannel)(plugin_id_t callerID, mumble_connection_t connection, - mumble_channelid_t channelID, mumble_userid_t **userList, size_t *userCount); - - /// Gets the current transmission mode of the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t (PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t *transmissionMode); - - - - // -------- Request functions -------- - - /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily set - /// the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the work of - /// restoring the previous state afterwards. - /// - /// @param callerID The ID of the plugin calling this function - /// @param transmissionMode The requested transmission mode - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)(plugin_id_t callerID, transmission_mode_t transmissionMode); - - /// Requests Mumble to move the given user into the given channel - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param channelID The ID of the channel to move the user to - /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target channel does not require a - /// password for entering - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestUserMove)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t channelID, const char *password); - - /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user had chosen - /// the continous transmission mode). If a plugin requests this overwrite, it is responsible for deactivating the overwrite again - /// once it is no longer required - /// - /// @param callerID The ID of the plugin calling this function - /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(plugin_id_t callerID, bool activate); - - - - // -------- Find functions -------- - - /// Fills in the information about a user with the specified name, if such a user exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userName The respective user's name - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t (PLUGIN_CALLING_CONVENTION *findUserByName)(plugin_id_t callerID, mumble_connection_t connection, const char *userName, - mumble_userid_t *userID); - - /// Fills in the information about a channel with the specified name, if such a channel exists. The search is case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelName The respective channel's name - /// @param[out] channelID A pointer to the memory the channel's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t (PLUGIN_CALLING_CONVENTION *findChannelByName)(plugin_id_t callerID, mumble_connection_t connection, - const char *channelName, mumble_channelid_t *channelID); - - - - // -------- Miscellaneous -------- - - /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin active - /// on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the sent data - /// must not contain sensitive information or anything else that shouldn't be known by others. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to send the data through (the server the given users are on) - /// @param users An array of user IDs to send the data to - /// @param userCount The size of the provided user-array - /// @param data The data that shall be sent as a String - /// @param dataLength The length of the data-string - /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do with - /// the data - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *sendData)(plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *users, - size_t userCount, const char *data, size_t dataLength, const char *dataID); - - /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. - /// - /// @param callerID The ID of the plugin calling this function - /// @param message The message to log - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *log)(plugin_id_t callerID, const char *message); - - /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported by it - /// in order for this to work out (see http://www.mega-nerd.com/libsndfile/). - /// - /// @param callerID The ID of the plugin calling this function - /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t (PLUGIN_CALLING_CONVENTION *playSample)(plugin_id_t callerID, const char *samplePath); -}; - -#endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h new file mode 100644 index 000000000..2e0a79466 --- /dev/null +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h @@ -0,0 +1,530 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file contains the definition of Mumble's API + +#ifndef MUMBLE_PLUGIN_API_H_ +#define MUMBLE_PLUGIN_API_H_ + +#include "PluginComponents_v_1_0_x.h" +#include + + +// API version +#define MUMBLE_PLUGIN_API_MAJOR_MACRO 1 +#define MUMBLE_PLUGIN_API_MINOR_MACRO 0 +#define MUMBLE_PLUGIN_API_PATCH_MACRO 0 + +constexpr int32_t MUMBLE_PLUGIN_API_MAJOR = MUMBLE_PLUGIN_API_MAJOR_MACRO; +constexpr int32_t MUMBLE_PLUGIN_API_MINOR = MUMBLE_PLUGIN_API_MINOR_MACRO; +constexpr int32_t MUMBLE_PLUGIN_API_PATCH = MUMBLE_PLUGIN_API_PATCH_MACRO; +const mumble_version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PLUGIN_API_MINOR, + MUMBLE_PLUGIN_API_PATCH }; + +// Create macro for casting the pointer to the API object to the proper struct. +// Note that this must only be used if the API uses MUMBLE_PLUGIN_API_VERSION of the API. +#define MUMBLE_CONCAT_HELPER(a, b) a##_##b +#define MUMBLE_CONCAT(a, b) MUMBLE_CONCAT_HELPER(a, b) +#define MUMBLE_API_STRUCT \ + MUMBLE_CONCAT(MumbleAPI_v, \ + MUMBLE_CONCAT(MUMBLE_PLUGIN_API_MAJOR_MACRO, MUMBLE_CONCAT(MUMBLE_PLUGIN_API_MINOR_MACRO, x))) +#define MUMBLE_API_CAST(ptrName) (*((struct MUMBLE_API_STRUCT *) ptrName)) + + +struct MumbleAPI_v_1_0_x { + ///////////////////////////////////////////////////////// + ////////////////////// GENERAL NOTES //////////////////// + ///////////////////////////////////////////////////////// + // + // All functions that take in a connection as a paremeter may only be called **after** the connection + // has finished synchronizing. The only exception from this is isConnectionSynchronized. + // + // Strings returned by the API are UTF-8 encoded + // Strings passed to the API are expected to be UTF-8 encoded + // + // All API functions are synchronized and will be executed in Mumble's "main thread" from which most plugin + // callbacks are called as well. Note however that an API call is BLOCKING if invoked from a different + // thread. This means that they can cause deadlocks if used without caution. An example that will lead + // to a deadlock is: + // - plugin callback gets called from the main thread + // - callback messages a separate thread to do something and waits for the action to have completed + // - Separate thread calls an API function + // - The function blocks and waits to be executed in the main thread which is currently blocked waiting + // - deadlock + + + // -------- Memory management -------- + + /// Frees the given pointer. + /// + /// @param callerID The ID of the plugin calling this function + /// @param pointer The pointer to free + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *freeMemory)(mumble_plugin_id_t callerID, const void *pointer); + + + + // -------- Getter functions -------- + + /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] connection A pointer to the memory location the ID should be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access + /// the value of the provided pointer + mumble_error_t(PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(mumble_plugin_id_t callerID, + mumble_connection_t *connection); + + /// Checks whether the given connection has finished initializing yet. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished + /// synchronization yet after this function has executed successfully. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *isConnectionSynchronized)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + bool *synchronized); + + /// Fills in the information about the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getLocalUserID)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t *userID); + + /// Fills in the information about the given user's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The user's ID whose name should be obtained + /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. + /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getUserName)(mumble_plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, const char **userName); + + /// Fills in the information about the given channel's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The channel's ID whose name should be obtained + /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. + /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getChannelName)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_channelid_t channelID, const char **channelName); + + /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the + /// out-parameter will prevent that property to be set/allocated. If you are only interested in the user count you + /// can thus pass nullptr as the users parameter and save time on allocating + freeing the channels-array while + /// still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getAllUsers)(mumble_plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t **users, size_t *userCount); + + /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent + /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as + /// the channels parameter and save time on allocating + freeing the channels-array while still getting the size + /// out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getAllChannels)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_channelid_t **channels, size_t *channelCount); + + /// Gets the ID of the channel the given user is currently connected to. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the ID of the channel shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getChannelOfUser)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t *channel); + + /// Gets an array of all users in the specified channel. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The ID of the channel whose users shall be retrieved + /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated + /// memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if + /// this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getUsersInChannel)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_channelid_t channelID, + mumble_userid_t **userList, size_t *userCount); + + /// Gets the current transmission mode of the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)( + mumble_plugin_id_t callerID, mumble_transmission_mode_t *transmissionMode); + + /// Checks whether the given user is currently locally muted. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to check for + /// @param[out] muted A pointer to where the local mute state of that user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *isUserLocallyMuted)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_userid_t userID, bool *muted); + + /// Checks whether the local user is currently muted. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] muted A pointer to where the mute state of the local user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *isLocalUserMuted)(mumble_plugin_id_t callerID, bool *muted); + + /// Checks whether the local user is currently deafened. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] deafened A pointer to where the deaf state of the local user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *isLocalUserDeafened)(mumble_plugin_id_t callerID, bool *deafened); + + /// Gets the hash of the given user (can be used to recognize users between restarts) + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] hash A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getUserHash)(mumble_plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, const char **hash); + + /// Gets the hash of the server for the given connection (can be used to recognize servers between restarts) + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection + /// @param[out] hash A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getServerHash)(mumble_plugin_id_t callerID, + mumble_connection_t connection, const char **hash); + + /// Gets the comment of the given user. Note that a user might have a comment configured that hasn't been + /// synchronized to this client yet. In this case this function will return EC_UNSYNCHRONIZED_BLOB. As of now there + /// is now way to request the synchronization to happen via the Plugin-API. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection + /// @param userID the ID of the user whose comment should be obtained + /// @param[out] comment A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getUserComment)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t userID, + const char **comment); + + /// Gets the description of the given channel. Note that a channel might have a description configured that hasn't + /// been synchronized to this client yet. In this case this function will return EC_UNSYNCHRONIZED_BLOB. As of now + /// there is now way to request the synchronization to happen via the Plugin-API. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection + /// @param channelID the ID of the channel whose comment should be obtained + /// @param[out] description A pointer to where the pointer to the allocated string (C-encoded) should be written to. + /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *getChannelDescription)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_channelid_t channelID, + const char **description); + + + // -------- Request functions -------- + + /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily + /// set the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the + /// work of restoring the previous state afterwards. + /// + /// @param callerID The ID of the plugin calling this function + /// @param transmissionMode The requested transmission mode + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)( + mumble_plugin_id_t callerID, mumble_transmission_mode_t transmissionMode); + + /// Requests Mumble to move the given user into the given channel + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param channelID The ID of the channel to move the user to + /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target + /// channel does not require a password for entering + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *requestUserMove)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t channelID, const char *password); + + /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user + /// had chosen the continous transmission mode). If a plugin requests this overwrite, it is responsible for + /// deactivating the overwrite again once it is no longer required + /// + /// @param callerID The ID of the plugin calling this function + /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(mumble_plugin_id_t callerID, + bool activate); + + /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute + /// state opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client + /// has muted its microphone and thus isn't transmitting any audio). Furthermore it must be noted that muting the + /// local user with this function does not work (it doesn't make sense). If you try to do so, this function will + /// fail. In order to make this work, this function will also fail if the server has not finished synchronizing with + /// the client yet. For muting the local user, use requestLocalUserMute instead. + /// + /// @param callerID The ID of the plugin calling this function. + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be muted + /// @param muted Whether to locally mute the given client (opposed to unmuting it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *requestLocalMute)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t userID, + bool muted); + + /// Requests Mumble to set the mute state of the local user. In the UI this is referred to as "self-mute". + /// + /// @param callerID The ID of the plugin calling this function. + /// @param muted Whether to locally mute the local user (opposed to unmuting it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *requestLocalUserMute)(mumble_plugin_id_t callerID, bool muted); + + /// Requests Mumble to set the deaf state of the local user. In the UI this is referred to as "self-deaf". + /// + /// @param callerID The ID of the plugin calling this function. + /// @param deafened Whether to locally deafen the local user (opposed to undeafening it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *requestLocalUserDeaf)(mumble_plugin_id_t callerID, bool deafened); + + /// Sets the comment of the local user + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection + /// @param comment The new comment to use (C-encoded). A subset of HTML formatting is supported. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION *requestSetLocalUserComment)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + const char *comment); + + + + // -------- Find functions -------- + + /// Fills in the information about a user with the specified name, if such a user exists. The search is + /// case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userName The respective user's name + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION *findUserByName)(mumble_plugin_id_t callerID, + mumble_connection_t connection, const char *userName, + mumble_userid_t *userID); + + /// Fills in the information about a channel with the specified name, if such a channel exists. The search is + /// case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelName The respective channel's name + /// @param[out] channelID A pointer to the memory the channel's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION *findChannelByName)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + const char *channelName, + mumble_channelid_t *channelID); + + + + // -------- Settings -------- + + /// Fills in the current value of the setting with the given key. Note that this function can only be used for + /// settings whose value is a bool! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param[out] outValue A pointer to the memory the setting's value shall be written to. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION *getMumbleSetting_bool)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, bool *outValue); + + /// Fills in the current value of the setting with the given key. Note that this function can only be used for + /// settings whose value is an int! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param[out] outValue A pointer to the memory the setting's value shall be written to. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION *getMumbleSetting_int)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, int64_t *outValue); + + /// Fills in the current value of the setting with the given key. Note that this function can only be used for + /// settings whose value is a double! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param[out] outValue A pointer to the memory the setting's value shall be written to. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION *getMumbleSetting_double)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, double *outValue); + + /// Fills in the current value of the setting with the given key. Note that this function can only be used for + /// settings whose value is a String! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param[out] outValue The memory address to which the pointer to the setting's value (the String) will be + /// written. The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will + /// only be allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION *getMumbleSetting_string)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, + const char **outValue); + + + /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose + /// value is a bool! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param value The value that should be set for the given setting + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *setMumbleSetting_bool)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, bool value); + + /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose + /// value is an int! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param value The value that should be set for the given setting + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *setMumbleSetting_int)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, int64_t value); + + /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose + /// value is a double! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param value The value that should be set for the given setting + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *setMumbleSetting_double)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, double value); + + /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose + /// value is a string! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param value The value that should be set for the given setting + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *setMumbleSetting_string)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, const char *value); + + + + // -------- Miscellaneous -------- + + /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin + /// active on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the + /// sent data must not contain sensitive information or anything else that shouldn't be known by others. + /// + /// NOTE: Messages sent via this API function are rate-limited by the server. If the rate-limit is hit, the message + /// will be dropped without an error message. The rate-limiting is global (e.g. it doesn't matter which plugin sent + /// the respective messages - they all count to the same limit). + /// Therefore if you have multiple messages to send, you should consider sending them asynchronously one at a time + /// with a little delay in between (~1 second). + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to send the data through (the server the given users are on) + /// @param users An array of user IDs to send the data to + /// @param userCount The size of the provided user-array + /// @param data The data array that shall be sent. This can be an arbitrary sequence of bytes. Note that the size of + /// is restricted to <= 1KB. + /// @param dataLength The length of the data array + /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do + /// with the data. This has to be a C-encoded String. It is recommended that the ID starts with a plugin-specific + /// prefix in order to avoid name clashes. Note that the size of this string is restricted to <= 100 bytes. + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *sendData)(mumble_plugin_id_t callerID, mumble_connection_t connection, + const mumble_userid_t *users, size_t userCount, + const uint8_t *data, size_t dataLength, const char *dataID); + + /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. + /// + /// @param callerID The ID of the plugin calling this function + /// @param message The message to log + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *log)(mumble_plugin_id_t callerID, const char *message); + + /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported + /// by it in order for this to work out (see http://www.mega-nerd.com/libsndfile/). + /// + /// @param callerID The ID of the plugin calling this function + /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION *playSample)(mumble_plugin_id_t callerID, const char *samplePath); +}; + +#endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h deleted file mode 100644 index c6c82393d..000000000 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin.h +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2019-2020 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -/// This header file specifies the Mumble plugin interface - -#ifndef EXTERNAL_MUMBLE_PLUGIN_H_ -#define EXTERNAL_MUMBLE_PLUGIN_H_ - -#include "PluginComponents.h" -#include "MumbleAPI.h" -#include -#include -#include - -#if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems - #define PLUGIN_EXPORT __attribute__((visibility("default"))) -#elif defined(_MSC_VER) - #define PLUGIN_EXPORT __declspec(dllexport) -#elif defined(__MINGW32__) - #define PLUGIN_EXPORT __attribute__((dllexport)) -#else - #error No PLUGIN_EXPORT definition available -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Gets called right after loading the plugin in order to let the plugin initialize. - /// - /// @param connection The ID of the server-connection this event is connected to, or its default value. - /// @returns The status of the initialization. If everything went fine, return STATUS_OK - PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_connection_t connection); - - /// Gets called when unloading the plugin in order to allow it to clean up after itself. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); - - /// Gets the name of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will be copied - /// for further usage though. - /// - /// @returns A pointer to the plugin name (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getName(); - - /// Gets the Version of the plugin-API this plugin intends to use. - /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. - /// - /// @return The respective API Version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); - - /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used - /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use - /// of it at some point. - /// - /// @param api The MumbleAPI struct - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(struct MumbleAPI api); - - - - ////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Tells the plugin some basic information about the Mumble client loading it. - /// This function will be the first one that is being called on this plugin - even before it is decided whether to load - /// the plugin at all. - /// - /// @param mumbleVersion The Version of the Mumble client - /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with - /// @param minimalExpectedAPIVersion The minimal Version the Mumble clients expects this plugin to meet in order to load it - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(version_t mumbleVersion, version_t mumbleAPIVersion, version_t minimalExpectedAPIVersion); - - /// Gets the Version of this plugin - /// - /// @returns The plugin's version - PLUGIN_EXPORT version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); - - /// Gets the name of the plugin author(s). The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the author(s) name(s) (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getAuthor(); - - /// Gets the description of the plugin. The plugin has to guarantee that the returned pointer will still be valid. The string will - /// be copied for further usage though. - /// - /// @returns A pointer to the description (encoded as a C-String) - PLUGIN_EXPORT const char* PLUGIN_CALLING_CONVENTION mumble_getDescription(); - - /// Registers the ID of this plugin. This is the ID Mumble will reference this plugin with and by which this plugin - /// can identify itself when communicating with Mumble. - /// - /// @param id The ID for this plugin - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerPluginID(uint32_t id); - - /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the PluginFeature enum - /// together. - /// - /// @returns The feature set of this plugin - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); - - /// Requests this plugin to deactivate the given (sub)set of provided features. - /// If this is not possible, the features that can't be deactivated shall be returned by this function. - /// - /// Example (check if FEATURE_POSITIONAL shall be deactivated): - /// @code - /// if (features & FEATURE_POSITIONAL) { - /// // positional shall be deactivated - /// }; - /// @endcode - /// - /// @param features The feature set that shall be deactivated - /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return - /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. - PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); - - - - ////////////////////////////////////////////////////////////////////////////////// - //////////////////////////// POSITIONAL AUDIO //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - // If this plugin wants to provide positional audio, all functions of this category - // have to be implemented - - /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is currently - /// able to do so and allocate memory that is needed for that process. - /// As a parameter this function gets an array of names and an array of PIDs. They are of same length and the PID at index i - /// belongs to a program whose name is listed at index i in the "name-array". - /// - /// @param programNames An array of pointers to the program names - /// @param programPIDs An array of the corresponding program PIDs - /// @param programCount The length of programNames and programPIDs - /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start frequently - /// calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is (currently) - /// uncapable of providing positional data. In this case this function must not have allocated any memory that needs to be - /// cleaned up later on. Depending on the returned error code, Mumble might try to call this function again later on. - PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char **programNames, const uint64_t *programPIDs, size_t programCount); - - /// Retrieves the positional audio data. If no data can be fetched, set all float-vectors to 0 and return false. - /// - /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar ingame (where it - /// is facing). - /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to its head. One - /// unit represents one meter of distance. - /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. - /// One unit represents one meter of distance. - /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame (where it - /// is facing). - /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One unit - /// represents one meter of distance. - /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided positional data - /// shall be written. This context should include information about the server (and team) the player is on. Only players with identical - /// context will be able to hear each other's audio. The returned pointer has to remain valid until the next invokation of this function - /// or until shutdownPositionalData is called. - /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall be written. It can - /// be polled by external scripts from the server and should uniquely identify the player in the game. The pointer has to remain valid - /// until the next invokation of this function or until shutdownPositionalData is called. - /// @returns Whether this plugin can continue delivering positional data. If this function returns false, shutdownPositionalData will - /// be called. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, float *avatarAxis, float *cameraPos, float *cameraDir, - float *cameraAxis, const char **context, const char **identity); - - /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this purpose should - /// be freed at this point. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// Called when connecting to a server. - /// - /// @param connection The ID of the newly established server-connection - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); - - /// Called when disconnecting from a server. - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); - - /// Called when the client has finished synchronizing with the server - /// - /// @param connection The ID of the server-connection that has been terminated - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); - - /// Called whenever any user on the server enters a channel - /// This function will also be called when freshly connecting to a server as each user on that - /// server needs to be "added" to the respective channel as far as the local client is concerned. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user this event has been triggered for - /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no previous channel (e.g. the user - /// freshly connected to the server) or the channel isn't available because of any other reason. - /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be retrieved. This means - /// that the ID is invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID, - mumble_channelid_t newChannelID); - - /// Called whenever a user leaves a channel. - /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel anymore. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user that left the channel - /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. This means that the ID is - /// invalid. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID); - - /// Called when any user changes his/her talking state. - /// - /// @param connection The ID of the server-connection this event is connected to - /// @param userID The ID of the user whose talking state has been changed - /// @param talkingState The new TalkingState the user has switched to. - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t talkingState); - - /// Called whenever there is audio input. - /// - /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of background noise) - /// @returns Whether this callback has modified the audio input-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech); - - /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). - /// The provided audio buffer is the raw buffer without any processing applied to it yet. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) - /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is false, - /// the content of this parameter is unspecified and should not be accessed - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, bool isSpeech, mumble_userid_t userID); - - /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). - /// Note that this happens immediately before Mumble clips the audio buffer. - /// - /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. Its length - /// is sampleCount * channelCount. - /// @param sampleCount The amount of sample points per channel - /// @param channelCount The amount of channels in the audio - /// @returns Whether this callback has modified the audio output-array - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount); - - /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the - /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended - /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. - /// - /// @param connection The ID of the server-connection the data is coming from - /// @param sender The ID of the user whose client's plugin has sent the data - /// @param data The sent data represented as a string - /// @param dataLength The length of data - /// @param dataID The ID of this data - /// @return Whether the given data has been processed by this plugin - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const char *data, size_t dataLength, - const char *dataID); - - /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the server the - /// local user is on but also when the local user connects to a server other clients are already connected to (in this case this - /// method will be called for every client already on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been added - - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the - /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case this - /// method will be called for every client on that server). - /// - /// @param connection An object used to identify the current connection - /// @param userID The ID of the user that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, mumble_userid_t userID); - - /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server the local - /// user is on but also when the local user connects to a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been added - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the local - /// user is on but also when the local user disconnects from a server that contains channels other than the root-channel (in this case - /// this method will be called for ever non-root channel on that server). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been removed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial name is also - /// considered renaming). - /// - /// @param connection An object used to identify the current connection - /// @param channelID The ID of the channel that has been renamed - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID); - - /// Called when a key has been pressed or released while Mumble has keyboard focus. - /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard - /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to - /// enable that. - /// - /// @param keyCode The key code of the respective key. The character codes are defined - /// via the KeyCode enum. For printable 7-bit ASCII characters these codes conform - /// to the ASCII code-page with the only difference that case is not distinguished. Therefore - /// always the upper-case letter code will be used for letters. - /// @param wasPres Whether the respective key has been pressed (instead of released) - PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); - - - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - /// This function is used to determine whether the plugin can find an update for itself that is available for download. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @return Whether the plugin was able to find an update for itself - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); - - /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. - /// If the URL is too long for the provided buffer, it will have to be split up and be read chunk by chunk. Make sure - /// though that you don't forget about the trailing null byte. - /// - /// NOTE: This function may be called without the plugin being loaded - /// - /// @param buffer A pointer to the char buffer to write the UTF-8 encoded URL (as C-string) into - /// @param bufferSize The size of the buffer - /// @param offset The offset in the URL from which this functions should start writing it to the buffer - /// @param Whether the URL has been completely written into the buffer yet. If this is false, this function will be called - /// again with a modified offset until the URL has been completely transferred. - PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(char *buffer, uint16_t bufferSize, uint16_t offset); - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_0_x.h new file mode 100644 index 000000000..afb2eee3f --- /dev/null +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_0_x.h @@ -0,0 +1,428 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file specifies the Mumble plugin interface + +#ifndef EXTERNAL_MUMBLE_PLUGIN_H_ +#define EXTERNAL_MUMBLE_PLUGIN_H_ + +#include "MumbleAPI_v_1_0_x.h" +#include "PluginComponents_v_1_0_x.h" +#include +#include +#include + +#if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems +# define PLUGIN_EXPORT __attribute__((visibility("default"))) +#elif defined(_MSC_VER) +# define PLUGIN_EXPORT __declspec(dllexport) +#elif defined(__MINGW32__) +# define PLUGIN_EXPORT __attribute__((dllexport)) +#else +# error No PLUGIN_EXPORT definition available +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// + +/// Gets called right after loading the plugin in order to let the plugin initialize. +/// +/// Registers the ID of this plugin. +/// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with +/// and by which this plugin can identify itself when communicating with Mumble. +/// @returns The status of the initialization. If everything went fine, return STATUS_OK +PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_plugin_id_t id); + +/// Gets called when unloading the plugin in order to allow it to clean up after itself. +/// Note that it is still safe to call API functions from within this callback. +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); + +/// Gets the name of the plugin. +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @returns A String-wrapper containing the requested name +PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getName(); + +/// Gets the Version of the plugin-API this plugin intends to use. +/// Mumble will decide whether this plugin is loadable or not based on the return value of this function. +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @returns The respective API Version +PLUGIN_EXPORT mumble_version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); + +/// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used +/// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use +/// of it at some point. +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @param api A pointer to the MumbleAPI struct. The API struct must be cast to the version corresponding to the +/// user API version. If your plugin is e.g. using the 1.0.x API, then you have to cast this pointer to +/// MumbleAPI_v_1_0_x. Note also that you **must not store this pointer**. It will become invalid. Therefore +/// you have to copy the struct in order to use it later on. +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(void *apiStruct); + +/// Releases the resource pointed to by the given pointer. If the respective resource has been allocated before, +/// this would be the time to free/delete it. +/// The resources processed by this functions are only those that have been specifically allocated in order to return +/// them in one of the plugin functions to Mumble (e.g. the String returned by mumble_getName) and has nothing to do +/// with your plugin's internal resource management. +/// In short: Only resources passed from the plugin to Mumble via a return value may be processed by this function. +/// +/// NOTE1: This function may be called without the plugin being loaded +/// +/// NOTE2: that the pointer might be pointing to memory that had to be allocated without the plugin being loaded. +/// Therefore you should be very sure that there'll be another callback in which you want to free this memory, +/// should you decide to not do it here (which is hereby explicitly advised against). +/// +/// NOTE3: The pointer is const as Mumble won't mess with the memory allocated by the plugin (no modifications). +/// Nontheless this function is explicitly responsible for freeing the respective memory parts. If the memory has +/// been allocated using malloc(), it needs to be freed using free() which requires a const-cast. If however the +/// memory has been created using the new operator you have to cast the pointer back to its original type and then +/// use the delete operator on it (no const-cast necessary in this case). +/// See https://stackoverflow.com/questions/2819535/unable-to-free-const-pointers-in-c +/// and https://stackoverflow.com/questions/941832/is-it-safe-to-delete-a-void-pointer +/// +/// @param pointer The pointer to the memory that needs free-ing +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_releaseResource(const void *pointer); + + + +////////////////////////////////////////////////////////////////////////////////// +///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// + +/// Tells the plugin some basic information about the Mumble client loading it. +/// This function will be the first one that is being called on this plugin - even before it is decided whether to load +/// the plugin at all. +/// +/// @param mumbleVersion The Version of the Mumble client +/// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with +/// @param minimumExpectedAPIVersion The minimum Version the Mumble clients expects this plugin to meet in order to load +/// it +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(mumble_version_t mumbleVersion, + mumble_version_t mumbleAPIVersion, + mumble_version_t minimumExpectedAPIVersion); + +/// Gets the Version of this plugin +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @returns The plugin's version +PLUGIN_EXPORT mumble_version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); + +/// Gets the name of the plugin author(s). +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @returns A String-wrapper containing the requested author name(s) +PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getAuthor(); + +/// Gets the description of the plugin. +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @returns A String-wrapper containing the requested description +PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getDescription(); + +/// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the +/// Mumble_PluginFeature enum together. +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @returns The feature set of this plugin +PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); + +/// Requests this plugin to deactivate the given (sub)set of provided features. +/// If this is not possible, the features that can't be deactivated shall be returned by this function. +/// +/// Example (check if FEATURE_POSITIONAL shall be deactivated): +/// @code +/// if (features & FEATURE_POSITIONAL) { +/// // positional shall be deactivated +/// }; +/// @endcode +/// +/// @param features The feature set that shall be deactivated +/// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return +/// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. +PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); + + + +////////////////////////////////////////////////////////////////////////////////// +//////////////////////////// POSITIONAL DATA ///////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +// If this plugin wants to provide positional data, ALL functions of this category +// have to be implemented + +/// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is +/// currently able to do so and allocate memory that is needed for that process. As a parameter this function gets an +/// array of names and an array of PIDs. They are of same length and the PID at index i belongs to a program whose name +/// is listed at index i in the "name-array". +/// +/// @param programNames An array of pointers to the program names +/// @param programPIDs An array of the corresponding program PIDs +/// @param programCount The length of programNames and programPIDs +/// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start +/// frequently calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is +/// (currently) uncapable of providing positional data. In this case this function must not have allocated any memory +/// that needs to be cleaned up later on. Depending on the returned error code, Mumble might try to call this function +/// again at some point. +PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char *const *programNames, + const uint64_t *programPIDs, + size_t programCount); + +/// Retrieves the positional data. If no data can be fetched, set all float-vectors to 0 and return false. +/// +/// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame +/// world. One unit represents one meter of distance. +/// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar +/// ingame (where it is facing). +/// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to +/// its head. One unit represents one meter of distance. +/// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. +/// One unit represents one meter of distance. +/// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame +/// (where it is facing). +/// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One +/// unit represents one meter of distance. +/// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided +/// positional data shall be written. This context should include information about the server (and team) the player is +/// on. Only players with identical context will be able to hear each other's audio. The returned pointer has to remain +/// valid until the next invokation of this function or until shutdownPositionalData is called. +/// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall +/// be written. It can be polled by external scripts from the server and should uniquely identify the player in the +/// game. The pointer has to remain valid until the next invokation of this function or until shutdownPositionalData is +/// called. +/// @returns Whether this plugin can continue delivering positional data. If this function returns false, +/// shutdownPositionalData will be called. +PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, + float *avatarAxis, float *cameraPos, + float *cameraDir, float *cameraAxis, + const char **context, const char **identity); + +/// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this +/// purpose should be freed at this point. +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); + + + +////////////////////////////////////////////////////////////////////////////////// +////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// +////////////////////////////////////////////////////////////////////////////////// + +/// Called when connecting to a server. +/// Note that in most cases you'll want to use mumble_onServerSynchronized instead. +/// Note also that this callback will be called from a DIFFERENT THREAD! +/// +/// @param connection The ID of the newly established server-connection +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); + +/// Called when disconnecting from a server. +/// Note that this callback is called from a DIFFERENT THREAD! +/// +/// @param connection The ID of the server-connection that has been terminated +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); + +/// Called when the client has finished synchronizing with the server +/// +/// @param connection The ID of the server-connection that has been terminated +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); + +/// Called whenever any user on the server enters a channel +/// This function will also be called when freshly connecting to a server as each user on that +/// server needs to be "added" to the respective channel as far as the local client is concerned. +/// +/// @param connection The ID of the server-connection this event is connected to +/// @param userID The ID of the user this event has been triggered for +/// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no +/// previous channel (e.g. the user freshly connected to the server) or the channel isn't available because of any other +/// reason. +/// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be +/// retrieved. This means that the ID is invalid. +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, + mumble_userid_t userID, + mumble_channelid_t previousChannelID, + mumble_channelid_t newChannelID); + +/// Called whenever a user leaves a channel. +/// This includes a client disconnecting from the server as this will also lead to the user not being in that channel +/// anymore. +/// +/// @param connection The ID of the server-connection this event is connected to +/// @param userID The ID of the user that left the channel +/// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. +/// This means that the ID is invalid. +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, + mumble_userid_t userID, + mumble_channelid_t channelID); + +/// Called when any user changes his/her talking state. +/// +/// @param connection The ID of the server-connection this event is connected to +/// @param userID The ID of the user whose talking state has been changed +/// @param talkingState The new TalkingState the user has switched to. +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, + mumble_userid_t userID, + mumble_talking_state_t talkingState); + +/// Called whenever there is audio input. +/// Note that this callback will be called from the AUDIO THREAD. +/// Note also that blocking this callback will cause Mumble's audio processing to get suspended. +/// +/// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its +/// length is sampleCount * channelCount. The PCM format for stereo input is [LRLRLR...] where L and R are samples of +/// the left and right channel respectively. +/// @param sampleCount The amount of sample points per channel +/// @param channelCount The amount of channels in the audio +/// @param sampleRate The used sample rate in Hz +/// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of +/// background noise) +/// @returns Whether this callback has modified the audio input-array +PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, + uint16_t channelCount, uint32_t sampleRate, + bool isSpeech); + +/// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). +/// The provided audio buffer is the raw buffer without any processing applied to it yet. +/// Note that this callback will be called from the AUDIO THREAD. +/// Note also that blocking this callback will cause Mumble's audio processing to get suspended. +/// +/// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. +/// Its length is sampleCount * channelCount. The PCM format for stereo output is [LRLRLR...] where L and R are samples +/// of the left and right channel respectively. +/// @param sampleCount The amount of sample points per channel +/// @param channelCount The amount of channels in the audio +/// @param sampleRate The used sample rate in Hz +/// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) +/// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is +/// false, the content of this parameter is unspecified and should not be accessed +/// @returns Whether this callback has modified the audio output-array +PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, + uint16_t channelCount, uint32_t sampleRate, + bool isSpeech, mumble_userid_t userID); + +/// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). +/// Note that this happens immediately before Mumble clips the audio buffer. +/// Note that this callback will be called from the AUDIO THREAD. +/// Note also that blocking this callback will cause Mumble's audio processing to get suspended. +/// +/// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. +/// Its length is sampleCount * channelCount. The PCM format for stereo output is [LRLRLR...] where L and R are samples +/// of the left and right channel respectively. +/// @param sampleCount The amount of sample points per channel +/// @param channelCount The amount of channels in the audio +/// @param sampleRate The used sample rate in Hz +/// @returns Whether this callback has modified the audio output-array +PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, + uint16_t channelCount, + uint32_t sampleRate); + +/// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the +/// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended +/// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. +/// +/// @param connection The ID of the server-connection the data is coming from +/// @param sender The ID of the user whose client's plugin has sent the data +/// @param data The sent data array. This can be an arbitrary sequence of bytes. +/// @param dataLength The length of the data array +/// @param dataID The ID of this data (C-encoded) +/// @return Whether the given data has been processed by this plugin +PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, + mumble_userid_t sender, const uint8_t *data, + size_t dataLength, const char *dataID); + +/// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the +/// server the local user is on but also when the local user connects to a server other clients are already connected to +/// (in this case this method will be called for every client already on that server). +/// +/// @param connection An object used to identify the current connection +/// @param userID The ID of the user that has been added + +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + +/// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the +/// local user is on but also when the local user disconnects from a server other clients are connected to (in this case +/// this method will be called for every client on that server). +/// +/// @param connection An object used to identify the current connection +/// @param userID The ID of the user that has been removed +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, + mumble_userid_t userID); + +/// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server +/// the local user is on but also when the local user connects to a server that contains channels other than the +/// root-channel (in this case this method will be called for ever non-root channel on that server). +/// +/// @param connection An object used to identify the current connection +/// @param channelID The ID of the channel that has been added +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, + mumble_channelid_t channelID); + +/// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the +/// local user is on but also when the local user disconnects from a server that contains channels other than the +/// root-channel (in this case this method will be called for ever non-root channel on that server). +/// +/// @param connection An object used to identify the current connection +/// @param channelID The ID of the channel that has been removed +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, + mumble_channelid_t channelID); + +/// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial +/// name is also considered renaming). +/// +/// @param connection An object used to identify the current connection +/// @param channelID The ID of the channel that has been renamed +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, + mumble_channelid_t channelID); + +/// Called when a key has been pressed or released while Mumble has keyboard focus. +/// Note that this callback will only work if the user has explicitly given permission to monitor keyboard +/// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to +/// enable that. +/// +/// @param keyCode The key code of the respective key. The character codes are defined +/// via the Mumble_KeyCode enum. For printable 7-bit ASCII characters these codes conform +/// to the ASCII code-page with the only difference that case is not distinguished. Therefore +/// always the upper-case letter code will be used for letters. +/// @param wasPres Whether the respective key has been pressed (instead of released) +PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); + + + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////// PLUGIN UPDATES //////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// + +/// This function is used to determine whether the plugin can find an update for itself that is available for download. +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @return Whether the plugin was able to find an update for itself +PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); + +/// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. +/// +/// NOTE: This function may be called without the plugin being loaded +/// +/// @returns A String-wrapper containing the requested URL +PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h deleted file mode 100644 index b203eb1b7..000000000 --- a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents.h +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2019-2020 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -/// This header file contains definitions of types and other components used in Mumble's plugin system - -#ifndef MUMBLE_PLUGINCOMPONENT_H_ -#define MUMBLE_PLUGINCOMPONENT_H_ - -#include -#include -#include - -#ifdef QT_VERSION - #include -#endif - -// define the calling convention macro based on the compiler being used -#if defined(_MSC_VER) - #define PLUGIN_CALLING_CONVENTION __cdecl -#elif defined(__MINGW32__) - #define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) -#else - #define PLUGIN_CALLING_CONVENTION -#endif - - -/// A macro holding the exit status of a successful operation -#define STATUS_OK EC_OK -/// A macro holding the version object that is considered to correspond to an unknown version -#define VERSION_UNKNOWN Version({0,0,0}) - - -/// This enum's values correspond to special feature sets a plugin may provide. -/// They are meant to be or'ed together to represent the total feature set of a plugin. -enum PluginFeature { - /// None of the below - FEATURE_NONE = 0, - /// The plugin provides positional data from a game - FEATURE_POSITIONAL = 1 << 0, - /// The plugin modifies the input/output audio itself - FEATURE_AUDIO = 1 << 1 -}; - -/// This enum's values represent talking states a user can be in when using Mumble. -enum TalkingState { - INVALID=-1, - PASSIVE=0, - TALKING, - WHISPERING, - SHOUTING -}; - -/// This enum's values represent transmission modes a user might have configured. Transmission mode -/// in this context is referring to a method that determines when a user is speaking and thus when -/// to transmit audio packets. -enum TransmissionMode { - TM_CONTINOUS, - TM_VOICE_ACTIVATION, - TM_PUSH_TO_TALK -}; - -/// This enum's values represent the error codes that are being used by the MumbleAPI. -/// You can get a string-representation for each error code via the errorMessage function. -enum ErrorCode { - EC_GENERIC_ERROR = -1, - EC_OK = 0, - EC_POINTER_NOT_FOUND, - EC_NO_ACTIVE_CONNECTION, - EC_USER_NOT_FOUND, - EC_CHANNEL_NOT_FOUND, - EC_CONNECTION_NOT_FOUND, - EC_UNKNOWN_TRANSMISSION_MODE, - EC_AUDIO_NOT_AVAILABLE, - EC_INVALID_SAMPLE, - EC_INVALID_PLUGIN_ID -}; - -/// This enum's values represent error codes specific to the framework of handling positional data -/// gathering (needed for Mumble's positional audio feature). -enum PositionalDataErrorCode { - /// Positional data has been initialized properly - PDEC_OK = 0, - /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be - /// at another point in time. - PDEC_ERROR_TEMP, - /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). - PDEC_ERROR_PERM -}; - -/// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. -enum KeyCode { - KC_INVALID = -1, - - // Non-printable characters first - KC_NULL = 0, - KC_END = 1, - KC_LEFT = 2, - KC_RIGHT = 4, - KC_UP = 5, - KC_DOWN = 6, - KC_DELETE = 7, - KC_BACKSPACE = 8, - KC_TAB = 9, - KC_ENTER = 10, // == '\n' - KC_ESCAPE = 27, - KC_PAGE_UP = 11, - KC_PAGE_DOWN = 12, - KC_SHIFT = 13, - KC_CONTROL = 14, - KC_META = 15, - KC_ALT = 16, - KC_ALT_GR = 17, - KC_CAPSLOCK = 18, - KC_NUMLOCK = 19, - KC_SUPER = 20, // == windows key - KC_HOME = 21, // == Pos1 - KC_PRINT = 22, - KC_SCROLLLOCK = 23, - - // Printable characters are assigned to their ASCII code - KC_SPACE = ' ', - KC_EXCLAMATION_MARK = '!', - KC_DOUBLE_QUOTE = '"', - KC_HASHTAG = '#', - KC_DOLLAR = '$', - KC_PERCENT = '%', - KC_AMPERSAND = '&', - KC_SINGLE_QUOTE = '\'', - KC_OPEN_PARENTHESIS = '(', - KC_CLOSE_PARENTHESIS = ')', - KC_ASTERISK = '*', - KC_PLUS = '+', - KC_COMMA = ',', - KC_MINUS = '-', - KC_PERIOD = '.', - KC_SLASH = '/', - KC_0 = '0', - KC_1 = '1', - KC_2 = '2', - KC_3 = '3', - KC_4 = '4', - KC_5 = '5', - KC_6 = '6', - KC_7 = '7', - KC_8 = '8', - KC_9 = '9', - KC_COLON = ':', - KC_SEMICOLON = ';', - KC_LESS_THAN = '<', - KC_EQUALS = '=', - KC_GREATER_THAN = '>', - KC_QUESTION_MARK = '?', - KC_AT_SYMBOL = '@', - KC_A = 'A', - KC_B = 'B', - KC_C = 'C', - KC_D = 'D', - KC_E = 'E', - KC_F = 'F', - KC_G = 'G', - KC_H = 'H', - KC_I = 'I', - KC_J = 'J', - KC_K = 'K', - KC_L = 'L', - KC_M = 'M', - KC_N = 'N', - KC_O = 'O', - KC_P = 'P', - KC_Q = 'Q', - KC_R = 'R', - KC_S = 'S', - KC_T = 'T', - KC_U = 'U', - KC_V = 'V', - KC_W = 'W', - KC_X = 'X', - KC_Y = 'Y', - KC_Z = 'Z', - // leave out lowercase letters (for now) - KC_OPEN_BRACKET = '[', - KC_BACKSLASH = '\\', - KC_CLOSE_BRACKET = ']', - KC_CIRCUMFLEX = '^', - KC_UNDERSCORE = '_', - KC_GRAVE_AKCENT = '`', - KC_OPEN_BRACE = '{', - KC_VERTICAL_BAR = '|', - KC_CLOSE_BRACE = '}', - KC_TILDE = '~', - - // Some characters from the extended ASCII code - KC_DEGREE_SIGN = 176, - - - - // F-keys - // Start at a value of 256 as extended ASCII codes range up to 256 - KC_F1 = 256, - KC_F2 = 257, - KC_F3 = 258, - KC_F4 = 259, - KC_F5 = 260, - KC_F6 = 261, - KC_F7 = 262, - KC_F8 = 263, - KC_F9 = 264, - KC_F10 = 265, - KC_F11 = 266, - KC_F12 = 267, - KC_F13 = 268, - KC_F14 = 269, - KC_F15 = 270, - KC_F16 = 271, - KC_F17 = 272, - KC_F18 = 273, - KC_F19 = 274, -}; - -/// A struct for representing a version of the form major.minor.patch -struct Version { - int32_t major; - int32_t minor; - int32_t patch; -#ifdef __cplusplus - bool operator<(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch < other.patch; - } - - bool operator>(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch > other.patch; - } - - bool operator>=(const Version& other) const { - return this->major >= other.major && this->minor >= other.minor && this->patch >= other.patch; - } - - bool operator<=(const Version& other) const { - return this->major <= other.major && this->minor <= other.minor && this->patch <= other.patch; - } - - bool operator==(const Version& other) const { - return this->major == other.major && this->minor == other.minor && this->patch == other.patch; - } - - operator std::string() const { - return std::string("v") + std::to_string(this->major) + std::to_string(this->minor) + std::to_string(this->patch); - } - -#ifdef QT_VERSION - operator QString() const { - return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); - } -#endif -#endif -}; - -/// @param errorCode The error code to get a message for -/// @returns The error message coresponding to the given error code. The message -/// is encoded as a C-string and are static meaning that it is safe to use the -/// returned pointer in your code. -inline const char* errorMessage(int16_t errorCode) { - switch (errorCode) { - case EC_GENERIC_ERROR: - return "Generic error"; - case EC_OK: - return "Ok - this is not an error"; - case EC_POINTER_NOT_FOUND: - return "Can't find the passed pointer"; - case EC_NO_ACTIVE_CONNECTION: - return "There is currently no active connection to a server"; - case EC_USER_NOT_FOUND: - return "Can't find the requested user"; - case EC_CHANNEL_NOT_FOUND: - return "Can't find the requested channel"; - case EC_CONNECTION_NOT_FOUND: - return "Can't identify the requested connection"; - case EC_UNKNOWN_TRANSMISSION_MODE: - return "Unknown transmission mode encountered"; - case EC_AUDIO_NOT_AVAILABLE: - return "There is currently no audio output available"; - case EC_INVALID_SAMPLE: - return "Attempted to use invalid sample (can't play it)"; - case EC_INVALID_PLUGIN_ID: - return "Used an invalid plugin ID"; - default: - return "Unknown error code"; - } -} - - -/// Typedef for the type of a talking state -typedef enum TalkingState talking_state_t; -/// Typedef for the type of a transmission mode -typedef enum TransmissionMode transmission_mode_t; -/// Typedef for the type of a version -typedef struct Version version_t; -/// Typedef for the type of a connection -typedef int32_t mumble_connection_t; -/// Typedef for the type of a user -typedef uint32_t mumble_userid_t; -/// Typedef for the type of a channel -typedef int32_t mumble_channelid_t; -/// Typedef for the type of an error (code) -typedef enum ErrorCode mumble_error_t; -/// Typedef for the type of a plugin ID -typedef uint32_t plugin_id_t; -/// Typedef for the type of a key-code -typedef KeyCode keycode_t; - -#endif // MUMBLE_PLUGINCOMPONENT_H_ diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h new file mode 100644 index 000000000..8692fc348 --- /dev/null +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h @@ -0,0 +1,401 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file contains definitions of types and other components used in Mumble's plugin system + +#ifndef MUMBLE_PLUGINCOMPONENT_H_ +#define MUMBLE_PLUGINCOMPONENT_H_ + +#include +#include +#include + +#ifdef __cplusplus +# include +#endif + +#if defined(QT_CORE_LIB) || defined(QT_VERSION) +# include +#endif + +// define the calling convention macro based on the compiler being used +#if defined(_MSC_VER) +# define PLUGIN_CALLING_CONVENTION __cdecl +#elif defined(__MINGW32__) +# define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) +#else +# define PLUGIN_CALLING_CONVENTION +#endif + + +/// A macro holding the exit status of a successful operation +#define STATUS_OK EC_OK +/// A macro holding the version object that is considered to correspond to an unknown version +#define VERSION_UNKNOWN Version({ 0, 0, 0 }) + + +/// This enum's values correspond to special feature sets a plugin may provide. +/// They are meant to be or'ed together to represent the total feature set of a plugin. +enum Mumble_PluginFeature { + /// None of the below + FEATURE_NONE = 0, + /// The plugin provides positional data from a game + FEATURE_POSITIONAL = 1 << 0, + /// The plugin modifies the input/output audio itself + FEATURE_AUDIO = 1 << 1 +}; + +/// This enum's values represent talking states a user can be in when using Mumble. +enum Mumble_TalkingState { INVALID = -1, PASSIVE = 0, TALKING, WHISPERING, SHOUTING, TALKING_MUTED }; + +/// This enum's values represent transmission modes a user might have configured. Transmission mode +/// in this context is referring to a method that determines when a user is speaking and thus when +/// to transmit audio packets. +enum Mumble_TransmissionMode { TM_CONTINOUS, TM_VOICE_ACTIVATION, TM_PUSH_TO_TALK }; + +/// This enum's values represent the error codes that are being used by the MumbleAPI. +/// You can get a string-representation for each error code via the errorMessage function. +enum Mumble_ErrorCode { + EC_INTERNAL_ERROR = -2, + EC_GENERIC_ERROR = -1, + EC_OK = 0, + EC_POINTER_NOT_FOUND, + EC_NO_ACTIVE_CONNECTION, + EC_USER_NOT_FOUND, + EC_CHANNEL_NOT_FOUND, + EC_CONNECTION_NOT_FOUND, + EC_UNKNOWN_TRANSMISSION_MODE, + EC_AUDIO_NOT_AVAILABLE, + EC_INVALID_SAMPLE, + EC_INVALID_PLUGIN_ID, + EC_INVALID_MUTE_TARGET, + EC_CONNECTION_UNSYNCHRONIZED, + EC_INVALID_API_VERSION, + EC_UNSYNCHRONIZED_BLOB, + EC_UNKNOWN_SETTINGS_KEY, + EC_WRONG_SETTINGS_TYPE, + EC_SETTING_WAS_REMOVED, + EC_DATA_TOO_BIG, + EC_DATA_ID_TOO_LONG, +}; + +/// This enum's values represent error codes specific to the framework of handling positional data +/// gathering (needed for Mumble's positional audio feature). +enum Mumble_PositionalDataErrorCode { + /// Positional data has been initialized properly + PDEC_OK = 0, + /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be + /// at another point in time. + PDEC_ERROR_TEMP, + /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). + PDEC_ERROR_PERM +}; + +/// This enum's values represent keys for specific settings inside Mumble. +enum Mumble_SettingsKey { + MSK_INVALID = -1, + MSK_AUDIO_INPUT_VOICE_HOLD = 0, + MSK_AUDIO_INPUT_VAD_SILENCE_THRESHOLD = 1, + MSK_AUDIO_INPUT_VAD_SPEECH_THRESHOLD = 2, + MSK_AUDIO_OUTPUT_PA_MINIMUM_DISTANCE = 3, + MSK_AUDIO_OUTPUT_PA_MAXIMUM_DISTANCE = 4, + MSK_AUDIO_OUTPUT_PA_BLOOM = 5, + MSK_AUDIO_OUTPUT_PA_MINIMUM_VOLUME = 6, +}; + +/// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. +enum Mumble_KeyCode { + KC_INVALID = -1, + + // Non-printable characters first + KC_NULL = 0, + KC_END = 1, + KC_LEFT = 2, + KC_RIGHT = 4, + KC_UP = 5, + KC_DOWN = 6, + KC_DELETE = 7, + KC_BACKSPACE = 8, + KC_TAB = 9, + KC_ENTER = 10, // == '\n' + KC_ESCAPE = 27, + KC_PAGE_UP = 11, + KC_PAGE_DOWN = 12, + KC_SHIFT = 13, + KC_CONTROL = 14, + KC_META = 15, + KC_ALT = 16, + KC_ALT_GR = 17, + KC_CAPSLOCK = 18, + KC_NUMLOCK = 19, + KC_SUPER = 20, // == windows key + KC_HOME = 21, // == Pos1 + KC_PRINT = 22, + KC_SCROLLLOCK = 23, + + // Printable characters are assigned to their ASCII code + KC_SPACE = ' ', + KC_EXCLAMATION_MARK = '!', + KC_DOUBLE_QUOTE = '"', + KC_HASHTAG = '#', + KC_DOLLAR = '$', + KC_PERCENT = '%', + KC_AMPERSAND = '&', + KC_SINGLE_QUOTE = '\'', + KC_OPEN_PARENTHESIS = '(', + KC_CLOSE_PARENTHESIS = ')', + KC_ASTERISK = '*', + KC_PLUS = '+', + KC_COMMA = ',', + KC_MINUS = '-', + KC_PERIOD = '.', + KC_SLASH = '/', + KC_0 = '0', + KC_1 = '1', + KC_2 = '2', + KC_3 = '3', + KC_4 = '4', + KC_5 = '5', + KC_6 = '6', + KC_7 = '7', + KC_8 = '8', + KC_9 = '9', + KC_COLON = ':', + KC_SEMICOLON = ';', + KC_LESS_THAN = '<', + KC_EQUALS = '=', + KC_GREATER_THAN = '>', + KC_QUESTION_MARK = '?', + KC_AT_SYMBOL = '@', + KC_A = 'A', + KC_B = 'B', + KC_C = 'C', + KC_D = 'D', + KC_E = 'E', + KC_F = 'F', + KC_G = 'G', + KC_H = 'H', + KC_I = 'I', + KC_J = 'J', + KC_K = 'K', + KC_L = 'L', + KC_M = 'M', + KC_N = 'N', + KC_O = 'O', + KC_P = 'P', + KC_Q = 'Q', + KC_R = 'R', + KC_S = 'S', + KC_T = 'T', + KC_U = 'U', + KC_V = 'V', + KC_W = 'W', + KC_X = 'X', + KC_Y = 'Y', + KC_Z = 'Z', + // leave out lowercase letters (for now) + KC_OPEN_BRACKET = '[', + KC_BACKSLASH = '\\', + KC_CLOSE_BRACKET = ']', + KC_CIRCUMFLEX = '^', + KC_UNDERSCORE = '_', + KC_GRAVE_AKCENT = '`', + KC_OPEN_BRACE = '{', + KC_VERTICAL_BAR = '|', + KC_CLOSE_BRACE = '}', + KC_TILDE = '~', + + // Some characters from the extended ASCII code + KC_DEGREE_SIGN = 176, + + + + // F-keys + // Start at a value of 256 as extended ASCII codes range up to 255 + KC_F1 = 256, + KC_F2 = 257, + KC_F3 = 258, + KC_F4 = 259, + KC_F5 = 260, + KC_F6 = 261, + KC_F7 = 262, + KC_F8 = 263, + KC_F9 = 264, + KC_F10 = 265, + KC_F11 = 266, + KC_F12 = 267, + KC_F13 = 268, + KC_F14 = 269, + KC_F15 = 270, + KC_F16 = 271, + KC_F17 = 272, + KC_F18 = 273, + KC_F19 = 274, +}; + +/// A struct for representing a version of the form major.minor.patch +struct Version { + int32_t major; + int32_t minor; + int32_t patch; +#ifdef __cplusplus + bool operator<(const Version &other) const { + if (this->major != other.major) { + return this->major < other.major; + } + if (this->minor != other.minor) { + return this->minor < other.minor; + } + // Major and Minor are equal + return this->patch < other.patch; + } + + bool operator>(const Version &other) const { + if (this->major != other.major) { + return this->major > other.major; + } + if (this->minor != other.minor) { + return this->minor > other.minor; + } + // Major and Minor are equal + return this->patch > other.patch; + } + + bool operator>=(const Version &other) const { + if (this->major != other.major) { + return this->major > other.major; + } + if (this->minor != other.minor) { + return this->minor > other.minor; + } + // Major and Minor are equal + return this->patch >= other.patch; + } + + bool operator<=(const Version &other) const { + if (this->major != other.major) { + return this->major < other.major; + } + if (this->minor != other.minor) { + return this->minor < other.minor; + } + // Major and Minor are equal + return this->patch <= other.patch; + } + + bool operator==(const Version &other) const { + return this->major == other.major && this->minor == other.minor && this->patch == other.patch; + } + + bool operator!=(const Version &other) const { + return this->major != other.major || this->minor != other.minor || this->patch != other.patch; + } + + operator std::string() const { + return std::string("v") + std::to_string(this->major) + std::string(".") + std::to_string(this->minor) + + std::string(".") + std::to_string(this->patch); + } + +# if defined(QT_CORE_LIB) || defined(QT_VERSION) + operator QString() const { + return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); + } +# endif +#endif +}; + +/// Obtains a String representation for the given numeric error code. +/// Note that the exact String representation corresponding to an error code may change and is thus +/// not part of the plugin API as such. This function acts merely as a convenience helper for printing +/// errors in a meaningful way. +/// +/// @param errorCode The error code to get the String representation for +/// @returns The error message coresponding to the given error code. The message +/// is encoded as a C-string and is static, meaning that it is safe to use the +/// returned pointer in your code. +inline const char *errorMessage(int16_t errorCode) { + switch (errorCode) { + case EC_GENERIC_ERROR: + return "Generic error"; + case EC_OK: + return "Ok - this is not an error"; + case EC_POINTER_NOT_FOUND: + return "Can't find the passed pointer"; + case EC_NO_ACTIVE_CONNECTION: + return "There is currently no active connection to a server"; + case EC_USER_NOT_FOUND: + return "Can't find the requested user"; + case EC_CHANNEL_NOT_FOUND: + return "Can't find the requested channel"; + case EC_CONNECTION_NOT_FOUND: + return "Can't identify the requested connection"; + case EC_UNKNOWN_TRANSMISSION_MODE: + return "Unknown transmission mode encountered"; + case EC_AUDIO_NOT_AVAILABLE: + return "There is currently no audio output available"; + case EC_INVALID_SAMPLE: + return "Attempted to use invalid sample (can't play it)"; + case EC_INVALID_PLUGIN_ID: + return "Used an invalid plugin ID"; + case EC_INVALID_MUTE_TARGET: + return "Used an invalid mute-target"; + case EC_CONNECTION_UNSYNCHRONIZED: + return "The requested server connection has not yet finished synchronizing"; + case EC_INVALID_API_VERSION: + return "The used API version is invalid or not supported"; + case EC_UNSYNCHRONIZED_BLOB: + return "The requested blob (content) has not yet been synchronized between the client and the server"; + case EC_UNKNOWN_SETTINGS_KEY: + return "The used settings-key does not match any key known to Mumble"; + case EC_WRONG_SETTINGS_TYPE: + return "The referenced setting has a different type than requested"; + case EC_SETTING_WAS_REMOVED: + return "The referenced setting got removed from Mumble and is no longer used"; + case EC_DATA_TOO_BIG: + return "The given data is too large (exceeds limit)"; + case EC_DATA_ID_TOO_LONG: + return "The given data ID is too long (exceeds limit)"; + default: + return "Unknown error code"; + } +} + + +/// This struct is used to return Strings from a plugin to Mumble. It is needed in order to +/// work around the limitation of std::string not being part of C (it holds important information +/// about the String's lifetime management requirements). +struct MumbleStringWrapper { + /// The pointer to the actual String data + const char *data; + /// The size of the pointed String data + size_t size; + /// Whether the wrapped String needs to be released + /// after its usage. Instances for which this would be + /// false: Static Strings, String literals + bool needsReleasing; +}; + +/// Typedef for the type of a talking state +typedef enum Mumble_TalkingState mumble_talking_state_t; +/// Typedef for the type of a transmission mode +typedef enum Mumble_TransmissionMode mumble_transmission_mode_t; +/// Typedef for the type of a version +typedef struct Version mumble_version_t; +/// Typedef for the type of a connection +typedef int32_t mumble_connection_t; +/// Typedef for the type of a user +typedef uint32_t mumble_userid_t; +/// Typedef for the type of a channel +typedef int32_t mumble_channelid_t; +/// Typedef for the type of an error (code) +typedef enum Mumble_ErrorCode mumble_error_t; +/// Typedef for the type of a plugin ID +typedef uint32_t mumble_plugin_id_t; +/// Typedef for the type of a key to a setting in Mumble +typedef enum Mumble_SettingsKey mumble_settings_key_t; +/// Typedef for the type of a key-code +typedef enum Mumble_KeyCode mumble_keycode_t; + +#endif // MUMBLE_PLUGINCOMPONENT_H_ From 2e5414530b08166b55bc25b43a17ac39be66de96 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 27 May 2021 20:43:12 +0200 Subject: [PATCH 075/104] Actually make it compile --- .../MumbleCallbacks_channelEvents.cpp | 2 +- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 2 +- .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 7 +++---- extensions/src/ACRE2Mumble/MumbleClient.cpp | 21 ++++++++++--------- .../src/ACRE2Mumble/MumbleCommandServer.cpp | 12 +++++------ .../src/ACRE2Mumble/acre2_mumble_dllmain.cpp | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp index de6f63beb..46e2d2721 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_channelEvents.cpp @@ -7,7 +7,7 @@ extern MumbleAPI_v_1_0_x mumAPI; extern mumble_connection_t activeConnection; -extern plugin_id_t pluginID; +extern mumble_plugin_id_t pluginID; void mumble_onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID) { (void) connection; diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 5c9b47fb2..bd945d280 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -12,7 +12,7 @@ extern MumbleAPI_v_1_0_x mumAPI; // TODO: Should these special values be a named variable? mumble_connection_t activeConnection = -1; -plugin_id_t pluginID = -1; +mumble_plugin_id_t pluginID = -1; uint32_t mumble_getFeatures() { return FEATURE_AUDIO; diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index 043d95d7c..0c8724b51 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -8,7 +8,7 @@ // // Mumble Speaking callbacks // -void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, talking_state_t status) { +void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, mumble_talking_state_t status) { TRACE("mumble_onUserTalkingStateChanged ENTER: %d", status); if (static_cast(userID) != CEngine::getInstance()->getSelf()->getId()) { return; @@ -40,8 +40,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use return; } - // TODO: Is the TalkingState enum defined somewhere in ACRE? 'cause it is not defined in Mumble - if (status == TalkingState::PASSIVE || status == TalkingState::INVALID) { + if (status == PASSIVE || status == INVALID) { if ((!CEngine::getInstance()->getClient()->getRadioPTTDown()) && (!CEngine::getInstance()->getClient()->getGodPTTDown()) && (!CEngine::getInstance()->getClient()->getZeusPTTDown())) { @@ -64,7 +63,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use } TRACE("enter: [%d],[%d]", clientID, status); - if ((status != TalkingState::PASSIVE) && (status != TalkingState::INVALID)) { + if ((status != PASSIVE) && (status != INVALID)) { CEngine::getInstance()->getClient()->setDirectFirst(true); CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::direct); } else { diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index a3e5b74e0..79c07f185 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -73,12 +73,11 @@ acre::Result CMumbleClient::start(const acre::id_t id_) { bool CMumbleClient::getVAD() { mumble_transmission_mode_t transmitMode; const mumble_error_t err = mumAPI.getLocalUserTransmissionMode(pluginID, &transmitMode); - if (err != ErrorCode::EC_OK) { + if (err != EC_OK) { return false; } - // TODO: Is this enum defined somewhere in ACRE? - return transmitMode == TransmissionMode::TM_VOICE_ACTIVATION; + return transmitMode == TM_VOICE_ACTIVATION; } acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType_) { @@ -117,7 +116,7 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } else { stopDirectSpeaking = true; } - } else if (VADactive && (speakingState != TalkingState::PASSIVE) && (speakingState != TalkingState::INVALID)) { + } else if (VADactive && (speakingState != PASSIVE) && (speakingState != INVALID)) { stopDirectSpeaking = true; } } @@ -176,7 +175,7 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ this->setOnRadio(false); const std::int32_t speakingState = this->getSpeakingState(); - if ((speakingState != TalkingState::PASSIVE) && (speakingState != TalkingState::INVALID)) { + if ((speakingState != PASSIVE) && (speakingState != INVALID)) { resendDirectSpeaking = true; } } @@ -188,7 +187,7 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ } else { resendDirectSpeaking = true; } - } else if ((speakingState != TalkingState::PASSIVE) && (speakingState != TalkingState::INVALID)) { + } else if ((speakingState != PASSIVE) && (speakingState != INVALID)) { resendDirectSpeaking = true; } } @@ -237,7 +236,7 @@ std::string CMumbleClient::getTempFilePath(void) { acre::Result CMumbleClient::microphoneOpen(bool status_) { const mumble_error_t res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, status_); - if (res != ErrorCode::EC_OK) { + if (res != EC_OK) { if (status_) { LOG("Error toggling PTT Open\n"); } else { @@ -322,11 +321,13 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { for (std::size_t idx = 0U; idx < channelCount; idx++) { channelId = *channelList + idx; - char *channelName = nullptr; + const char *channelName = nullptr; if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == STATUS_OK) { - // TODO: Does std::string take care of deleting the allocated name? - std::string channelNameString(channelName); + // Copy the channel name into a std::string and then get rid of the Mumble resource again + std::string channelNameString(channelName); + mumAPI.freeMemory(pluginID, (void *) channelName); + if (channelNameString.find(default_mumble_channel) != -1 || (!details_.at(0).empty() && channelNameString == name)) { if (channelNameString == default_mumble_channel) { defaultChannelId = channelId; diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index f033b38c6..014f8344a 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -4,9 +4,9 @@ #include "MumbleFunctions.h" #include "TextMessage.h" -extern MumbleAPI mumAPI; +extern MumbleAPI_v_1_0_x mumAPI; extern mumble_connection_t activeConnection; -extern plugin_id_t pluginID; +extern mumble_plugin_id_t pluginID; acre::Result CMumbleCommandServer::initialize() { TRACE("enter"); @@ -28,24 +28,24 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg) { mumble_channelid_t currentChannel = 0; mumble_error_t err = mumAPI.getChannelOfUser(pluginID, activeConnection, this->getId(), ¤tChannel); - if (err != ErrorCode::EC_OK) { + if (err != EC_OK) { LOG("ERROR, UNABLE TO GET CHANNEL OF USER: %d", err); return acre::Result::error; } err = mumAPI.getUsersInChannel(pluginID, activeConnection, currentChannel, &channelUsers, &userCount); - if (err != ErrorCode::EC_OK) { + if (err != EC_OK) { LOG("ERROR, UNABLE TO GET USERS IN CHANNEL: %d", err); return acre::Result::error; } err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const uint8_t *) msg->getData(), msg->getLength(), "ACRE2"); - if (err != ErrorCode::EC_OK) { + if (err != EC_OK) { LOG("ERROR, UNABLE TO SEND MESSAGE DATA: %d", err); return acre::Result::error; } err = mumAPI.freeMemory(pluginID, (void *) channelUsers); - if (err != ErrorCode::EC_OK) { + if (err != EC_OK) { LOG("ERROR, UNABLE TO FREE CHANNEL USER LIST: %d", err); return acre::Result::error; } diff --git a/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp b/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp index 6a8240044..bcc4b003c 100644 --- a/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp +++ b/extensions/src/ACRE2Mumble/acre2_mumble_dllmain.cpp @@ -1,6 +1,6 @@ #include "MumbleFunctions.h" -MumbleAPI mumAPI; +MumbleAPI_v_1_0_x mumAPI; #pragma comment(lib, "x3daudio.lib") #pragma comment(lib, "shlwapi.lib") From 0c0df7fe99dd77db16ac806fb0d49408436eb9c1 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 27 May 2021 20:48:55 +0200 Subject: [PATCH 076/104] Query active connection at plugin init --- extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index bd945d280..a1b7c1c07 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -20,6 +20,7 @@ uint32_t mumble_getFeatures() { void mumble_registerAPIFunctions(void *apiStruct) { mumAPI = MUMBLE_API_CAST(apiStruct); + CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); if (CEngine::getInstance() != NULL) { if (((CMumbleCommandServer *) CEngine::getInstance()->getExternalServer()) != NULL) { @@ -37,9 +38,10 @@ void mumble_registerAPIFunctions(void *apiStruct) { mumble_error_t mumble_init(mumble_plugin_id_t id) { pluginID = id; - - // TODO: Is initializing the active server connection required at this point? - // If so it must be done via an API call + + if (mumAPI.getActiveServerConnection(pluginID, &connection) != EC_OK) { + connection = -1; + } return STATUS_OK; } From 408ea60fb68212e4f1334ecfefb2af40dd26c566 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Wed, 9 Jun 2021 20:33:17 +0200 Subject: [PATCH 077/104] Use new API headers with prefixed names --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 8 +- .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 4 +- extensions/src/ACRE2Mumble/MumbleClient.cpp | 24 +- .../src/ACRE2Mumble/MumbleCommandServer.cpp | 8 +- .../mumble_includes/MumbleAPI_v_1_0_x.h | 12 +- .../PluginComponents_v_1_0_x.h | 386 +++++++++--------- 6 files changed, 225 insertions(+), 217 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index a1b7c1c07..c5649db48 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -15,7 +15,7 @@ mumble_connection_t activeConnection = -1; mumble_plugin_id_t pluginID = -1; uint32_t mumble_getFeatures() { - return FEATURE_AUDIO; + return MUMBLE_FEATURE_AUDIO; } void mumble_registerAPIFunctions(void *apiStruct) { @@ -39,11 +39,11 @@ void mumble_registerAPIFunctions(void *apiStruct) { mumble_error_t mumble_init(mumble_plugin_id_t id) { pluginID = id; - if (mumAPI.getActiveServerConnection(pluginID, &connection) != EC_OK) { - connection = -1; + if (mumAPI.getActiveServerConnection(pluginID, &activeConnection) != MUMBLE_STATUS_OK) { + activeConnection = -1; } - return STATUS_OK; + return MUMBLE_STATUS_OK; } void mumble_onServerSynchronized(mumble_connection_t connection) { diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index 0c8724b51..c5ff1939b 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -40,7 +40,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use return; } - if (status == PASSIVE || status == INVALID) { + if (status == MUMBLE_TS_PASSIVE || status == MUMBLE_TS_INVALID) { if ((!CEngine::getInstance()->getClient()->getRadioPTTDown()) && (!CEngine::getInstance()->getClient()->getGodPTTDown()) && (!CEngine::getInstance()->getClient()->getZeusPTTDown())) { @@ -63,7 +63,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use } TRACE("enter: [%d],[%d]", clientID, status); - if ((status != PASSIVE) && (status != INVALID)) { + if ((status != MUMBLE_TS_PASSIVE) && (status != MUMBLE_TS_INVALID)) { CEngine::getInstance()->getClient()->setDirectFirst(true); CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::direct); } else { diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 79c07f185..b617968f6 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -73,11 +73,11 @@ acre::Result CMumbleClient::start(const acre::id_t id_) { bool CMumbleClient::getVAD() { mumble_transmission_mode_t transmitMode; const mumble_error_t err = mumAPI.getLocalUserTransmissionMode(pluginID, &transmitMode); - if (err != EC_OK) { + if (err != MUMBLE_STATUS_OK) { return false; } - return transmitMode == TM_VOICE_ACTIVATION; + return transmitMode == MUMBLE_TM_VOICE_ACTIVATION; } acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType_) { @@ -116,7 +116,7 @@ acre::Result CMumbleClient::localStartSpeaking(const acre::Speaking speakingType } else { stopDirectSpeaking = true; } - } else if (VADactive && (speakingState != PASSIVE) && (speakingState != INVALID)) { + } else if (VADactive && (speakingState != MUMBLE_TS_PASSIVE) && (speakingState != MUMBLE_TS_INVALID)) { stopDirectSpeaking = true; } } @@ -175,7 +175,7 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ this->setOnRadio(false); const std::int32_t speakingState = this->getSpeakingState(); - if ((speakingState != PASSIVE) && (speakingState != INVALID)) { + if ((speakingState != MUMBLE_TS_PASSIVE) && (speakingState != MUMBLE_TS_INVALID)) { resendDirectSpeaking = true; } } @@ -187,7 +187,7 @@ acre::Result CMumbleClient::localStopSpeaking(const acre::Speaking speakingType_ } else { resendDirectSpeaking = true; } - } else if ((speakingState != PASSIVE) && (speakingState != INVALID)) { + } else if ((speakingState != MUMBLE_TS_PASSIVE) && (speakingState != MUMBLE_TS_INVALID)) { resendDirectSpeaking = true; } } @@ -236,7 +236,7 @@ std::string CMumbleClient::getTempFilePath(void) { acre::Result CMumbleClient::microphoneOpen(bool status_) { const mumble_error_t res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, status_); - if (res != EC_OK) { + if (res != MUMBLE_STATUS_OK) { if (status_) { LOG("Error toggling PTT Open\n"); } else { @@ -260,10 +260,10 @@ acre::Result CMumbleClient::moveToServerChannel() { mumble_userid_t clientId; std::vector details = getChannelDetails(); - if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == STATUS_OK) { + if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == MUMBLE_STATUS_OK) { mumble_channelid_t currentChannelId = invalid_mumble_channel; - if ((mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) && + if ((mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == MUMBLE_STATUS_OK) && (getPreviousChannel() == invalid_mumble_channel)) { setPreviousChannel(currentChannelId); } @@ -289,10 +289,10 @@ acre::Result CMumbleClient::moveToPreviousChannel() { if (!CAcreSettings::getInstance()->getDisableChannelSwitch()) { mumble_userid_t clientId = -1; - if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == STATUS_OK) { + if (mumAPI.getLocalUserID(pluginID, activeConnection, &clientId) == MUMBLE_STATUS_OK) { mumble_channelid_t currentChannelId = invalid_mumble_channel; - if (mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == STATUS_OK) { + if (mumAPI.getChannelOfUser(pluginID, activeConnection, clientId, ¤tChannelId) == MUMBLE_STATUS_OK) { const mumble_channelid_t channelId = static_cast(getPreviousChannel()); if (channelId != invalid_mumble_channel && channelId != currentChannelId) { mumAPI.requestUserMove(pluginID, activeConnection, clientId, channelId, ""); @@ -310,7 +310,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { mumble_channelid_t *channelList = nullptr; std::size_t channelCount = 0U; - if (mumAPI.getAllChannels(pluginID, activeConnection, &channelList, &channelCount) == STATUS_OK) { + if (mumAPI.getAllChannels(pluginID, activeConnection, &channelList, &channelCount) == MUMBLE_STATUS_OK) { mumble_channelid_t channelId = invalid_mumble_channel; mumble_channelid_t defaultChannelId = invalid_mumble_channel; std::map channelMap; @@ -323,7 +323,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { channelId = *channelList + idx; const char *channelName = nullptr; - if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == STATUS_OK) { + if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == MUMBLE_STATUS_OK) { // Copy the channel name into a std::string and then get rid of the Mumble resource again std::string channelNameString(channelName); mumAPI.freeMemory(pluginID, (void *) channelName); diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index 014f8344a..f4779b79d 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -28,24 +28,24 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg) { mumble_channelid_t currentChannel = 0; mumble_error_t err = mumAPI.getChannelOfUser(pluginID, activeConnection, this->getId(), ¤tChannel); - if (err != EC_OK) { + if (err != MUMBLE_STATUS_OK) { LOG("ERROR, UNABLE TO GET CHANNEL OF USER: %d", err); return acre::Result::error; } err = mumAPI.getUsersInChannel(pluginID, activeConnection, currentChannel, &channelUsers, &userCount); - if (err != EC_OK) { + if (err != MUMBLE_STATUS_OK) { LOG("ERROR, UNABLE TO GET USERS IN CHANNEL: %d", err); return acre::Result::error; } err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const uint8_t *) msg->getData(), msg->getLength(), "ACRE2"); - if (err != EC_OK) { + if (err != MUMBLE_STATUS_OK) { LOG("ERROR, UNABLE TO SEND MESSAGE DATA: %d", err); return acre::Result::error; } err = mumAPI.freeMemory(pluginID, (void *) channelUsers); - if (err != EC_OK) { + if (err != MUMBLE_STATUS_OK) { LOG("ERROR, UNABLE TO FREE CHANNEL USER LIST: %d", err); return acre::Result::error; } diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h index 2e0a79466..4471680a1 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h @@ -5,8 +5,8 @@ /// This header file contains the definition of Mumble's API -#ifndef MUMBLE_PLUGIN_API_H_ -#define MUMBLE_PLUGIN_API_H_ +#ifndef EXTERNAL_MUMBLE_PLUGIN_API_H_ +#define EXTERNAL_MUMBLE_PLUGIN_API_H_ #include "PluginComponents_v_1_0_x.h" #include @@ -17,9 +17,9 @@ #define MUMBLE_PLUGIN_API_MINOR_MACRO 0 #define MUMBLE_PLUGIN_API_PATCH_MACRO 0 -constexpr int32_t MUMBLE_PLUGIN_API_MAJOR = MUMBLE_PLUGIN_API_MAJOR_MACRO; -constexpr int32_t MUMBLE_PLUGIN_API_MINOR = MUMBLE_PLUGIN_API_MINOR_MACRO; -constexpr int32_t MUMBLE_PLUGIN_API_PATCH = MUMBLE_PLUGIN_API_PATCH_MACRO; +const int32_t MUMBLE_PLUGIN_API_MAJOR = MUMBLE_PLUGIN_API_MAJOR_MACRO; +const int32_t MUMBLE_PLUGIN_API_MINOR = MUMBLE_PLUGIN_API_MINOR_MACRO; +const int32_t MUMBLE_PLUGIN_API_PATCH = MUMBLE_PLUGIN_API_PATCH_MACRO; const mumble_version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PLUGIN_API_MINOR, MUMBLE_PLUGIN_API_PATCH }; @@ -527,4 +527,4 @@ struct MumbleAPI_v_1_0_x { mumble_error_t(PLUGIN_CALLING_CONVENTION *playSample)(mumble_plugin_id_t callerID, const char *samplePath); }; -#endif +#endif // EXTERNAL_MUMBLE_PLUGIN_API_H_ diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h index 8692fc348..f6c422e97 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h @@ -5,8 +5,8 @@ /// This header file contains definitions of types and other components used in Mumble's plugin system -#ifndef MUMBLE_PLUGINCOMPONENT_H_ -#define MUMBLE_PLUGINCOMPONENT_H_ +#ifndef EXTERNAL_MUMBLE_PLUGINCOMPONENT_H_ +#define EXTERNAL_MUMBLE_PLUGINCOMPONENT_H_ #include #include @@ -30,218 +30,219 @@ #endif -/// A macro holding the exit status of a successful operation -#define STATUS_OK EC_OK -/// A macro holding the version object that is considered to correspond to an unknown version -#define VERSION_UNKNOWN Version({ 0, 0, 0 }) - - /// This enum's values correspond to special feature sets a plugin may provide. /// They are meant to be or'ed together to represent the total feature set of a plugin. enum Mumble_PluginFeature { /// None of the below - FEATURE_NONE = 0, + MUMBLE_FEATURE_NONE = 0, /// The plugin provides positional data from a game - FEATURE_POSITIONAL = 1 << 0, + MUMBLE_FEATURE_POSITIONAL = 1 << 0, /// The plugin modifies the input/output audio itself - FEATURE_AUDIO = 1 << 1 + MUMBLE_FEATURE_AUDIO = 1 << 1 }; /// This enum's values represent talking states a user can be in when using Mumble. -enum Mumble_TalkingState { INVALID = -1, PASSIVE = 0, TALKING, WHISPERING, SHOUTING, TALKING_MUTED }; +enum Mumble_TalkingState { + MUMBLE_TS_INVALID = -1, + MUMBLE_TS_PASSIVE = 0, + MUMBLE_TS_TALKING, + MUMBLE_TS_WHISPERING, + MUMBLE_TS_SHOUTING, + MUMBLE_TS_TALKING_MUTED +}; /// This enum's values represent transmission modes a user might have configured. Transmission mode /// in this context is referring to a method that determines when a user is speaking and thus when /// to transmit audio packets. -enum Mumble_TransmissionMode { TM_CONTINOUS, TM_VOICE_ACTIVATION, TM_PUSH_TO_TALK }; +enum Mumble_TransmissionMode { MUMBLE_TM_CONTINOUS, MUMBLE_TM_VOICE_ACTIVATION, MUMBLE_TM_PUSH_TO_TALK }; /// This enum's values represent the error codes that are being used by the MumbleAPI. /// You can get a string-representation for each error code via the errorMessage function. enum Mumble_ErrorCode { - EC_INTERNAL_ERROR = -2, - EC_GENERIC_ERROR = -1, - EC_OK = 0, - EC_POINTER_NOT_FOUND, - EC_NO_ACTIVE_CONNECTION, - EC_USER_NOT_FOUND, - EC_CHANNEL_NOT_FOUND, - EC_CONNECTION_NOT_FOUND, - EC_UNKNOWN_TRANSMISSION_MODE, - EC_AUDIO_NOT_AVAILABLE, - EC_INVALID_SAMPLE, - EC_INVALID_PLUGIN_ID, - EC_INVALID_MUTE_TARGET, - EC_CONNECTION_UNSYNCHRONIZED, - EC_INVALID_API_VERSION, - EC_UNSYNCHRONIZED_BLOB, - EC_UNKNOWN_SETTINGS_KEY, - EC_WRONG_SETTINGS_TYPE, - EC_SETTING_WAS_REMOVED, - EC_DATA_TOO_BIG, - EC_DATA_ID_TOO_LONG, + MUMBLE_EC_INTERNAL_ERROR = -2, + MUMBLE_EC_GENERIC_ERROR = -1, + MUMBLE_EC_OK = 0, + MUMBLE_EC_POINTER_NOT_FOUND, + MUMBLE_EC_NO_ACTIVE_CONNECTION, + MUMBLE_EC_USER_NOT_FOUND, + MUMBLE_EC_CHANNEL_NOT_FOUND, + MUMBLE_EC_CONNECTION_NOT_FOUND, + MUMBLE_EC_UNKNOWN_TRANSMISSION_MODE, + MUMBLE_EC_AUDIO_NOT_AVAILABLE, + MUMBLE_EC_INVALID_SAMPLE, + MUMBLE_EC_INVALID_PLUGIN_ID, + MUMBLE_EC_INVALID_MUTE_TARGET, + MUMBLE_EC_CONNECTION_UNSYNCHRONIZED, + MUMBLE_EC_INVALID_API_VERSION, + MUMBLE_EC_UNSYNCHRONIZED_BLOB, + MUMBLE_EC_UNKNOWN_SETTINGS_KEY, + MUMBLE_EC_WRONG_SETTINGS_TYPE, + MUMBLE_EC_SETTING_WAS_REMOVED, + MUMBLE_EC_DATA_TOO_BIG, + MUMBLE_EC_DATA_ID_TOO_LONG, }; /// This enum's values represent error codes specific to the framework of handling positional data /// gathering (needed for Mumble's positional audio feature). enum Mumble_PositionalDataErrorCode { /// Positional data has been initialized properly - PDEC_OK = 0, + MUMBLE_PDEC_OK = 0, /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be /// at another point in time. - PDEC_ERROR_TEMP, + MUMBLE_PDEC_ERROR_TEMP, /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). - PDEC_ERROR_PERM + MUMBLE_PDEC_ERROR_PERM }; /// This enum's values represent keys for specific settings inside Mumble. enum Mumble_SettingsKey { - MSK_INVALID = -1, - MSK_AUDIO_INPUT_VOICE_HOLD = 0, - MSK_AUDIO_INPUT_VAD_SILENCE_THRESHOLD = 1, - MSK_AUDIO_INPUT_VAD_SPEECH_THRESHOLD = 2, - MSK_AUDIO_OUTPUT_PA_MINIMUM_DISTANCE = 3, - MSK_AUDIO_OUTPUT_PA_MAXIMUM_DISTANCE = 4, - MSK_AUDIO_OUTPUT_PA_BLOOM = 5, - MSK_AUDIO_OUTPUT_PA_MINIMUM_VOLUME = 6, + MUMBLE_SK_INVALID = -1, + MUMBLE_SK_AUDIO_INPUT_VOICE_HOLD = 0, + MUMBLE_SK_AUDIO_INPUT_VAD_SILENCE_THRESHOLD = 1, + MUMBLE_SK_AUDIO_INPUT_VAD_SPEECH_THRESHOLD = 2, + MUMBLE_SK_AUDIO_OUTPUT_PA_MINIMUM_DISTANCE = 3, + MUMBLE_SK_AUDIO_OUTPUT_PA_MAXIMUM_DISTANCE = 4, + MUMBLE_SK_AUDIO_OUTPUT_PA_BLOOM = 5, + MUMBLE_SK_AUDIO_OUTPUT_PA_MINIMUM_VOLUME = 6, }; /// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. enum Mumble_KeyCode { - KC_INVALID = -1, + MUMBLE_KC_INVALID = -1, // Non-printable characters first - KC_NULL = 0, - KC_END = 1, - KC_LEFT = 2, - KC_RIGHT = 4, - KC_UP = 5, - KC_DOWN = 6, - KC_DELETE = 7, - KC_BACKSPACE = 8, - KC_TAB = 9, - KC_ENTER = 10, // == '\n' - KC_ESCAPE = 27, - KC_PAGE_UP = 11, - KC_PAGE_DOWN = 12, - KC_SHIFT = 13, - KC_CONTROL = 14, - KC_META = 15, - KC_ALT = 16, - KC_ALT_GR = 17, - KC_CAPSLOCK = 18, - KC_NUMLOCK = 19, - KC_SUPER = 20, // == windows key - KC_HOME = 21, // == Pos1 - KC_PRINT = 22, - KC_SCROLLLOCK = 23, + MUMBLE_KC_NULL = 0, + MUMBLE_KC_END = 1, + MUMBLE_KC_LEFT = 2, + MUMBLE_KC_RIGHT = 4, + MUMBLE_KC_UP = 5, + MUMBLE_KC_DOWN = 6, + MUMBLE_KC_DELETE = 7, + MUMBLE_KC_BACKSPACE = 8, + MUMBLE_KC_TAB = 9, + MUMBLE_KC_ENTER = 10, // == '\n' + MUMBLE_KC_ESCAPE = 27, + MUMBLE_KC_PAGE_UP = 11, + MUMBLE_KC_PAGE_DOWN = 12, + MUMBLE_KC_SHIFT = 13, + MUMBLE_KC_CONTROL = 14, + MUMBLE_KC_META = 15, + MUMBLE_KC_ALT = 16, + MUMBLE_KC_ALT_GR = 17, + MUMBLE_KC_CAPSLOCK = 18, + MUMBLE_KC_NUMLOCK = 19, + MUMBLE_KC_SUPER = 20, // == windows key + MUMBLE_KC_HOME = 21, // == Pos1 + MUMBLE_KC_PRINT = 22, + MUMBLE_KC_SCROLLLOCK = 23, // Printable characters are assigned to their ASCII code - KC_SPACE = ' ', - KC_EXCLAMATION_MARK = '!', - KC_DOUBLE_QUOTE = '"', - KC_HASHTAG = '#', - KC_DOLLAR = '$', - KC_PERCENT = '%', - KC_AMPERSAND = '&', - KC_SINGLE_QUOTE = '\'', - KC_OPEN_PARENTHESIS = '(', - KC_CLOSE_PARENTHESIS = ')', - KC_ASTERISK = '*', - KC_PLUS = '+', - KC_COMMA = ',', - KC_MINUS = '-', - KC_PERIOD = '.', - KC_SLASH = '/', - KC_0 = '0', - KC_1 = '1', - KC_2 = '2', - KC_3 = '3', - KC_4 = '4', - KC_5 = '5', - KC_6 = '6', - KC_7 = '7', - KC_8 = '8', - KC_9 = '9', - KC_COLON = ':', - KC_SEMICOLON = ';', - KC_LESS_THAN = '<', - KC_EQUALS = '=', - KC_GREATER_THAN = '>', - KC_QUESTION_MARK = '?', - KC_AT_SYMBOL = '@', - KC_A = 'A', - KC_B = 'B', - KC_C = 'C', - KC_D = 'D', - KC_E = 'E', - KC_F = 'F', - KC_G = 'G', - KC_H = 'H', - KC_I = 'I', - KC_J = 'J', - KC_K = 'K', - KC_L = 'L', - KC_M = 'M', - KC_N = 'N', - KC_O = 'O', - KC_P = 'P', - KC_Q = 'Q', - KC_R = 'R', - KC_S = 'S', - KC_T = 'T', - KC_U = 'U', - KC_V = 'V', - KC_W = 'W', - KC_X = 'X', - KC_Y = 'Y', - KC_Z = 'Z', + MUMBLE_KC_SPACE = ' ', + MUMBLE_KC_EXCLAMATION_MARK = '!', + MUMBLE_KC_DOUBLE_QUOTE = '"', + MUMBLE_KC_HASHTAG = '#', + MUMBLE_KC_DOLLAR = '$', + MUMBLE_KC_PERCENT = '%', + MUMBLE_KC_AMPERSAND = '&', + MUMBLE_KC_SINGLE_QUOTE = '\'', + MUMBLE_KC_OPEN_PARENTHESIS = '(', + MUMBLE_KC_CLOSE_PARENTHESIS = ')', + MUMBLE_KC_ASTERISK = '*', + MUMBLE_KC_PLUS = '+', + MUMBLE_KC_COMMA = ',', + MUMBLE_KC_MINUS = '-', + MUMBLE_KC_PERIOD = '.', + MUMBLE_KC_SLASH = '/', + MUMBLE_KC_0 = '0', + MUMBLE_KC_1 = '1', + MUMBLE_KC_2 = '2', + MUMBLE_KC_3 = '3', + MUMBLE_KC_4 = '4', + MUMBLE_KC_5 = '5', + MUMBLE_KC_6 = '6', + MUMBLE_KC_7 = '7', + MUMBLE_KC_8 = '8', + MUMBLE_KC_9 = '9', + MUMBLE_KC_COLON = ':', + MUMBLE_KC_SEMICOLON = ';', + MUMBLE_KC_LESS_THAN = '<', + MUMBLE_KC_EQUALS = '=', + MUMBLE_KC_GREATER_THAN = '>', + MUMBLE_KC_QUESTION_MARK = '?', + MUMBLE_KC_AT_SYMBOL = '@', + MUMBLE_KC_A = 'A', + MUMBLE_KC_B = 'B', + MUMBLE_KC_C = 'C', + MUMBLE_KC_D = 'D', + MUMBLE_KC_E = 'E', + MUMBLE_KC_F = 'F', + MUMBLE_KC_G = 'G', + MUMBLE_KC_H = 'H', + MUMBLE_KC_I = 'I', + MUMBLE_KC_J = 'J', + MUMBLE_KC_K = 'K', + MUMBLE_KC_L = 'L', + MUMBLE_KC_M = 'M', + MUMBLE_KC_N = 'N', + MUMBLE_KC_O = 'O', + MUMBLE_KC_P = 'P', + MUMBLE_KC_Q = 'Q', + MUMBLE_KC_R = 'R', + MUMBLE_KC_S = 'S', + MUMBLE_KC_T = 'T', + MUMBLE_KC_U = 'U', + MUMBLE_KC_V = 'V', + MUMBLE_KC_W = 'W', + MUMBLE_KC_X = 'X', + MUMBLE_KC_Y = 'Y', + MUMBLE_KC_Z = 'Z', // leave out lowercase letters (for now) - KC_OPEN_BRACKET = '[', - KC_BACKSLASH = '\\', - KC_CLOSE_BRACKET = ']', - KC_CIRCUMFLEX = '^', - KC_UNDERSCORE = '_', - KC_GRAVE_AKCENT = '`', - KC_OPEN_BRACE = '{', - KC_VERTICAL_BAR = '|', - KC_CLOSE_BRACE = '}', - KC_TILDE = '~', + MUMBLE_KC_OPEN_BRACKET = '[', + MUMBLE_KC_BACKSLASH = '\\', + MUMBLE_KC_CLOSE_BRACKET = ']', + MUMBLE_KC_CIRCUMFLEX = '^', + MUMBLE_KC_UNDERSCORE = '_', + MUMBLE_KC_GRAVE_AKCENT = '`', + MUMBLE_KC_OPEN_BRACE = '{', + MUMBLE_KC_VERTICAL_BAR = '|', + MUMBLE_KC_CLOSE_BRACE = '}', + MUMBLE_KC_TILDE = '~', // Some characters from the extended ASCII code - KC_DEGREE_SIGN = 176, + MUMBLE_KC_DEGREE_SIGN = 176, // F-keys // Start at a value of 256 as extended ASCII codes range up to 255 - KC_F1 = 256, - KC_F2 = 257, - KC_F3 = 258, - KC_F4 = 259, - KC_F5 = 260, - KC_F6 = 261, - KC_F7 = 262, - KC_F8 = 263, - KC_F9 = 264, - KC_F10 = 265, - KC_F11 = 266, - KC_F12 = 267, - KC_F13 = 268, - KC_F14 = 269, - KC_F15 = 270, - KC_F16 = 271, - KC_F17 = 272, - KC_F18 = 273, - KC_F19 = 274, + MUMBLE_KC_F1 = 256, + MUMBLE_KC_F2 = 257, + MUMBLE_KC_F3 = 258, + MUMBLE_KC_F4 = 259, + MUMBLE_KC_F5 = 260, + MUMBLE_KC_F6 = 261, + MUMBLE_KC_F7 = 262, + MUMBLE_KC_F8 = 263, + MUMBLE_KC_F9 = 264, + MUMBLE_KC_F10 = 265, + MUMBLE_KC_F11 = 266, + MUMBLE_KC_F12 = 267, + MUMBLE_KC_F13 = 268, + MUMBLE_KC_F14 = 269, + MUMBLE_KC_F15 = 270, + MUMBLE_KC_F16 = 271, + MUMBLE_KC_F17 = 272, + MUMBLE_KC_F18 = 273, + MUMBLE_KC_F19 = 274, }; /// A struct for representing a version of the form major.minor.patch -struct Version { +struct MumbleVersion { int32_t major; int32_t minor; int32_t patch; #ifdef __cplusplus - bool operator<(const Version &other) const { + bool operator<(const MumbleVersion &other) const { if (this->major != other.major) { return this->major < other.major; } @@ -252,7 +253,7 @@ struct Version { return this->patch < other.patch; } - bool operator>(const Version &other) const { + bool operator>(const MumbleVersion &other) const { if (this->major != other.major) { return this->major > other.major; } @@ -263,7 +264,7 @@ struct Version { return this->patch > other.patch; } - bool operator>=(const Version &other) const { + bool operator>=(const MumbleVersion &other) const { if (this->major != other.major) { return this->major > other.major; } @@ -274,7 +275,7 @@ struct Version { return this->patch >= other.patch; } - bool operator<=(const Version &other) const { + bool operator<=(const MumbleVersion &other) const { if (this->major != other.major) { return this->major < other.major; } @@ -285,11 +286,11 @@ struct Version { return this->patch <= other.patch; } - bool operator==(const Version &other) const { + bool operator==(const MumbleVersion &other) const { return this->major == other.major && this->minor == other.minor && this->patch == other.patch; } - bool operator!=(const Version &other) const { + bool operator!=(const MumbleVersion &other) const { return this->major != other.major || this->minor != other.minor || this->patch != other.patch; } @@ -315,47 +316,47 @@ struct Version { /// @returns The error message coresponding to the given error code. The message /// is encoded as a C-string and is static, meaning that it is safe to use the /// returned pointer in your code. -inline const char *errorMessage(int16_t errorCode) { +inline const char *mumble_errorMessage(int16_t errorCode) { switch (errorCode) { - case EC_GENERIC_ERROR: + case MUMBLE_EC_GENERIC_ERROR: return "Generic error"; - case EC_OK: + case MUMBLE_EC_OK: return "Ok - this is not an error"; - case EC_POINTER_NOT_FOUND: + case MUMBLE_EC_POINTER_NOT_FOUND: return "Can't find the passed pointer"; - case EC_NO_ACTIVE_CONNECTION: + case MUMBLE_EC_NO_ACTIVE_CONNECTION: return "There is currently no active connection to a server"; - case EC_USER_NOT_FOUND: + case MUMBLE_EC_USER_NOT_FOUND: return "Can't find the requested user"; - case EC_CHANNEL_NOT_FOUND: + case MUMBLE_EC_CHANNEL_NOT_FOUND: return "Can't find the requested channel"; - case EC_CONNECTION_NOT_FOUND: + case MUMBLE_EC_CONNECTION_NOT_FOUND: return "Can't identify the requested connection"; - case EC_UNKNOWN_TRANSMISSION_MODE: + case MUMBLE_EC_UNKNOWN_TRANSMISSION_MODE: return "Unknown transmission mode encountered"; - case EC_AUDIO_NOT_AVAILABLE: + case MUMBLE_EC_AUDIO_NOT_AVAILABLE: return "There is currently no audio output available"; - case EC_INVALID_SAMPLE: + case MUMBLE_EC_INVALID_SAMPLE: return "Attempted to use invalid sample (can't play it)"; - case EC_INVALID_PLUGIN_ID: + case MUMBLE_EC_INVALID_PLUGIN_ID: return "Used an invalid plugin ID"; - case EC_INVALID_MUTE_TARGET: + case MUMBLE_EC_INVALID_MUTE_TARGET: return "Used an invalid mute-target"; - case EC_CONNECTION_UNSYNCHRONIZED: + case MUMBLE_EC_CONNECTION_UNSYNCHRONIZED: return "The requested server connection has not yet finished synchronizing"; - case EC_INVALID_API_VERSION: + case MUMBLE_EC_INVALID_API_VERSION: return "The used API version is invalid or not supported"; - case EC_UNSYNCHRONIZED_BLOB: + case MUMBLE_EC_UNSYNCHRONIZED_BLOB: return "The requested blob (content) has not yet been synchronized between the client and the server"; - case EC_UNKNOWN_SETTINGS_KEY: + case MUMBLE_EC_UNKNOWN_SETTINGS_KEY: return "The used settings-key does not match any key known to Mumble"; - case EC_WRONG_SETTINGS_TYPE: + case MUMBLE_EC_WRONG_SETTINGS_TYPE: return "The referenced setting has a different type than requested"; - case EC_SETTING_WAS_REMOVED: + case MUMBLE_EC_SETTING_WAS_REMOVED: return "The referenced setting got removed from Mumble and is no longer used"; - case EC_DATA_TOO_BIG: + case MUMBLE_EC_DATA_TOO_BIG: return "The given data is too large (exceeds limit)"; - case EC_DATA_ID_TOO_LONG: + case MUMBLE_EC_DATA_ID_TOO_LONG: return "The given data ID is too long (exceeds limit)"; default: return "Unknown error code"; @@ -382,7 +383,7 @@ typedef enum Mumble_TalkingState mumble_talking_state_t; /// Typedef for the type of a transmission mode typedef enum Mumble_TransmissionMode mumble_transmission_mode_t; /// Typedef for the type of a version -typedef struct Version mumble_version_t; +typedef struct MumbleVersion mumble_version_t; /// Typedef for the type of a connection typedef int32_t mumble_connection_t; /// Typedef for the type of a user @@ -398,4 +399,11 @@ typedef enum Mumble_SettingsKey mumble_settings_key_t; /// Typedef for the type of a key-code typedef enum Mumble_KeyCode mumble_keycode_t; -#endif // MUMBLE_PLUGINCOMPONENT_H_ + + +/// A constant holding the exit status of a successful operation +static const mumble_error_t MUMBLE_STATUS_OK = MUMBLE_EC_OK; +/// A constant holding the version object that is considered to correspond to an unknown version +static const mumble_version_t MUMBLE_VERSION_UNKNOWN = { 0, 0, 0 }; + +#endif // EXTERNAL_MUMBLE_PLUGINCOMPONENT_H_ From 1cfde54a18de1202a0d02768f2df353eb51bb7f4 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Wed, 9 Jun 2021 20:35:51 +0200 Subject: [PATCH 078/104] Init ACRE in init function instead of in registerAPI function --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index c5649db48..fe2d75699 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -20,6 +20,14 @@ uint32_t mumble_getFeatures() { void mumble_registerAPIFunctions(void *apiStruct) { mumAPI = MUMBLE_API_CAST(apiStruct); +} + +mumble_error_t mumble_init(mumble_plugin_id_t id) { + pluginID = id; + + if (mumAPI.getActiveServerConnection(pluginID, &activeConnection) != MUMBLE_STATUS_OK) { + activeConnection = -1; + } CEngine::getInstance()->initialize(new CMumbleClient(), new CMumbleCommandServer(), FROM_PIPENAME, TO_PIPENAME); if (CEngine::getInstance() != NULL) { @@ -34,14 +42,6 @@ void mumble_registerAPIFunctions(void *apiStruct) { mumble_onServerSynchronized(activeConnection); } } -} - -mumble_error_t mumble_init(mumble_plugin_id_t id) { - pluginID = id; - - if (mumAPI.getActiveServerConnection(pluginID, &activeConnection) != MUMBLE_STATUS_OK) { - activeConnection = -1; - } return MUMBLE_STATUS_OK; } From e7bdea3dee37f34f75a0a09bb88a2dadd58326ba Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Wed, 9 Jun 2021 21:11:14 +0200 Subject: [PATCH 079/104] Implemented missing mandatory function --- extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index fe2d75699..eadf530d4 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -78,3 +78,8 @@ void mumble_shutdown() { } CEngine::getInstance()->stop(); } + +void mumble_releaseResource(const void *) { + // Nothing to do here since we never pass allocated resourced to Mumble + // that needed freeing +} From ff895357b1acef1837c9ac0a7787c3ee59140ddc Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sat, 12 Jun 2021 17:34:35 +0200 Subject: [PATCH 080/104] Use correct variable name in TRACE statement --- extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index c5ff1939b..75b0ee9bd 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -61,7 +61,7 @@ void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_use return; } - TRACE("enter: [%d],[%d]", clientID, status); + TRACE("enter: [%d],[%d]", userID, status); if ((status != MUMBLE_TS_PASSIVE) && (status != MUMBLE_TS_INVALID)) { CEngine::getInstance()->getClient()->setDirectFirst(true); From 169ae75cd17fdff4af5b005d846566a690c0d12e Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 4 Jul 2021 13:21:49 +0200 Subject: [PATCH 081/104] Make event processing async by introducing event queue --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 55 +++++---- .../MumbleCallbacks_pluginEvents.cpp | 8 +- .../ACRE2Mumble/MumbleCallbacks_speaking.cpp | 106 +++++++++--------- .../src/ACRE2Mumble/MumbleEventLoop.cpp | 63 +++++++++++ extensions/src/ACRE2Mumble/MumbleEventLoop.h | 32 ++++++ 5 files changed, 189 insertions(+), 75 deletions(-) create mode 100644 extensions/src/ACRE2Mumble/MumbleEventLoop.cpp create mode 100644 extensions/src/ACRE2Mumble/MumbleEventLoop.h diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index eadf530d4..7cccdeb00 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -3,6 +3,7 @@ #include "MumbleClient.h" #include "MumbleCommandServer.h" #include "MumbleFunctions.h" +#include "MumbleEventLoop.h" #include "compat.h" #include "helpers.h" @@ -47,36 +48,44 @@ mumble_error_t mumble_init(mumble_plugin_id_t id) { } void mumble_onServerSynchronized(mumble_connection_t connection) { - activeConnection = connection; - - // set ID on every new connection - acre::id_t clientId = 0; - // TODO: Missing error handling of API call - mumAPI.getLocalUserID(pluginID, activeConnection, (mumble_userid_t *) &clientId); - CEngine::getInstance()->getSelf()->setId(clientId); - CEngine::getInstance()->getExternalServer()->setId(clientId); - - // subscribe to all channels to receive event - if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { - CEngine::getInstance()->getClient()->start(static_cast(clientId)); - } + acre::MumbleEventLoop::getInstance().queue([connection]() { + activeConnection = connection; + + // set ID on every new connection + acre::id_t clientId = 0; + // TODO: Missing error handling of API call + mumAPI.getLocalUserID(pluginID, activeConnection, (mumble_userid_t*)&clientId); + CEngine::getInstance()->getSelf()->setId(clientId); + CEngine::getInstance()->getExternalServer()->setId(clientId); + + // subscribe to all channels to receive event + if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { + CEngine::getInstance()->getClient()->start(static_cast(clientId)); + } + }); } void mumble_onServerDisconnected(mumble_connection_t connection) { - activeConnection = -1; + acre::MumbleEventLoop::getInstance().queue([connection]() { + activeConnection = -1; - if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && - (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { - CEngine::getInstance()->getClient()->stop(); - } + if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && + (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { + CEngine::getInstance()->getClient()->stop(); + } + }); } void mumble_shutdown() { - if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && - (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { - CEngine::getInstance()->getClient()->stop(); - } - CEngine::getInstance()->stop(); + acre::MumbleEventLoop::getInstance().queue([]() { + if ((CEngine::getInstance()->getClient()->getState() != acre::State::stopped) && + (CEngine::getInstance()->getClient()->getState() != acre::State::stopping)) { + CEngine::getInstance()->getClient()->stop(); + } + CEngine::getInstance()->stop(); + }); + + acre::MumbleEventLoop::getInstance().stop(); } void mumble_releaseResource(const void *) { diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp index f242f1456..035c16b87 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_pluginEvents.cpp @@ -1,6 +1,7 @@ #include "Engine.h" #include "Log.h" #include "MumbleFunctions.h" +#include "MumbleEventLoop.h" #include "compat.h" // @@ -8,8 +9,11 @@ // bool mumble_onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const uint8_t *data, size_t dataLength, const char *dataID) { if ((dataLength > 0U) && CEngine::getInstance()->getExternalServer()) { - // TODO: Cast is probably unnecessary - CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *) data, dataLength); + // Copy data to make sure it stays available in the async processing + std::string dataString(reinterpret_cast(data), dataLength); + acre::MumbleEventLoop::getInstance().queue([dataString]() { + CEngine::getInstance()->getExternalServer()->handleMessage((unsigned char *)dataString.data(), dataString.size()); + }); return true; } return false; diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp index 75b0ee9bd..2fe03c5b2 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_speaking.cpp @@ -2,6 +2,7 @@ #include "Log.h" #include "Macros.h" #include "MumbleClient.h" +#include "MumbleEventLoop.h" #include "Types.h" #include "compat.h" @@ -9,68 +10,73 @@ // Mumble Speaking callbacks // void mumble_onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, mumble_talking_state_t status) { - TRACE("mumble_onUserTalkingStateChanged ENTER: %d", status); - if (static_cast(userID) != CEngine::getInstance()->getSelf()->getId()) { - return; - } - - if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { - return; - } + acre::MumbleEventLoop::getInstance().queue([connection, userID, status]() { + TRACE("mumble_onUserTalkingStateChanged ENTER: %d", status); + if (static_cast(userID) != CEngine::getInstance()->getSelf()->getId()) { + return; + } - if (!CEngine::getInstance()->getGameServer()) { - return; - } + if (CEngine::getInstance()->getClient()->getState() != acre::State::running) { + return; + } - if (CEngine::getInstance()->getState() != acre::State::running) { - return; - } + if (!CEngine::getInstance()->getGameServer()) { + return; + } - if (!CEngine::getInstance()->getGameServer()->getConnected()) { - return; - } + if (CEngine::getInstance()->getState() != acre::State::running) { + return; + } - CEngine::getInstance()->getClient()->setSpeakingState(status); - if (CEngine::getInstance()->getSoundSystemOverride()) { - return; - } + if (!CEngine::getInstance()->getGameServer()->getConnected()) { + return; + } - if (CEngine::getInstance()->getClient()->getOnRadio()) { - if (CEngine::getInstance()->getClient()->getVAD()) { + CEngine::getInstance()->getClient()->setSpeakingState(status); + if (CEngine::getInstance()->getSoundSystemOverride()) { return; } - if (status == MUMBLE_TS_PASSIVE || status == MUMBLE_TS_INVALID) { - if ((!CEngine::getInstance()->getClient()->getRadioPTTDown()) - && (!CEngine::getInstance()->getClient()->getGodPTTDown()) - && (!CEngine::getInstance()->getClient()->getZeusPTTDown())) { - CEngine::getInstance()->getClient()->setOnRadio(false); - } else { - if (!CEngine::getInstance()->getClient()->getDirectFirst()) { - CEngine::getInstance()->getClient()->microphoneOpen(true); - } else { - CEngine::getInstance()->getClient()->setDirectFirst(false); - if ((CEngine::getInstance()->getClient()->getRadioPTTDown()) - || (CEngine::getInstance()->getClient()->getGodPTTDown()) - || (CEngine::getInstance()->getClient()->getZeusPTTDown())) { + if (CEngine::getInstance()->getClient()->getOnRadio()) { + if (CEngine::getInstance()->getClient()->getVAD()) { + return; + } + + if (status == MUMBLE_TS_PASSIVE || status == MUMBLE_TS_INVALID) { + if ((!CEngine::getInstance()->getClient()->getRadioPTTDown()) + && (!CEngine::getInstance()->getClient()->getGodPTTDown()) + && (!CEngine::getInstance()->getClient()->getZeusPTTDown())) { + CEngine::getInstance()->getClient()->setOnRadio(false); + } + else { + if (!CEngine::getInstance()->getClient()->getDirectFirst()) { CEngine::getInstance()->getClient()->microphoneOpen(true); } + else { + CEngine::getInstance()->getClient()->setDirectFirst(false); + if ((CEngine::getInstance()->getClient()->getRadioPTTDown()) + || (CEngine::getInstance()->getClient()->getGodPTTDown()) + || (CEngine::getInstance()->getClient()->getZeusPTTDown())) { + CEngine::getInstance()->getClient()->microphoneOpen(true); + } + } } } - } - return; - } - TRACE("enter: [%d],[%d]", userID, status); + return; + } + TRACE("enter: [%d],[%d]", userID, status); - if ((status != MUMBLE_TS_PASSIVE) && (status != MUMBLE_TS_INVALID)) { - CEngine::getInstance()->getClient()->setDirectFirst(true); - CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::direct); - } else { - CEngine::getInstance()->getClient()->setDirectFirst(false); - CEngine::getInstance()->getClient()->localStopSpeaking(acre::Speaking::direct); - CEngine::getInstance()->getClient()->setMainPTTDown(false); - CEngine::getInstance()->getClient()->setGodPTTDown(false); - CEngine::getInstance()->getClient()->setZeusPTTDown(false); - } + if ((status != MUMBLE_TS_PASSIVE) && (status != MUMBLE_TS_INVALID)) { + CEngine::getInstance()->getClient()->setDirectFirst(true); + CEngine::getInstance()->getClient()->localStartSpeaking(acre::Speaking::direct); + } + else { + CEngine::getInstance()->getClient()->setDirectFirst(false); + CEngine::getInstance()->getClient()->localStopSpeaking(acre::Speaking::direct); + CEngine::getInstance()->getClient()->setMainPTTDown(false); + CEngine::getInstance()->getClient()->setGodPTTDown(false); + CEngine::getInstance()->getClient()->setZeusPTTDown(false); + } + }); } diff --git a/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp b/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp new file mode 100644 index 000000000..080ba0e64 --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp @@ -0,0 +1,63 @@ +#include "MumbleEventLoop.h" + +namespace acre { + + MumbleEventLoop& MumbleEventLoop::getInstance() { + static MumbleEventLoop loop; + + return loop; + } + + MumbleEventLoop::MumbleEventLoop() : m_thread(&MumbleEventLoop::run, this) { + } + + void MumbleEventLoop::stop() { + { + std::lock_guard guard(m_lock); + m_keepRunning = false; + } + + m_waiter.notify_all(); + + // Wait until the worker thread has finished + m_thread.join(); + } + + void MumbleEventLoop::queue(const std::function& callable) { + { + std::lock_guard guard(m_lock); + + m_queuedFunctions.push_back(callable); + } + + m_waiter.notify_all(); + } + + void MumbleEventLoop::queue(std::function&& callable) { + { + std::unique_lock guard(m_lock); + + m_queuedFunctions.push_back(std::move(callable)); + } + + m_waiter.notify_all(); + } + + void MumbleEventLoop::run() { + std::unique_lock guard(m_lock); + + while (m_keepRunning) { + // Process all pending events + while (!m_queuedFunctions.empty()) { + std::function currentFunc = std::move(m_queuedFunctions.front()); + m_queuedFunctions.pop_front(); + + currentFunc(); + } + + // Wait for something to happen. Note that during the waiting the lock is released and + // re-aquired once the waiting ends + m_waiter.wait(guard); + } + } +} diff --git a/extensions/src/ACRE2Mumble/MumbleEventLoop.h b/extensions/src/ACRE2Mumble/MumbleEventLoop.h new file mode 100644 index 000000000..2bfe6ed62 --- /dev/null +++ b/extensions/src/ACRE2Mumble/MumbleEventLoop.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace acre { + + class MumbleEventLoop { + public: + MumbleEventLoop(); + + static MumbleEventLoop& getInstance(); + + void stop(); + + void queue(const std::function& callable); + void queue(std::function&& callable); + + protected: + std::mutex m_lock; + std::condition_variable m_waiter; + bool m_keepRunning = true; + std::deque> m_queuedFunctions; + std::thread m_thread; + + void run(); + }; + +} From b72aca68160f349820cb02f619f6201f5f6025cc Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 7 Nov 2021 19:00:15 +0100 Subject: [PATCH 082/104] Fix deadlock in plugin 169ae75cd17fdff4af5b005d846566a690c0d12e introduced the MumbleEventLoop class, which was supposed to make the processing of Mumble callbacks asynchronous. However, the loop was keeping the lock when executing queued callbacks and if such a callback was to use a Mumble API function while Mumble's main thread was currently executing one of the plugin callbacks within ACRE, this API call would block. If the active callback now tried to queue a new event, this would block as well, since the event queue was still holding the lock for processing that function. Thus, a deadlock occured. Given that the timing had to be right for this to happen, the deadlocks were now much less common than they were before the introduction of the event queue, but with a bit of patience, they could still be created. The solution is to simply release the lock while executing the currently processed function in the event loop. This allows simultaneous queueing of new events withouot blocking. --- extensions/src/ACRE2Mumble/MumbleEventLoop.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp b/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp index 080ba0e64..da7f19712 100644 --- a/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp +++ b/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp @@ -52,7 +52,14 @@ namespace acre { std::function currentFunc = std::move(m_queuedFunctions.front()); m_queuedFunctions.pop_front(); + // Execute the current funtion. However, during the time this function is executing, there is no need to + // keep holding m_lock. By releasing it for that time, we allow further functions to be queued by other threads. + // This gets especially important if the called function will call a Mumble API function. This function will require + // to run in Mumble's main thread but if that thread is in turn waiting until a new event is queued (in one of the + // plugin callbacks in this plugin), we end up with a deadlock. + guard.unlock(); currentFunc(); + guard.lock(); } // Wait for something to happen. Note that during the waiting the lock is released and From 698b500b892c582a313811ee6377ad5ff0369675 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sat, 18 Dec 2021 19:04:52 +0100 Subject: [PATCH 083/104] Fix crash due to double-join Joining a thread makes it unjoinable. Attempting to join it again will throw an exception, which (due to not being handled) will crash Mumble. This situation would be created by loading, unloading, loading and unloading ACRE because the used EventLoop instance is a singleton that will survive the reloads. However, the used thread object will be invalid after the second load. The solution is to simply make starting the thread explicit instead of implicitly starting it as soon as the loop is instantiated. --- .../src/ACRE2Mumble/MumbleEventLoop.cpp | 21 ++++++++++++++++--- extensions/src/ACRE2Mumble/MumbleEventLoop.h | 1 + 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp b/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp index da7f19712..a5057e8b9 100644 --- a/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp +++ b/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp @@ -8,7 +8,20 @@ namespace acre { return loop; } - MumbleEventLoop::MumbleEventLoop() : m_thread(&MumbleEventLoop::run, this) { + MumbleEventLoop::MumbleEventLoop() { + } + + void MumbleEventLoop::start() { + if (m_thread.joinable()) { + throw std::runtime_error("ACRE2 - MumbleEventLoop: Attempted to start already-running event loop. Must call stop first."); + } + + { + std::lock_guard guard(m_lock); + m_keepRunning = true; + } + + m_thread = std::thread(&MumbleEventLoop::run, this); } void MumbleEventLoop::stop() { @@ -19,8 +32,10 @@ namespace acre { m_waiter.notify_all(); - // Wait until the worker thread has finished - m_thread.join(); + if (m_thread.joinable()) { + // Wait until the worker thread has finished + m_thread.join(); + } } void MumbleEventLoop::queue(const std::function& callable) { diff --git a/extensions/src/ACRE2Mumble/MumbleEventLoop.h b/extensions/src/ACRE2Mumble/MumbleEventLoop.h index 2bfe6ed62..599880a29 100644 --- a/extensions/src/ACRE2Mumble/MumbleEventLoop.h +++ b/extensions/src/ACRE2Mumble/MumbleEventLoop.h @@ -14,6 +14,7 @@ namespace acre { static MumbleEventLoop& getInstance(); + void start(); void stop(); void queue(const std::function& callable); From 1fcf1d8a53435c31a930c82837d29e084cefc188 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:11:14 +0100 Subject: [PATCH 084/104] Removed unneeded todo notes --- extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp | 4 +--- extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 7cccdeb00..4e7ed3f95 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -11,9 +11,8 @@ #define TO_PIPENAME "\\\\.\\pipe\\acre_comm_pipe_toTS" extern MumbleAPI_v_1_0_x mumAPI; -// TODO: Should these special values be a named variable? mumble_connection_t activeConnection = -1; -mumble_plugin_id_t pluginID = -1; +mumble_plugin_id_t pluginID = -1; uint32_t mumble_getFeatures() { return MUMBLE_FEATURE_AUDIO; @@ -53,7 +52,6 @@ void mumble_onServerSynchronized(mumble_connection_t connection) { // set ID on every new connection acre::id_t clientId = 0; - // TODO: Missing error handling of API call mumAPI.getLocalUserID(pluginID, activeConnection, (mumble_userid_t*)&clientId); CEngine::getInstance()->getSelf()->setId(clientId); CEngine::getInstance()->getExternalServer()->setId(clientId); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 372a83a91..2c325b007 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -17,7 +17,6 @@ using LIMITER = std::numeric_limits; bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, uint32_t sampleRate, bool isSpeech, mumble_userid_t userID) { - // TODO: Do you need this for something? (void) sampleRate; if (CEngine::getInstance()->getSoundSystemOverride()) { From d38608e36a64cf8ecdfe2e175f515e34a3fcfbbe Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:12:31 +0100 Subject: [PATCH 085/104] Added some status logs for start/stop --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index b617968f6..01788d50b 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -47,7 +47,10 @@ acre::Result CMumbleClient::stop() { this->m_versionThreadHandle.join(); } this->setState(acre::State::stopped); + + mumAPI.log(pluginID, "stopped"); } + return acre::Result::ok; } @@ -67,6 +70,8 @@ acre::Result CMumbleClient::start(const acre::id_t id_) { // this->m_versionThreadHandle = std::thread(&CMumbleClient::exPersistVersion, this); + mumAPI.log(pluginID, "started"); + return acre::Result::ok; } From 513d54d2c5189d0363e4bdff2ed8c429d08b6149 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:12:52 +0100 Subject: [PATCH 086/104] Fix API call for freeing memory --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 01788d50b..9879da6c2 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -342,7 +342,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { } } - mumAPI.freeMemory(pluginID, (void *) &channelList); + mumAPI.freeMemory(pluginID, channelList); mumble_channelid_t bestChannelId = invalid_mumble_channel; int32_t bestMatches = 0; From 376829c8576c9785917d69c57d6de4e8dc1f396e Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:13:47 +0100 Subject: [PATCH 087/104] Fix deadlock caused by not releasing lock on early return --- extensions/src/ACRE2Mumble/MumbleCommandServer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index f4779b79d..09e3a0063 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -4,6 +4,8 @@ #include "MumbleFunctions.h" #include "TextMessage.h" +#include + extern MumbleAPI_v_1_0_x mumAPI; extern mumble_connection_t activeConnection; extern mumble_plugin_id_t pluginID; @@ -21,7 +23,7 @@ acre::Result CMumbleCommandServer::shutdown() { } acre::Result CMumbleCommandServer::sendMessage(IMessage *msg) { - LOCK(this); + std::lock_guard guard(*this); mumble_userid_t *channelUsers = nullptr; size_t userCount = 0U; @@ -52,8 +54,6 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg) { delete msg; - UNLOCK(this); - return acre::Result::ok; } From b71299aabb3c630aa82162bd69e665ec604db785 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:14:16 +0100 Subject: [PATCH 088/104] Improved error logging --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 4 ++-- extensions/src/ACRE2Mumble/MumbleCommandServer.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 9879da6c2..16083c597 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -243,9 +243,9 @@ acre::Result CMumbleClient::microphoneOpen(bool status_) { const mumble_error_t res = mumAPI.requestMicrophoneActivationOvewrite(pluginID, status_); if (res != MUMBLE_STATUS_OK) { if (status_) { - LOG("Error toggling PTT Open\n"); + LOG("Error toggling PTT Open: %s (%d)\n", mumble_errorMessage(res), res); } else { - LOG("Error toggling PTT Closed\n"); + LOG("Error toggling PTT Closed: %s (%d)\n", mumble_errorMessage(res), res); } return acre::Result::error; diff --git a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp index 09e3a0063..2729f6d16 100644 --- a/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCommandServer.cpp @@ -31,24 +31,24 @@ acre::Result CMumbleCommandServer::sendMessage(IMessage *msg) { mumble_error_t err = mumAPI.getChannelOfUser(pluginID, activeConnection, this->getId(), ¤tChannel); if (err != MUMBLE_STATUS_OK) { - LOG("ERROR, UNABLE TO GET CHANNEL OF USER: %d", err); + LOG("ERROR, UNABLE TO GET CHANNEL OF USER: %s (%d)", mumble_errorMessage(err), err); return acre::Result::error; } err = mumAPI.getUsersInChannel(pluginID, activeConnection, currentChannel, &channelUsers, &userCount); if (err != MUMBLE_STATUS_OK) { - LOG("ERROR, UNABLE TO GET USERS IN CHANNEL: %d", err); + LOG("ERROR, UNABLE TO GET USERS IN CHANNEL: %s (%d)", mumble_errorMessage(err), err); return acre::Result::error; } err = mumAPI.sendData(pluginID, activeConnection, channelUsers, userCount, (const uint8_t *) msg->getData(), msg->getLength(), "ACRE2"); if (err != MUMBLE_STATUS_OK) { - LOG("ERROR, UNABLE TO SEND MESSAGE DATA: %d", err); + LOG("ERROR, UNABLE TO SEND MESSAGE DATA: %s (%d)", mumble_errorMessage(err), err); return acre::Result::error; } err = mumAPI.freeMemory(pluginID, (void *) channelUsers); if (err != MUMBLE_STATUS_OK) { - LOG("ERROR, UNABLE TO FREE CHANNEL USER LIST: %d", err); + LOG("ERROR, UNABLE TO FREE CHANNEL USER LIST: %s (%d)", mumble_errorMessage(err), err); return acre::Result::error; } From 63f0e6e957c50f44470f40122028b25f395e3e7c Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:15:51 +0100 Subject: [PATCH 089/104] Update to latest API headers --- .../ACRE2Mumble/MumbleCallbacks_static.cpp | 4 + extensions/src/ACRE2Mumble/MumbleFunctions.h | 3 +- .../mumble_includes/MumbleAPI_v_1_0_x.h | 994 +++++++++--------- .../mumble_includes/MumblePlugin_v_1_0_x.h | 428 -------- .../mumble_includes/MumblePlugin_v_1_1_x.h | 477 +++++++++ .../PluginComponents_v_1_0_x.h | 585 ++++++----- 6 files changed, 1277 insertions(+), 1214 deletions(-) delete mode 100644 extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_0_x.h create mode 100644 extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_1_x.h diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp index 36ca681bf..aab0ac8e0 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -29,3 +29,7 @@ mumble_version_t mumble_getAPIVersion() { mumble_version_t mumble_getVersion() { return mumble_version_t{ACRE_VERSION_MAJOR, ACRE_VERSION_MINOR, ACRE_VERSION_SUBMINOR}; } + +mumble_version_t mumble_getPluginFunctionsVersion() { + return MUMBLE_PLUGIN_FUNCTIONS_VERSION; +} diff --git a/extensions/src/ACRE2Mumble/MumbleFunctions.h b/extensions/src/ACRE2Mumble/MumbleFunctions.h index 9a7725877..c5860ab87 100644 --- a/extensions/src/ACRE2Mumble/MumbleFunctions.h +++ b/extensions/src/ACRE2Mumble/MumbleFunctions.h @@ -1,4 +1,5 @@ #pragma once #include "MumbleAPI_v_1_0_x.h" -#include "MumblePlugin_v_1_0_x.h" +#define MUMBLE_PLUGIN_NO_DEFAULT_FUNCTION_DEFINITIONS +#include "MumblePlugin_v_1_1_x.h" diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h index 4471680a1..1b8b722b6 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h @@ -15,13 +15,13 @@ // API version #define MUMBLE_PLUGIN_API_MAJOR_MACRO 1 #define MUMBLE_PLUGIN_API_MINOR_MACRO 0 -#define MUMBLE_PLUGIN_API_PATCH_MACRO 0 +#define MUMBLE_PLUGIN_API_PATCH_MACRO 3 -const int32_t MUMBLE_PLUGIN_API_MAJOR = MUMBLE_PLUGIN_API_MAJOR_MACRO; -const int32_t MUMBLE_PLUGIN_API_MINOR = MUMBLE_PLUGIN_API_MINOR_MACRO; -const int32_t MUMBLE_PLUGIN_API_PATCH = MUMBLE_PLUGIN_API_PATCH_MACRO; +const int32_t MUMBLE_PLUGIN_API_MAJOR = MUMBLE_PLUGIN_API_MAJOR_MACRO; +const int32_t MUMBLE_PLUGIN_API_MINOR = MUMBLE_PLUGIN_API_MINOR_MACRO; +const int32_t MUMBLE_PLUGIN_API_PATCH = MUMBLE_PLUGIN_API_PATCH_MACRO; const mumble_version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MUMBLE_PLUGIN_API_MINOR, - MUMBLE_PLUGIN_API_PATCH }; + MUMBLE_PLUGIN_API_PATCH }; // Create macro for casting the pointer to the API object to the proper struct. // Note that this must only be used if the API uses MUMBLE_PLUGIN_API_VERSION of the API. @@ -34,497 +34,499 @@ const mumble_version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MU struct MumbleAPI_v_1_0_x { - ///////////////////////////////////////////////////////// - ////////////////////// GENERAL NOTES //////////////////// - ///////////////////////////////////////////////////////// - // - // All functions that take in a connection as a paremeter may only be called **after** the connection - // has finished synchronizing. The only exception from this is isConnectionSynchronized. - // - // Strings returned by the API are UTF-8 encoded - // Strings passed to the API are expected to be UTF-8 encoded - // - // All API functions are synchronized and will be executed in Mumble's "main thread" from which most plugin - // callbacks are called as well. Note however that an API call is BLOCKING if invoked from a different - // thread. This means that they can cause deadlocks if used without caution. An example that will lead - // to a deadlock is: - // - plugin callback gets called from the main thread - // - callback messages a separate thread to do something and waits for the action to have completed - // - Separate thread calls an API function - // - The function blocks and waits to be executed in the main thread which is currently blocked waiting - // - deadlock - - - // -------- Memory management -------- - - /// Frees the given pointer. - /// - /// @param callerID The ID of the plugin calling this function - /// @param pointer The pointer to free - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *freeMemory)(mumble_plugin_id_t callerID, const void *pointer); - - - - // -------- Getter functions -------- - - /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] connection A pointer to the memory location the ID should be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access - /// the value of the provided pointer - mumble_error_t(PLUGIN_CALLING_CONVENTION *getActiveServerConnection)(mumble_plugin_id_t callerID, - mumble_connection_t *connection); - - /// Checks whether the given connection has finished initializing yet. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished - /// synchronization yet after this function has executed successfully. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *isConnectionSynchronized)(mumble_plugin_id_t callerID, - mumble_connection_t connection, - bool *synchronized); - - /// Fills in the information about the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getLocalUserID)(mumble_plugin_id_t callerID, - mumble_connection_t connection, mumble_userid_t *userID); - - /// Fills in the information about the given user's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The user's ID whose name should be obtained - /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. - /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getUserName)(mumble_plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, const char **userName); - - /// Fills in the information about the given channel's name. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The channel's ID whose name should be obtained - /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. - /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getChannelName)(mumble_plugin_id_t callerID, - mumble_connection_t connection, - mumble_channelid_t channelID, const char **channelName); - - /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the - /// out-parameter will prevent that property to be set/allocated. If you are only interested in the user count you - /// can thus pass nullptr as the users parameter and save time on allocating + freeing the channels-array while - /// still getting the size out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getAllUsers)(mumble_plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t **users, size_t *userCount); - - /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent - /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as - /// the channels parameter and save time on allocating + freeing the channels-array while still getting the size - /// out. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getAllChannels)(mumble_plugin_id_t callerID, - mumble_connection_t connection, - mumble_channelid_t **channels, size_t *channelCount); - - /// Gets the ID of the channel the given user is currently connected to. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] A pointer to where the ID of the channel shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getChannelOfUser)(mumble_plugin_id_t callerID, - mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t *channel); - - /// Gets an array of all users in the specified channel. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelID The ID of the channel whose users shall be retrieved - /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated - /// memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if - /// this function returns STATUS_OK. - /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getUsersInChannel)(mumble_plugin_id_t callerID, - mumble_connection_t connection, - mumble_channelid_t channelID, - mumble_userid_t **userList, size_t *userCount); - - /// Gets the current transmission mode of the local user. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getLocalUserTransmissionMode)( - mumble_plugin_id_t callerID, mumble_transmission_mode_t *transmissionMode); - - /// Checks whether the given user is currently locally muted. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to check for - /// @param[out] muted A pointer to where the local mute state of that user shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *isUserLocallyMuted)(mumble_plugin_id_t callerID, - mumble_connection_t connection, - mumble_userid_t userID, bool *muted); - - /// Checks whether the local user is currently muted. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] muted A pointer to where the mute state of the local user shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *isLocalUserMuted)(mumble_plugin_id_t callerID, bool *muted); - - /// Checks whether the local user is currently deafened. - /// - /// @param callerID The ID of the plugin calling this function - /// @param[out] deafened A pointer to where the deaf state of the local user shall be written - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *isLocalUserDeafened)(mumble_plugin_id_t callerID, bool *deafened); - - /// Gets the hash of the given user (can be used to recognize users between restarts) - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user to search for - /// @param[out] hash A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getUserHash)(mumble_plugin_id_t callerID, mumble_connection_t connection, - mumble_userid_t userID, const char **hash); - - /// Gets the hash of the server for the given connection (can be used to recognize servers between restarts) - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection - /// @param[out] hash A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getServerHash)(mumble_plugin_id_t callerID, - mumble_connection_t connection, const char **hash); - - /// Gets the comment of the given user. Note that a user might have a comment configured that hasn't been - /// synchronized to this client yet. In this case this function will return EC_UNSYNCHRONIZED_BLOB. As of now there - /// is now way to request the synchronization to happen via the Plugin-API. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection - /// @param userID the ID of the user whose comment should be obtained - /// @param[out] comment A pointer to where the pointer to the allocated string (C-encoded) should be written to. The - /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getUserComment)(mumble_plugin_id_t callerID, - mumble_connection_t connection, mumble_userid_t userID, - const char **comment); - - /// Gets the description of the given channel. Note that a channel might have a description configured that hasn't - /// been synchronized to this client yet. In this case this function will return EC_UNSYNCHRONIZED_BLOB. As of now - /// there is now way to request the synchronization to happen via the Plugin-API. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection - /// @param channelID the ID of the channel whose comment should be obtained - /// @param[out] description A pointer to where the pointer to the allocated string (C-encoded) should be written to. - /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be - /// allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *getChannelDescription)(mumble_plugin_id_t callerID, - mumble_connection_t connection, - mumble_channelid_t channelID, - const char **description); - - - // -------- Request functions -------- - - /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily - /// set the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the - /// work of restoring the previous state afterwards. - /// - /// @param callerID The ID of the plugin calling this function - /// @param transmissionMode The requested transmission mode - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *requestLocalUserTransmissionMode)( - mumble_plugin_id_t callerID, mumble_transmission_mode_t transmissionMode); - - /// Requests Mumble to move the given user into the given channel - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be moved - /// @param channelID The ID of the channel to move the user to - /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target - /// channel does not require a password for entering - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *requestUserMove)(mumble_plugin_id_t callerID, - mumble_connection_t connection, mumble_userid_t userID, - mumble_channelid_t channelID, const char *password); - - /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user - /// had chosen the continous transmission mode). If a plugin requests this overwrite, it is responsible for - /// deactivating the overwrite again once it is no longer required - /// - /// @param callerID The ID of the plugin calling this function - /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *requestMicrophoneActivationOvewrite)(mumble_plugin_id_t callerID, - bool activate); - - /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute - /// state opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client - /// has muted its microphone and thus isn't transmitting any audio). Furthermore it must be noted that muting the - /// local user with this function does not work (it doesn't make sense). If you try to do so, this function will - /// fail. In order to make this work, this function will also fail if the server has not finished synchronizing with - /// the client yet. For muting the local user, use requestLocalUserMute instead. - /// - /// @param callerID The ID of the plugin calling this function. - /// @param connection The ID of the server-connection to use as a context - /// @param userID The ID of the user that shall be muted - /// @param muted Whether to locally mute the given client (opposed to unmuting it) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *requestLocalMute)(mumble_plugin_id_t callerID, - mumble_connection_t connection, mumble_userid_t userID, - bool muted); - - /// Requests Mumble to set the mute state of the local user. In the UI this is referred to as "self-mute". - /// - /// @param callerID The ID of the plugin calling this function. - /// @param muted Whether to locally mute the local user (opposed to unmuting it) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *requestLocalUserMute)(mumble_plugin_id_t callerID, bool muted); - - /// Requests Mumble to set the deaf state of the local user. In the UI this is referred to as "self-deaf". - /// - /// @param callerID The ID of the plugin calling this function. - /// @param deafened Whether to locally deafen the local user (opposed to undeafening it) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *requestLocalUserDeaf)(mumble_plugin_id_t callerID, bool deafened); - - /// Sets the comment of the local user - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection - /// @param comment The new comment to use (C-encoded). A subset of HTML formatting is supported. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer - /// may be accessed - mumble_error_t(PLUGIN_CALLING_CONVENTION *requestSetLocalUserComment)(mumble_plugin_id_t callerID, - mumble_connection_t connection, - const char *comment); - - - - // -------- Find functions -------- - - /// Fills in the information about a user with the specified name, if such a user exists. The search is - /// case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param userName The respective user's name - /// @param[out] userID A pointer to the memory the user's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION *findUserByName)(mumble_plugin_id_t callerID, - mumble_connection_t connection, const char *userName, - mumble_userid_t *userID); - - /// Fills in the information about a channel with the specified name, if such a channel exists. The search is - /// case-sensitive. - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to use as a context - /// @param channelName The respective channel's name - /// @param[out] channelID A pointer to the memory the channel's ID shall be written to - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION *findChannelByName)(mumble_plugin_id_t callerID, - mumble_connection_t connection, - const char *channelName, - mumble_channelid_t *channelID); - - - - // -------- Settings -------- - - /// Fills in the current value of the setting with the given key. Note that this function can only be used for - /// settings whose value is a bool! - /// - /// @param callerID The ID of the plugin calling this function - /// @param key The key to the desired setting - /// @param[out] outValue A pointer to the memory the setting's value shall be written to. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION *getMumbleSetting_bool)(mumble_plugin_id_t callerID, - mumble_settings_key_t key, bool *outValue); - - /// Fills in the current value of the setting with the given key. Note that this function can only be used for - /// settings whose value is an int! - /// - /// @param callerID The ID of the plugin calling this function - /// @param key The key to the desired setting - /// @param[out] outValue A pointer to the memory the setting's value shall be written to. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION *getMumbleSetting_int)(mumble_plugin_id_t callerID, - mumble_settings_key_t key, int64_t *outValue); - - /// Fills in the current value of the setting with the given key. Note that this function can only be used for - /// settings whose value is a double! - /// - /// @param callerID The ID of the plugin calling this function - /// @param key The key to the desired setting - /// @param[out] outValue A pointer to the memory the setting's value shall be written to. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION *getMumbleSetting_double)(mumble_plugin_id_t callerID, - mumble_settings_key_t key, double *outValue); - - /// Fills in the current value of the setting with the given key. Note that this function can only be used for - /// settings whose value is a String! - /// - /// @param callerID The ID of the plugin calling this function - /// @param key The key to the desired setting - /// @param[out] outValue The memory address to which the pointer to the setting's value (the String) will be - /// written. The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will - /// only be allocated if this function returns STATUS_OK. - /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may - /// be accessed. - mumble_error_t(PLUGIN_CALLING_CONVENTION *getMumbleSetting_string)(mumble_plugin_id_t callerID, - mumble_settings_key_t key, - const char **outValue); - - - /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose - /// value is a bool! - /// - /// @param callerID The ID of the plugin calling this function - /// @param key The key to the desired setting - /// @param value The value that should be set for the given setting - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *setMumbleSetting_bool)(mumble_plugin_id_t callerID, - mumble_settings_key_t key, bool value); - - /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose - /// value is an int! - /// - /// @param callerID The ID of the plugin calling this function - /// @param key The key to the desired setting - /// @param value The value that should be set for the given setting - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *setMumbleSetting_int)(mumble_plugin_id_t callerID, - mumble_settings_key_t key, int64_t value); - - /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose - /// value is a double! - /// - /// @param callerID The ID of the plugin calling this function - /// @param key The key to the desired setting - /// @param value The value that should be set for the given setting - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *setMumbleSetting_double)(mumble_plugin_id_t callerID, - mumble_settings_key_t key, double value); - - /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose - /// value is a string! - /// - /// @param callerID The ID of the plugin calling this function - /// @param key The key to the desired setting - /// @param value The value that should be set for the given setting - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *setMumbleSetting_string)(mumble_plugin_id_t callerID, - mumble_settings_key_t key, const char *value); - - - - // -------- Miscellaneous -------- - - /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin - /// active on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the - /// sent data must not contain sensitive information or anything else that shouldn't be known by others. - /// - /// NOTE: Messages sent via this API function are rate-limited by the server. If the rate-limit is hit, the message - /// will be dropped without an error message. The rate-limiting is global (e.g. it doesn't matter which plugin sent - /// the respective messages - they all count to the same limit). - /// Therefore if you have multiple messages to send, you should consider sending them asynchronously one at a time - /// with a little delay in between (~1 second). - /// - /// @param callerID The ID of the plugin calling this function - /// @param connection The ID of the server-connection to send the data through (the server the given users are on) - /// @param users An array of user IDs to send the data to - /// @param userCount The size of the provided user-array - /// @param data The data array that shall be sent. This can be an arbitrary sequence of bytes. Note that the size of - /// is restricted to <= 1KB. - /// @param dataLength The length of the data array - /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do - /// with the data. This has to be a C-encoded String. It is recommended that the ID starts with a plugin-specific - /// prefix in order to avoid name clashes. Note that the size of this string is restricted to <= 100 bytes. - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *sendData)(mumble_plugin_id_t callerID, mumble_connection_t connection, - const mumble_userid_t *users, size_t userCount, - const uint8_t *data, size_t dataLength, const char *dataID); - - /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. - /// - /// @param callerID The ID of the plugin calling this function - /// @param message The message to log - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *log)(mumble_plugin_id_t callerID, const char *message); - - /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported - /// by it in order for this to work out (see http://www.mega-nerd.com/libsndfile/). - /// - /// @param callerID The ID of the plugin calling this function - /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) - /// @returns The error code. If everything went well, STATUS_OK will be returned. - mumble_error_t(PLUGIN_CALLING_CONVENTION *playSample)(mumble_plugin_id_t callerID, const char *samplePath); + ///////////////////////////////////////////////////////// + ////////////////////// GENERAL NOTES //////////////////// + ///////////////////////////////////////////////////////// + // + // All functions that take in a connection as a paremeter may only be called **after** the connection + // has finished synchronizing. The only exception from this is isConnectionSynchronized. + // + // Strings returned by the API are UTF-8 encoded + // Strings passed to the API are expected to be UTF-8 encoded + // + // All API functions are synchronized and will be executed in Mumble's "main thread" from which most plugin + // callbacks are called as well. Note however that an API call is BLOCKING if invoked from a different + // thread. This means that they can cause deadlocks if used without caution. An example that will lead + // to a deadlock is: + // - plugin callback gets called from the main thread + // - callback messages a separate thread to do something and waits for the action to have completed + // - Separate thread calls an API function + // - The function blocks and waits to be executed in the main thread which is currently blocked waiting + // - deadlock + + + // -------- Memory management -------- + + /// Frees the given pointer. + /// + /// @param callerID The ID of the plugin calling this function + /// @param pointer The pointer to free + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* freeMemory)(mumble_plugin_id_t callerID, const void* pointer); + + + + // -------- Getter functions -------- + + /// Gets the connection ID of the server the user is currently active on (the user's audio output is directed at). + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] connection A pointer to the memory location the ID should be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then it is valid to access + /// the value of the provided pointer + mumble_error_t(PLUGIN_CALLING_CONVENTION* getActiveServerConnection)(mumble_plugin_id_t callerID, + mumble_connection_t* connection); + + /// Checks whether the given connection has finished initializing yet. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] A pointer to the boolean variable that'll hold the info whether the server has finished + /// synchronization yet after this function has executed successfully. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* isConnectionSynchronized)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + bool* synchronized); + + /// Fills in the information about the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserID)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t* userID); + + /// Fills in the information about the given user's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The user's ID whose name should be obtained + /// @param[out] userName A pointer to where the pointer to the allocated string (C-encoded) should be written to. + /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getUserName)(mumble_plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, const char** userName); + + /// Fills in the information about the given channel's name. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The channel's ID whose name should be obtained + /// @param[out] channelName A pointer to where the pointer to the allocated string (C-ecoded) should be written to. + /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelName)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_channelid_t channelID, const char** channelName); + + /// Gets an array of all users that are currently connected to the provided server. Passing a nullptr as any of the + /// out-parameter will prevent that property to be set/allocated. If you are only interested in the user count you + /// can thus pass nullptr as the users parameter and save time on allocating + freeing the channels-array while + /// still getting the size out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] users A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllUsers)(mumble_plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t** users, size_t* userCount); + + /// Gets an array of all channels on the provided server. Passing a nullptr as any of the out-parameter will prevent + /// that property to be set/allocated. If you are only interested in the channel count you can thus pass nullptr as + /// the channels parameter and save time on allocating + freeing the channels-array while still getting the size + /// out. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param[out] channels A pointer to where the pointer of the allocated array shall be written. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @param[out] channelCount A pointer to where the size of the allocated channel-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getAllChannels)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_channelid_t** channels, size_t* channelCount); + + /// Gets the ID of the channel the given user is currently connected to. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] A pointer to where the ID of the channel shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelOfUser)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t* channel); + + /// Gets an array of all users in the specified channel. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelID The ID of the channel whose users shall be retrieved + /// @param[out] userList A pointer to where the pointer of the allocated array shall be written. The allocated + /// memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be allocated if + /// this function returns STATUS_OK. + /// @param[out] userCount A pointer to where the size of the allocated user-array shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getUsersInChannel)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_channelid_t channelID, + mumble_userid_t** userList, size_t* userCount); + + /// Gets the current transmission mode of the local user. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] transmissionMode A pointer to where the transmission mode shall be written. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getLocalUserTransmissionMode)( + mumble_plugin_id_t callerID, mumble_transmission_mode_t* transmissionMode); + + /// Checks whether the given user is currently locally muted. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to check for + /// @param[out] muted A pointer to where the local mute state of that user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* isUserLocallyMuted)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_userid_t userID, bool* muted); + + /// Checks whether the local user is currently muted. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] muted A pointer to where the mute state of the local user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* isLocalUserMuted)(mumble_plugin_id_t callerID, bool* muted); + + /// Checks whether the local user is currently deafened. + /// + /// @param callerID The ID of the plugin calling this function + /// @param[out] deafened A pointer to where the deaf state of the local user shall be written + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* isLocalUserDeafened)(mumble_plugin_id_t callerID, bool* deafened); + + /// Gets the hash of the given user (can be used to recognize users between restarts) + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user to search for + /// @param[out] hash A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getUserHash)(mumble_plugin_id_t callerID, mumble_connection_t connection, + mumble_userid_t userID, const char** hash); + + /// Gets the hash of the server for the given connection (can be used to recognize servers between restarts) + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection + /// @param[out] hash A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getServerHash)(mumble_plugin_id_t callerID, + mumble_connection_t connection, const char** hash); + + /// Gets the comment of the given user. Note that a user might have a comment configured that hasn't been + /// synchronized to this client yet. In this case this function will return EC_UNSYNCHRONIZED_BLOB. As of now there + /// is now way to request the synchronization to happen via the Plugin-API. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection + /// @param userID the ID of the user whose comment should be obtained + /// @param[out] comment A pointer to where the pointer to the allocated string (C-encoded) should be written to. The + /// allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getUserComment)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t userID, + const char** comment); + + /// Gets the description of the given channel. Note that a channel might have a description configured that hasn't + /// been synchronized to this client yet. In this case this function will return EC_UNSYNCHRONIZED_BLOB. As of now + /// there is now way to request the synchronization to happen via the Plugin-API. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection + /// @param channelID the ID of the channel whose comment should be obtained + /// @param[out] description A pointer to where the pointer to the allocated string (C-encoded) should be written to. + /// The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will only be + /// allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* getChannelDescription)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + mumble_channelid_t channelID, + const char** description); + + + // -------- Request functions -------- + + /// Requests Mumble to set the local user's transmission mode to the specified one. If you only need to temporarily + /// set the transmission mode to continous, use requestMicrophoneActivationOverwrite instead as this saves you the + /// work of restoring the previous state afterwards. + /// + /// @param callerID The ID of the plugin calling this function + /// @param transmissionMode The requested transmission mode + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalUserTransmissionMode)( + mumble_plugin_id_t callerID, mumble_transmission_mode_t transmissionMode); + + /// Requests Mumble to move the given user into the given channel + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be moved + /// @param channelID The ID of the channel to move the user to + /// @param password The password of the target channel (UTF-8 encoded as a C-string). Pass NULL if the target + /// channel does not require a password for entering + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestUserMove)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t userID, + mumble_channelid_t channelID, const char* password); + + /// Requests Mumble to overwrite the microphone activation so that the microphone is always on (same as if the user + /// had chosen the continous transmission mode). If a plugin requests this overwrite, it is responsible for + /// deactivating the overwrite again once it is no longer required + /// + /// @param callerID The ID of the plugin calling this function + /// @param activate Whether to activate the overwrite (false deactivates an existing overwrite) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestMicrophoneActivationOvewrite)(mumble_plugin_id_t callerID, + bool activate); + + /// Requests Mumble to set the local mute state of the given client. Note that this only affects the **local** mute + /// state opposed to a server-mute (client is globally muted by the server) or the client's own mute-state (client + /// has muted its microphone and thus isn't transmitting any audio). Furthermore it must be noted that muting the + /// local user with this function does not work (it doesn't make sense). If you try to do so, this function will + /// fail. In order to make this work, this function will also fail if the server has not finished synchronizing with + /// the client yet. For muting the local user, use requestLocalUserMute instead. + /// + /// @param callerID The ID of the plugin calling this function. + /// @param connection The ID of the server-connection to use as a context + /// @param userID The ID of the user that shall be muted + /// @param muted Whether to locally mute the given client (opposed to unmuting it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalMute)(mumble_plugin_id_t callerID, + mumble_connection_t connection, mumble_userid_t userID, + bool muted); + + /// Requests Mumble to set the mute state of the local user. In the UI this is referred to as "self-mute". + /// + /// @param callerID The ID of the plugin calling this function. + /// @param muted Whether to locally mute the local user (opposed to unmuting it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalUserMute)(mumble_plugin_id_t callerID, bool muted); + + /// Requests Mumble to set the deaf state of the local user. In the UI this is referred to as "self-deaf". + /// + /// @param callerID The ID of the plugin calling this function. + /// @param deafened Whether to locally deafen the local user (opposed to undeafening it) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestLocalUserDeaf)(mumble_plugin_id_t callerID, bool deafened); + + /// Sets the comment of the local user + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection + /// @param comment The new comment to use (C-encoded). A subset of HTML formatting is supported. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer + /// may be accessed + mumble_error_t(PLUGIN_CALLING_CONVENTION* requestSetLocalUserComment)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + const char* comment); + + + + // -------- Find functions -------- + + /// Fills in the information about a user with the specified name, if such a user exists. The search is + /// case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param userName The respective user's name + /// @param[out] userID A pointer to the memory the user's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* findUserByName)(mumble_plugin_id_t callerID, + mumble_connection_t connection, const char* userName, + mumble_userid_t* userID); + + /// Fills in the information about a channel with the specified name, if such a channel exists. The search is + /// case-sensitive. + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to use as a context + /// @param channelName The respective channel's name + /// @param[out] channelID A pointer to the memory the channel's ID shall be written to + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* findChannelByName)(mumble_plugin_id_t callerID, + mumble_connection_t connection, + const char* channelName, + mumble_channelid_t* channelID); + + + + // -------- Settings -------- + + /// Fills in the current value of the setting with the given key. Note that this function can only be used for + /// settings whose value is a bool! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param[out] outValue A pointer to the memory the setting's value shall be written to. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* getMumbleSetting_bool)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, bool* outValue); + + /// Fills in the current value of the setting with the given key. Note that this function can only be used for + /// settings whose value is an int! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param[out] outValue A pointer to the memory the setting's value shall be written to. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* getMumbleSetting_int)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, int64_t* outValue); + + /// Fills in the current value of the setting with the given key. Note that this function can only be used for + /// settings whose value is a double! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param[out] outValue A pointer to the memory the setting's value shall be written to. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* getMumbleSetting_double)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, double* outValue); + + /// Fills in the current value of the setting with the given key. Note that this function can only be used for + /// settings whose value is a String! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param[out] outValue The memory address to which the pointer to the setting's value (the String) will be + /// written. The allocated memory has to be freed by a call to freeMemory by the plugin eventually. The memory will + /// only be allocated if this function returns STATUS_OK. + /// @returns The error code. If everything went well, STATUS_OK will be returned. Only then the passed pointer may + /// be accessed. + mumble_error_t(PLUGIN_CALLING_CONVENTION* getMumbleSetting_string)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, + const char** outValue); + + + /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose + /// value is a bool! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param value The value that should be set for the given setting + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* setMumbleSetting_bool)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, bool value); + + /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose + /// value is an int! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param value The value that should be set for the given setting + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* setMumbleSetting_int)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, int64_t value); + + /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose + /// value is a double! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param value The value that should be set for the given setting + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* setMumbleSetting_double)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, double value); + + /// Sets the value of the setting with the given key. Note that this function can only be used for settings whose + /// value is a string! + /// + /// @param callerID The ID of the plugin calling this function + /// @param key The key to the desired setting + /// @param value The value that should be set for the given setting + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* setMumbleSetting_string)(mumble_plugin_id_t callerID, + mumble_settings_key_t key, const char* value); + + + + // -------- Miscellaneous -------- + + /// Sends the provided data to the provided client(s). This kind of data can only be received by another plugin + /// active on that client. The sent data can be seen by any active plugin on the receiving client. Therefore the + /// sent data must not contain sensitive information or anything else that shouldn't be known by others. + /// + /// NOTE: Messages sent via this API function are rate-limited by the server. If the rate-limit is hit, the message + /// will be dropped without an error message. The rate-limiting is global (e.g. it doesn't matter which plugin sent + /// the respective messages - they all count to the same limit). + /// Therefore if you have multiple messages to send, you should consider sending them asynchronously one at a time + /// with a little delay in between (~1 second). + /// + /// @param callerID The ID of the plugin calling this function + /// @param connection The ID of the server-connection to send the data through (the server the given users are on) + /// @param users An array of user IDs to send the data to + /// @param userCount The size of the provided user-array + /// @param data The data array that shall be sent. This can be an arbitrary sequence of bytes. Note that the size of + /// is restricted to <= 1KB. + /// @param dataLength The length of the data array + /// @param dataID The ID of the sent data. This has to be used by the receiving plugin(s) to figure out what to do + /// with the data. This has to be a C-encoded String. It is recommended that the ID starts with a plugin-specific + /// prefix in order to avoid name clashes. Note that the size of this string is restricted to <= 100 bytes. + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* sendData)(mumble_plugin_id_t callerID, mumble_connection_t connection, + const mumble_userid_t* users, size_t userCount, + const uint8_t* data, size_t dataLength, const char* dataID); + + /// Logs the given message (typically to Mumble's console). All passed strings have to be UTF-8 encoded. + /// + /// @param callerID The ID of the plugin calling this function + /// @param message The message to log + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* log)(mumble_plugin_id_t callerID, const char* message); + + /// Plays the provided sample. It uses libsndfile as a backend so the respective file format needs to be supported + /// by it in order for this to work out (see http://www.mega-nerd.com/libsndfile/). + /// + /// @param callerID The ID of the plugin calling this function + /// @param samplePath The path to the sample that shall be played (UTF-8 encoded) + /// @returns The error code. If everything went well, STATUS_OK will be returned. + mumble_error_t(PLUGIN_CALLING_CONVENTION* playSample)(mumble_plugin_id_t callerID, const char* samplePath); }; +typedef struct MumbleAPI_v_1_0_x mumble_api_t; + #endif // EXTERNAL_MUMBLE_PLUGIN_API_H_ diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_0_x.h deleted file mode 100644 index afb2eee3f..000000000 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_0_x.h +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright 2021 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -/// This header file specifies the Mumble plugin interface - -#ifndef EXTERNAL_MUMBLE_PLUGIN_H_ -#define EXTERNAL_MUMBLE_PLUGIN_H_ - -#include "MumbleAPI_v_1_0_x.h" -#include "PluginComponents_v_1_0_x.h" -#include -#include -#include - -#if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems -# define PLUGIN_EXPORT __attribute__((visibility("default"))) -#elif defined(_MSC_VER) -# define PLUGIN_EXPORT __declspec(dllexport) -#elif defined(__MINGW32__) -# define PLUGIN_EXPORT __attribute__((dllexport)) -#else -# error No PLUGIN_EXPORT definition available -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -////////////////////////////////////////////////////////////////////////////////// -////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// -////////////////////////////////////////////////////////////////////////////////// - -/// Gets called right after loading the plugin in order to let the plugin initialize. -/// -/// Registers the ID of this plugin. -/// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with -/// and by which this plugin can identify itself when communicating with Mumble. -/// @returns The status of the initialization. If everything went fine, return STATUS_OK -PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_plugin_id_t id); - -/// Gets called when unloading the plugin in order to allow it to clean up after itself. -/// Note that it is still safe to call API functions from within this callback. -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); - -/// Gets the name of the plugin. -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @returns A String-wrapper containing the requested name -PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getName(); - -/// Gets the Version of the plugin-API this plugin intends to use. -/// Mumble will decide whether this plugin is loadable or not based on the return value of this function. -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @returns The respective API Version -PLUGIN_EXPORT mumble_version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); - -/// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used -/// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use -/// of it at some point. -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @param api A pointer to the MumbleAPI struct. The API struct must be cast to the version corresponding to the -/// user API version. If your plugin is e.g. using the 1.0.x API, then you have to cast this pointer to -/// MumbleAPI_v_1_0_x. Note also that you **must not store this pointer**. It will become invalid. Therefore -/// you have to copy the struct in order to use it later on. -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(void *apiStruct); - -/// Releases the resource pointed to by the given pointer. If the respective resource has been allocated before, -/// this would be the time to free/delete it. -/// The resources processed by this functions are only those that have been specifically allocated in order to return -/// them in one of the plugin functions to Mumble (e.g. the String returned by mumble_getName) and has nothing to do -/// with your plugin's internal resource management. -/// In short: Only resources passed from the plugin to Mumble via a return value may be processed by this function. -/// -/// NOTE1: This function may be called without the plugin being loaded -/// -/// NOTE2: that the pointer might be pointing to memory that had to be allocated without the plugin being loaded. -/// Therefore you should be very sure that there'll be another callback in which you want to free this memory, -/// should you decide to not do it here (which is hereby explicitly advised against). -/// -/// NOTE3: The pointer is const as Mumble won't mess with the memory allocated by the plugin (no modifications). -/// Nontheless this function is explicitly responsible for freeing the respective memory parts. If the memory has -/// been allocated using malloc(), it needs to be freed using free() which requires a const-cast. If however the -/// memory has been created using the new operator you have to cast the pointer back to its original type and then -/// use the delete operator on it (no const-cast necessary in this case). -/// See https://stackoverflow.com/questions/2819535/unable-to-free-const-pointers-in-c -/// and https://stackoverflow.com/questions/941832/is-it-safe-to-delete-a-void-pointer -/// -/// @param pointer The pointer to the memory that needs free-ing -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_releaseResource(const void *pointer); - - - -////////////////////////////////////////////////////////////////////////////////// -///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////// - -/// Tells the plugin some basic information about the Mumble client loading it. -/// This function will be the first one that is being called on this plugin - even before it is decided whether to load -/// the plugin at all. -/// -/// @param mumbleVersion The Version of the Mumble client -/// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with -/// @param minimumExpectedAPIVersion The minimum Version the Mumble clients expects this plugin to meet in order to load -/// it -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(mumble_version_t mumbleVersion, - mumble_version_t mumbleAPIVersion, - mumble_version_t minimumExpectedAPIVersion); - -/// Gets the Version of this plugin -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @returns The plugin's version -PLUGIN_EXPORT mumble_version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); - -/// Gets the name of the plugin author(s). -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @returns A String-wrapper containing the requested author name(s) -PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getAuthor(); - -/// Gets the description of the plugin. -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @returns A String-wrapper containing the requested description -PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getDescription(); - -/// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the -/// Mumble_PluginFeature enum together. -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @returns The feature set of this plugin -PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); - -/// Requests this plugin to deactivate the given (sub)set of provided features. -/// If this is not possible, the features that can't be deactivated shall be returned by this function. -/// -/// Example (check if FEATURE_POSITIONAL shall be deactivated): -/// @code -/// if (features & FEATURE_POSITIONAL) { -/// // positional shall be deactivated -/// }; -/// @endcode -/// -/// @param features The feature set that shall be deactivated -/// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return -/// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. -PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); - - - -////////////////////////////////////////////////////////////////////////////////// -//////////////////////////// POSITIONAL DATA ///////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////// -// If this plugin wants to provide positional data, ALL functions of this category -// have to be implemented - -/// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is -/// currently able to do so and allocate memory that is needed for that process. As a parameter this function gets an -/// array of names and an array of PIDs. They are of same length and the PID at index i belongs to a program whose name -/// is listed at index i in the "name-array". -/// -/// @param programNames An array of pointers to the program names -/// @param programPIDs An array of the corresponding program PIDs -/// @param programCount The length of programNames and programPIDs -/// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start -/// frequently calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is -/// (currently) uncapable of providing positional data. In this case this function must not have allocated any memory -/// that needs to be cleaned up later on. Depending on the returned error code, Mumble might try to call this function -/// again at some point. -PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char *const *programNames, - const uint64_t *programPIDs, - size_t programCount); - -/// Retrieves the positional data. If no data can be fetched, set all float-vectors to 0 and return false. -/// -/// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame -/// world. One unit represents one meter of distance. -/// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar -/// ingame (where it is facing). -/// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to -/// its head. One unit represents one meter of distance. -/// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. -/// One unit represents one meter of distance. -/// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame -/// (where it is facing). -/// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One -/// unit represents one meter of distance. -/// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided -/// positional data shall be written. This context should include information about the server (and team) the player is -/// on. Only players with identical context will be able to hear each other's audio. The returned pointer has to remain -/// valid until the next invokation of this function or until shutdownPositionalData is called. -/// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall -/// be written. It can be polled by external scripts from the server and should uniquely identify the player in the -/// game. The pointer has to remain valid until the next invokation of this function or until shutdownPositionalData is -/// called. -/// @returns Whether this plugin can continue delivering positional data. If this function returns false, -/// shutdownPositionalData will be called. -PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float *avatarPos, float *avatarDir, - float *avatarAxis, float *cameraPos, - float *cameraDir, float *cameraAxis, - const char **context, const char **identity); - -/// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this -/// purpose should be freed at this point. -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); - - - -////////////////////////////////////////////////////////////////////////////////// -////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// -////////////////////////////////////////////////////////////////////////////////// - -/// Called when connecting to a server. -/// Note that in most cases you'll want to use mumble_onServerSynchronized instead. -/// Note also that this callback will be called from a DIFFERENT THREAD! -/// -/// @param connection The ID of the newly established server-connection -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); - -/// Called when disconnecting from a server. -/// Note that this callback is called from a DIFFERENT THREAD! -/// -/// @param connection The ID of the server-connection that has been terminated -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); - -/// Called when the client has finished synchronizing with the server -/// -/// @param connection The ID of the server-connection that has been terminated -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); - -/// Called whenever any user on the server enters a channel -/// This function will also be called when freshly connecting to a server as each user on that -/// server needs to be "added" to the respective channel as far as the local client is concerned. -/// -/// @param connection The ID of the server-connection this event is connected to -/// @param userID The ID of the user this event has been triggered for -/// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no -/// previous channel (e.g. the user freshly connected to the server) or the channel isn't available because of any other -/// reason. -/// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be -/// retrieved. This means that the ID is invalid. -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, - mumble_userid_t userID, - mumble_channelid_t previousChannelID, - mumble_channelid_t newChannelID); - -/// Called whenever a user leaves a channel. -/// This includes a client disconnecting from the server as this will also lead to the user not being in that channel -/// anymore. -/// -/// @param connection The ID of the server-connection this event is connected to -/// @param userID The ID of the user that left the channel -/// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. -/// This means that the ID is invalid. -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, - mumble_userid_t userID, - mumble_channelid_t channelID); - -/// Called when any user changes his/her talking state. -/// -/// @param connection The ID of the server-connection this event is connected to -/// @param userID The ID of the user whose talking state has been changed -/// @param talkingState The new TalkingState the user has switched to. -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, - mumble_userid_t userID, - mumble_talking_state_t talkingState); - -/// Called whenever there is audio input. -/// Note that this callback will be called from the AUDIO THREAD. -/// Note also that blocking this callback will cause Mumble's audio processing to get suspended. -/// -/// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its -/// length is sampleCount * channelCount. The PCM format for stereo input is [LRLRLR...] where L and R are samples of -/// the left and right channel respectively. -/// @param sampleCount The amount of sample points per channel -/// @param channelCount The amount of channels in the audio -/// @param sampleRate The used sample rate in Hz -/// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of -/// background noise) -/// @returns Whether this callback has modified the audio input-array -PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short *inputPCM, uint32_t sampleCount, - uint16_t channelCount, uint32_t sampleRate, - bool isSpeech); - -/// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). -/// The provided audio buffer is the raw buffer without any processing applied to it yet. -/// Note that this callback will be called from the AUDIO THREAD. -/// Note also that blocking this callback will cause Mumble's audio processing to get suspended. -/// -/// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. -/// Its length is sampleCount * channelCount. The PCM format for stereo output is [LRLRLR...] where L and R are samples -/// of the left and right channel respectively. -/// @param sampleCount The amount of sample points per channel -/// @param channelCount The amount of channels in the audio -/// @param sampleRate The used sample rate in Hz -/// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) -/// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is -/// false, the content of this parameter is unspecified and should not be accessed -/// @returns Whether this callback has modified the audio output-array -PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, - uint16_t channelCount, uint32_t sampleRate, - bool isSpeech, mumble_userid_t userID); - -/// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). -/// Note that this happens immediately before Mumble clips the audio buffer. -/// Note that this callback will be called from the AUDIO THREAD. -/// Note also that blocking this callback will cause Mumble's audio processing to get suspended. -/// -/// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. -/// Its length is sampleCount * channelCount. The PCM format for stereo output is [LRLRLR...] where L and R are samples -/// of the left and right channel respectively. -/// @param sampleCount The amount of sample points per channel -/// @param channelCount The amount of channels in the audio -/// @param sampleRate The used sample rate in Hz -/// @returns Whether this callback has modified the audio output-array -PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, - uint16_t channelCount, - uint32_t sampleRate); - -/// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the -/// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended -/// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. -/// -/// @param connection The ID of the server-connection the data is coming from -/// @param sender The ID of the user whose client's plugin has sent the data -/// @param data The sent data array. This can be an arbitrary sequence of bytes. -/// @param dataLength The length of the data array -/// @param dataID The ID of this data (C-encoded) -/// @return Whether the given data has been processed by this plugin -PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, - mumble_userid_t sender, const uint8_t *data, - size_t dataLength, const char *dataID); - -/// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the -/// server the local user is on but also when the local user connects to a server other clients are already connected to -/// (in this case this method will be called for every client already on that server). -/// -/// @param connection An object used to identify the current connection -/// @param userID The ID of the user that has been added - -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); - -/// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the -/// local user is on but also when the local user disconnects from a server other clients are connected to (in this case -/// this method will be called for every client on that server). -/// -/// @param connection An object used to identify the current connection -/// @param userID The ID of the user that has been removed -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, - mumble_userid_t userID); - -/// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server -/// the local user is on but also when the local user connects to a server that contains channels other than the -/// root-channel (in this case this method will be called for ever non-root channel on that server). -/// -/// @param connection An object used to identify the current connection -/// @param channelID The ID of the channel that has been added -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, - mumble_channelid_t channelID); - -/// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the -/// local user is on but also when the local user disconnects from a server that contains channels other than the -/// root-channel (in this case this method will be called for ever non-root channel on that server). -/// -/// @param connection An object used to identify the current connection -/// @param channelID The ID of the channel that has been removed -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, - mumble_channelid_t channelID); - -/// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial -/// name is also considered renaming). -/// -/// @param connection An object used to identify the current connection -/// @param channelID The ID of the channel that has been renamed -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, - mumble_channelid_t channelID); - -/// Called when a key has been pressed or released while Mumble has keyboard focus. -/// Note that this callback will only work if the user has explicitly given permission to monitor keyboard -/// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to -/// enable that. -/// -/// @param keyCode The key code of the respective key. The character codes are defined -/// via the Mumble_KeyCode enum. For printable 7-bit ASCII characters these codes conform -/// to the ASCII code-page with the only difference that case is not distinguished. Therefore -/// always the upper-case letter code will be used for letters. -/// @param wasPres Whether the respective key has been pressed (instead of released) -PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); - - - -////////////////////////////////////////////////////////////////////////////////// -////////////////////////////// PLUGIN UPDATES //////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////// - -/// This function is used to determine whether the plugin can find an update for itself that is available for download. -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @return Whether the plugin was able to find an update for itself -PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); - -/// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. -/// -/// NOTE: This function may be called without the plugin being loaded -/// -/// @returns A String-wrapper containing the requested URL -PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(); - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_1_x.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_1_x.h new file mode 100644 index 000000000..0d646ac86 --- /dev/null +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_1_x.h @@ -0,0 +1,477 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +/// This header file specifies the Mumble plugin interface + +#ifndef EXTERNAL_MUMBLE_PLUGIN_H_ +#define EXTERNAL_MUMBLE_PLUGIN_H_ + +#include "PluginComponents_v_1_0_x.h" +#include +#include +#include + +#if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems +# define PLUGIN_EXPORT __attribute__((visibility("default"))) +#elif defined(_MSC_VER) +# define PLUGIN_EXPORT __declspec(dllexport) +#elif defined(__MINGW32__) +# define PLUGIN_EXPORT __attribute__((dllexport)) +#else +# error No PLUGIN_EXPORT definition available +#endif + + +// Plugin functions version +#define MUMBLE_PLUGIN_FUNCTIONS_MAJOR_MACRO 1 +#define MUMBLE_PLUGIN_FUNCTIONS_MINOR_MACRO 1 +#define MUMBLE_PLUGIN_FUNCTIONS_PATCH_MACRO 0 + +const int32_t MUMBLE_PLUGIN_FUNCTIONS_MAJOR = MUMBLE_PLUGIN_FUNCTIONS_MAJOR_MACRO; +const int32_t MUMBLE_PLUGIN_FUNCTIONS_MINOR = MUMBLE_PLUGIN_FUNCTIONS_MINOR_MACRO; +const int32_t MUMBLE_PLUGIN_FUNCTIONS_PATCH = MUMBLE_PLUGIN_FUNCTIONS_PATCH_MACRO; +const mumble_version_t MUMBLE_PLUGIN_FUNCTIONS_VERSION = { MUMBLE_PLUGIN_FUNCTIONS_MAJOR, MUMBLE_PLUGIN_FUNCTIONS_MINOR, + MUMBLE_PLUGIN_FUNCTIONS_PATCH }; + +#ifdef __cplusplus +extern "C" { +#endif + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// MANDATORY FUNCTIONS /////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Gets called right after loading the plugin in order to let the plugin initialize. + /// + /// Registers the ID of this plugin. + /// @param id The ID for this plugin. This is the ID Mumble will reference this plugin with + /// and by which this plugin can identify itself when communicating with Mumble. + /// @returns The status of the initialization. If everything went fine, return STATUS_OK + PLUGIN_EXPORT mumble_error_t PLUGIN_CALLING_CONVENTION mumble_init(mumble_plugin_id_t id); + + /// Gets called when unloading the plugin in order to allow it to clean up after itself. + /// Note that it is still safe to call API functions from within this callback. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdown(); + + /// Gets the name of the plugin. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @returns A String-wrapper containing the requested name + PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getName(); + + /// Gets the Version of the plugin-API this plugin intends to use. + /// Mumble will decide whether this plugin is loadable or not based on the return value of this function. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @returns The respective API Version + PLUGIN_EXPORT mumble_version_t PLUGIN_CALLING_CONVENTION mumble_getAPIVersion(); + + /// Provides the MumbleAPI struct to the plugin. This struct contains function pointers that can be used + /// to interact with the Mumble client. It is up to the plugin to store this struct somewhere if it wants to make use + /// of it at some point. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @param api A pointer to the MumbleAPI struct. The API struct must be cast to the version corresponding to the + /// user API version. If your plugin is e.g. using the 1.0.x API, then you have to cast this pointer to + /// MumbleAPI_v_1_0_x. Note also that you **must not store this pointer**. It will become invalid. Therefore + /// you have to copy the struct in order to use it later on. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_registerAPIFunctions(void* apiStruct); + + /// Releases the resource pointed to by the given pointer. If the respective resource has been allocated before, + /// this would be the time to free/delete it. + /// The resources processed by this functions are only those that have been specifically allocated in order to return + /// them in one of the plugin functions to Mumble (e.g. the String returned by mumble_getName) and has nothing to do + /// with your plugin's internal resource management. + /// In short: Only resources passed from the plugin to Mumble via a return value may be processed by this function. + /// + /// NOTE1: This function may be called without the plugin being loaded + /// + /// NOTE2: that the pointer might be pointing to memory that had to be allocated without the plugin being loaded. + /// Therefore you should be very sure that there'll be another callback in which you want to free this memory, + /// should you decide to not do it here (which is hereby explicitly advised against). + /// + /// NOTE3: The pointer is const as Mumble won't mess with the memory allocated by the plugin (no modifications). + /// Nontheless this function is explicitly responsible for freeing the respective memory parts. If the memory has + /// been allocated using malloc(), it needs to be freed using free() which requires a const-cast. If however the + /// memory has been created using the new operator you have to cast the pointer back to its original type and then + /// use the delete operator on it (no const-cast necessary in this case). + /// See https://stackoverflow.com/questions/2819535/unable-to-free-const-pointers-in-c + /// and https://stackoverflow.com/questions/941832/is-it-safe-to-delete-a-void-pointer + /// + /// @param pointer The pointer to the memory that needs free-ing + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_releaseResource(const void* pointer); + + + + ////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// GENERAL FUNCTIONS ////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Tells the plugin some basic information about the Mumble client loading it. + /// This function will be the first one that is being called on this plugin - even before it is decided whether to load + /// the plugin at all. + /// + /// @param mumbleVersion The Version of the Mumble client + /// @param mumbleAPIVersion The Version of the plugin-API the Mumble client runs with + /// @param minimumExpectedAPIVersion The minimum Version the Mumble clients expects this plugin to meet in order to load + /// it + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_setMumbleInfo(mumble_version_t mumbleVersion, + mumble_version_t mumbleAPIVersion, + mumble_version_t minimumExpectedAPIVersion); + + /// Gets the Version of this plugin + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @returns The plugin's version + PLUGIN_EXPORT mumble_version_t PLUGIN_CALLING_CONVENTION mumble_getVersion(); + + /// Gets the name of the plugin author(s). + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @returns A String-wrapper containing the requested author name(s) + PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getAuthor(); + + /// Gets the description of the plugin. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @returns A String-wrapper containing the requested description + PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getDescription(); + + /// Gets the feature set of this plugin. The feature set is described by bitwise or'ing the elements of the + /// Mumble_PluginFeature enum together. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @returns The feature set of this plugin + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_getFeatures(); + + /// Requests this plugin to deactivate the given (sub)set of provided features. + /// If this is not possible, the features that can't be deactivated shall be returned by this function. + /// + /// Example (check if FEATURE_POSITIONAL shall be deactivated): + /// @code + /// if (features & FEATURE_POSITIONAL) { + /// // positional shall be deactivated + /// }; + /// @endcode + /// + /// @param features The feature set that shall be deactivated + /// @returns The feature set that can't be disabled (bitwise or'ed). If all requested features can be disabled, return + /// FEATURE_NONE. If none of the requested features can be disabled return the unmodified features parameter. + PLUGIN_EXPORT uint32_t PLUGIN_CALLING_CONVENTION mumble_deactivateFeatures(uint32_t features); + + + + ////////////////////////////////////////////////////////////////////////////////// + //////////////////////////// POSITIONAL DATA ///////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // If this plugin wants to provide positional data, the mumble_initPositionalData, mumble_fetchPositionalData + // and mumble_shutdownPositionalData functions have to be implemented together (implementing only a subset + // will yield the same result as if no support for positional data was implemened). + + /// Indicates that Mumble wants to use this plugin to request positional data. Therefore it should check whether it is + /// currently able to do so and allocate memory that is needed for that process. As a parameter this function gets an + /// array of names and an array of PIDs. They are of same length and the PID at index i belongs to a program whose name + /// is listed at index i in the "name-array". + /// + /// @param programNames An array of pointers to the program names + /// @param programPIDs An array of the corresponding program PIDs + /// @param programCount The length of programNames and programPIDs + /// @returns The error code. If everything went fine PDEC_OK shall be returned. In that case Mumble will start + /// frequently calling fetchPositionalData. If this returns anything but PDEC_OK, Mumble will assume that the plugin is + /// (currently) uncapable of providing positional data. In this case this function must not have allocated any memory + /// that needs to be cleaned up later on. Depending on the returned error code, Mumble might try to call this function + /// again at some point. + PLUGIN_EXPORT uint8_t PLUGIN_CALLING_CONVENTION mumble_initPositionalData(const char* const* programNames, + const uint64_t* programPIDs, + size_t programCount); + + /// Retrieves the positional data. If no data can be fetched, set all float-vectors to 0 and return false. + /// + /// @param[out] avatarPos A float-array of size 3 representing the cartesian position of the player/avatar in the ingame + /// world. One unit represents one meter of distance. + /// @param[out] avatarDir A float-array of size 3 representing the cartesian direction-vector of the player/avatar + /// ingame (where it is facing). + /// @param[out] avatarAxis A float-array of size 3 representing the vector pointing from the toes of the character to + /// its head. One unit represents one meter of distance. + /// @param[out] cameraPos A float-array of size 3 representing the cartesian position of the camera in the ingame world. + /// One unit represents one meter of distance. + /// @param[out] cameraDir A float-array of size 3 representing the cartesian direction-vector of the camera ingame + /// (where it is facing). + /// @param[out] cameraAxis A float-array of size 3 representing a vector from the bottom of the camera to its top. One + /// unit represents one meter of distance. + /// @param[out] context A pointer to where the pointer to a C-encoded string storing the context of the provided + /// positional data shall be written. This context should include information about the server (and team) the player is + /// on. Only players with identical context will be able to hear each other's audio. The returned pointer has to remain + /// valid until the next invokation of this function or until shutdownPositionalData is called. + /// @param[out] identity A pointer to where the pointer to a C-encoded string storing the identity of the player shall + /// be written. It can be polled by external scripts from the server and should uniquely identify the player in the + /// game. The pointer has to remain valid until the next invokation of this function or until shutdownPositionalData is + /// called. + /// @returns Whether this plugin can continue delivering positional data. If this function returns false, + /// shutdownPositionalData will be called. + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_fetchPositionalData(float* avatarPos, float* avatarDir, + float* avatarAxis, float* cameraPos, + float* cameraDir, float* cameraAxis, + const char** context, const char** identity); + + /// Indicates that this plugin will not be asked for positional data any longer. Thus any memory allocated for this + /// purpose should be freed at this point. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_shutdownPositionalData(); + + /// The context in positional data is used to determine whether different positional data sets from different + /// clients belong to the same game (and same server). Only if the contexts matches up across these clients, + /// will Mumble activate the positional audio effects, as it will assume that these clients are playing the + /// same game together. + /// The context is set during fetching of the other positional data and is usually something like e.g. the + /// current server's name. In order to avoid clashes between different plugins (that most likely work for + /// different games), the context is prefixed by Mumble. If this function is not implemented, the name of + /// the plugin is used as a prefix (which tends to be the supported game's name), but sometimes a different + /// prefix is desirable. For these cases, a custom prefix can be provided through this function. + /// + /// NOTE that while it is possible to allocate a string for this purpose every time this function is called + /// and then letting mumble release the resource again (via mumble_releaseResource), it is generally not the + /// advised way of doing things (it may impact overall performance negatively, since this function will be + /// called very frequently). Instead you should either return a static string (if your language supports that + /// and if it actually fits your needs) or you should allocate a string during mumble_initPositionalData and + /// free it in mumble_shutdownPositionalData and when returning the string in this function, tell Mumble that + /// the string does not need releasing. + /// + /// @returns The context prefix to use for positional data fetched by this plugin. + /// + /// @since Plugin API v1.1.0 + PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getPositionalDataContextPrefix(); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////// EVENTHANDLERS / CALLBACK FUNCTIONS //////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// Called when connecting to a server. + /// Note that in most cases you'll want to use mumble_onServerSynchronized instead. + /// Note also that this callback will be called from a DIFFERENT THREAD! + /// + /// @param connection The ID of the newly established server-connection + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerConnected(mumble_connection_t connection); + + /// Called when disconnecting from a server. + /// Note that this callback is called from a DIFFERENT THREAD! + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerDisconnected(mumble_connection_t connection); + + /// Called when the client has finished synchronizing with the server + /// + /// @param connection The ID of the server-connection that has been terminated + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onServerSynchronized(mumble_connection_t connection); + + /// Called whenever any user on the server enters a channel + /// This function will also be called when freshly connecting to a server as each user on that + /// server needs to be "added" to the respective channel as far as the local client is concerned. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user this event has been triggered for + /// @param previousChannelID The ID of the chanel the user is coming from. Negative IDs indicate that there is no + /// previous channel (e.g. the user freshly connected to the server) or the channel isn't available because of any other + /// reason. + /// @param newChannelID The ID of the channel the user has entered. If the ID is negative, the new channel could not be + /// retrieved. This means that the ID is invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelEntered(mumble_connection_t connection, + mumble_userid_t userID, + mumble_channelid_t previousChannelID, + mumble_channelid_t newChannelID); + + /// Called whenever a user leaves a channel. + /// This includes a client disconnecting from the server as this will also lead to the user not being in that channel + /// anymore. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user that left the channel + /// @param channelID The ID of the channel the user left. If the ID is negative, the channel could not be retrieved. + /// This means that the ID is invalid. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelExited(mumble_connection_t connection, + mumble_userid_t userID, + mumble_channelid_t channelID); + + /// Called when any user changes his/her talking state. + /// + /// @param connection The ID of the server-connection this event is connected to + /// @param userID The ID of the user whose talking state has been changed + /// @param talkingState The new TalkingState the user has switched to. + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserTalkingStateChanged(mumble_connection_t connection, + mumble_userid_t userID, + mumble_talking_state_t talkingState); + + /// Called whenever there is audio input. + /// Note that this callback will be called from the AUDIO THREAD. + /// Note also that blocking this callback will cause Mumble's audio processing to get suspended. + /// + /// @param inputPCM A pointer to a short-array holding the pulse-code-modulation (PCM) representing the audio input. Its + /// length is sampleCount * channelCount. The PCM format for stereo input is [LRLRLR...] where L and R are samples of + /// the left and right channel respectively. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param sampleRate The used sample rate in Hz + /// @param isSpeech A boolean flag indicating whether Mumble considers the input as part of speech (instead of + /// background noise) + /// @returns Whether this callback has modified the audio input-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioInput(short* inputPCM, uint32_t sampleCount, + uint16_t channelCount, uint32_t sampleRate, + bool isSpeech); + + /// Called whenever Mumble fetches data from an active audio source (could be a voice packet or a playing sample). + /// The provided audio buffer is the raw buffer without any processing applied to it yet. + /// Note that this callback will be called from the AUDIO THREAD. + /// Note also that blocking this callback will cause Mumble's audio processing to get suspended. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. + /// Its length is sampleCount * channelCount. The PCM format for stereo output is [LRLRLR...] where L and R are samples + /// of the left and right channel respectively. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param sampleRate The used sample rate in Hz + /// @param isSpeech Whether this audio belongs to a received voice packet (and will thus (most likely) contain speech) + /// @param userID If isSpeech is true, this contains the ID of the user this voice packet belongs to. If isSpeech is + /// false, the content of this parameter is unspecified and should not be accessed + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioSourceFetched(float* outputPCM, uint32_t sampleCount, + uint16_t channelCount, uint32_t sampleRate, + bool isSpeech, mumble_userid_t userID); + + /// Called whenever the fully mixed and processed audio is about to be handed to the audio backend (about to be played). + /// Note that this happens immediately before Mumble clips the audio buffer. + /// Note that this callback will be called from the AUDIO THREAD. + /// Note also that blocking this callback will cause Mumble's audio processing to get suspended. + /// + /// @param outputPCM A pointer to a float-array holding the pulse-code-modulation (PCM) representing the audio output. + /// Its length is sampleCount * channelCount. The PCM format for stereo output is [LRLRLR...] where L and R are samples + /// of the left and right channel respectively. + /// @param sampleCount The amount of sample points per channel + /// @param channelCount The amount of channels in the audio + /// @param sampleRate The used sample rate in Hz + /// @returns Whether this callback has modified the audio output-array + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onAudioOutputAboutToPlay(float* outputPCM, uint32_t sampleCount, + uint16_t channelCount, + uint32_t sampleRate); + + /// Called whenever data has been received that has been sent by a plugin. This data should only be processed by the + /// intended plugin. For this reason a dataID is provided that should be used to determine whether the data is intended + /// for this plugin or not. As soon as the data has been processed, no further plugins will be notified about it. + /// + /// @param connection The ID of the server-connection the data is coming from + /// @param sender The ID of the user whose client's plugin has sent the data + /// @param data The sent data array. This can be an arbitrary sequence of bytes. + /// @param dataLength The length of the data array + /// @param dataID The ID of this data (C-encoded) + /// @return Whether the given data has been processed by this plugin + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_onReceiveData(mumble_connection_t connection, + mumble_userid_t sender, const uint8_t* data, + size_t dataLength, const char* dataID); + + /// Called when a new user gets added to the user model. This is the case when that new user freshly connects to the + /// server the local user is on but also when the local user connects to a server other clients are already connected to + /// (in this case this method will be called for every client already on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been added + + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserAdded(mumble_connection_t connection, mumble_userid_t userID); + + /// Called when a user gets removed from the user model. This is the case when that user disconnects from the server the + /// local user is on but also when the local user disconnects from a server other clients are connected to (in this case + /// this method will be called for every client on that server). + /// + /// @param connection An object used to identify the current connection + /// @param userID The ID of the user that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onUserRemoved(mumble_connection_t connection, + mumble_userid_t userID); + + /// Called when a new channel gets added to the user model. This is the case when a new channel is created on the server + /// the local user is on but also when the local user connects to a server that contains channels other than the + /// root-channel (in this case this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been added + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelAdded(mumble_connection_t connection, + mumble_channelid_t channelID); + + /// Called when a channel gets removed from the user model. This is the case when a channel is removed on the server the + /// local user is on but also when the local user disconnects from a server that contains channels other than the + /// root-channel (in this case this method will be called for ever non-root channel on that server). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been removed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRemoved(mumble_connection_t connection, + mumble_channelid_t channelID); + + /// Called when a channel gets renamed. This also applies when a new channel is created (thus assigning it an initial + /// name is also considered renaming). + /// + /// @param connection An object used to identify the current connection + /// @param channelID The ID of the channel that has been renamed + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onChannelRenamed(mumble_connection_t connection, + mumble_channelid_t channelID); + + /// Called when a key has been pressed or released while Mumble has keyboard focus. + /// Note that this callback will only work if the user has explicitly given permission to monitor keyboard + /// events for this plugin. Thus if you want to use this callback, make sure your users know that they have to + /// enable that. + /// + /// @param keyCode The key code of the respective key. The character codes are defined + /// via the Mumble_KeyCode enum. For printable 7-bit ASCII characters these codes conform + /// to the ASCII code-page with the only difference that case is not distinguished. Therefore + /// always the upper-case letter code will be used for letters. + /// @param wasPres Whether the respective key has been pressed (instead of released) + PLUGIN_EXPORT void PLUGIN_CALLING_CONVENTION mumble_onKeyEvent(uint32_t keyCode, bool wasPress); + + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// PLUGIN UPDATES //////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + /// This function is used to determine whether the plugin can find an update for itself that is available for download. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @return Whether the plugin was able to find an update for itself + PLUGIN_EXPORT bool PLUGIN_CALLING_CONVENTION mumble_hasUpdate(); + + /// This function is used to retrieve the URL for downloading the newer/updated version of this plugin. + /// + /// NOTE: This function may be called without the plugin being loaded + /// + /// @returns A String-wrapper containing the requested URL + PLUGIN_EXPORT struct MumbleStringWrapper PLUGIN_CALLING_CONVENTION mumble_getUpdateDownloadURL(); + + + + ////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// DEFAULT FUNCTIONS ////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // These functions don't have to be implemented by you + PLUGIN_EXPORT mumble_version_t mumble_getPluginFunctionsVersion(); + +#ifndef MUMBLE_PLUGIN_NO_DEFAULT_FUNCTION_DEFINITIONS + + PLUGIN_EXPORT mumble_version_t mumble_getPluginFunctionsVersion() { + return MUMBLE_PLUGIN_FUNCTIONS_VERSION; + } + +#endif + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h index f6c422e97..cad868362 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h @@ -33,22 +33,22 @@ /// This enum's values correspond to special feature sets a plugin may provide. /// They are meant to be or'ed together to represent the total feature set of a plugin. enum Mumble_PluginFeature { - /// None of the below - MUMBLE_FEATURE_NONE = 0, - /// The plugin provides positional data from a game - MUMBLE_FEATURE_POSITIONAL = 1 << 0, - /// The plugin modifies the input/output audio itself - MUMBLE_FEATURE_AUDIO = 1 << 1 + /// None of the below + MUMBLE_FEATURE_NONE = 0, + /// The plugin provides positional data from a game + MUMBLE_FEATURE_POSITIONAL = 1 << 0, + /// The plugin modifies the input/output audio itself + MUMBLE_FEATURE_AUDIO = 1 << 1 }; /// This enum's values represent talking states a user can be in when using Mumble. enum Mumble_TalkingState { - MUMBLE_TS_INVALID = -1, - MUMBLE_TS_PASSIVE = 0, - MUMBLE_TS_TALKING, - MUMBLE_TS_WHISPERING, - MUMBLE_TS_SHOUTING, - MUMBLE_TS_TALKING_MUTED + MUMBLE_TS_INVALID = -1, + MUMBLE_TS_PASSIVE = 0, + MUMBLE_TS_TALKING, + MUMBLE_TS_WHISPERING, + MUMBLE_TS_SHOUTING, + MUMBLE_TS_TALKING_MUTED }; /// This enum's values represent transmission modes a user might have configured. Transmission mode @@ -59,250 +59,252 @@ enum Mumble_TransmissionMode { MUMBLE_TM_CONTINOUS, MUMBLE_TM_VOICE_ACTIVATION, /// This enum's values represent the error codes that are being used by the MumbleAPI. /// You can get a string-representation for each error code via the errorMessage function. enum Mumble_ErrorCode { - MUMBLE_EC_INTERNAL_ERROR = -2, - MUMBLE_EC_GENERIC_ERROR = -1, - MUMBLE_EC_OK = 0, - MUMBLE_EC_POINTER_NOT_FOUND, - MUMBLE_EC_NO_ACTIVE_CONNECTION, - MUMBLE_EC_USER_NOT_FOUND, - MUMBLE_EC_CHANNEL_NOT_FOUND, - MUMBLE_EC_CONNECTION_NOT_FOUND, - MUMBLE_EC_UNKNOWN_TRANSMISSION_MODE, - MUMBLE_EC_AUDIO_NOT_AVAILABLE, - MUMBLE_EC_INVALID_SAMPLE, - MUMBLE_EC_INVALID_PLUGIN_ID, - MUMBLE_EC_INVALID_MUTE_TARGET, - MUMBLE_EC_CONNECTION_UNSYNCHRONIZED, - MUMBLE_EC_INVALID_API_VERSION, - MUMBLE_EC_UNSYNCHRONIZED_BLOB, - MUMBLE_EC_UNKNOWN_SETTINGS_KEY, - MUMBLE_EC_WRONG_SETTINGS_TYPE, - MUMBLE_EC_SETTING_WAS_REMOVED, - MUMBLE_EC_DATA_TOO_BIG, - MUMBLE_EC_DATA_ID_TOO_LONG, + MUMBLE_EC_INTERNAL_ERROR = -2, + MUMBLE_EC_GENERIC_ERROR = -1, + MUMBLE_EC_OK = 0, + MUMBLE_EC_POINTER_NOT_FOUND, + MUMBLE_EC_NO_ACTIVE_CONNECTION, + MUMBLE_EC_USER_NOT_FOUND, + MUMBLE_EC_CHANNEL_NOT_FOUND, + MUMBLE_EC_CONNECTION_NOT_FOUND, + MUMBLE_EC_UNKNOWN_TRANSMISSION_MODE, + MUMBLE_EC_AUDIO_NOT_AVAILABLE, + MUMBLE_EC_INVALID_SAMPLE, + MUMBLE_EC_INVALID_PLUGIN_ID, + MUMBLE_EC_INVALID_MUTE_TARGET, + MUMBLE_EC_CONNECTION_UNSYNCHRONIZED, + MUMBLE_EC_INVALID_API_VERSION, + MUMBLE_EC_UNSYNCHRONIZED_BLOB, + MUMBLE_EC_UNKNOWN_SETTINGS_KEY, + MUMBLE_EC_WRONG_SETTINGS_TYPE, + MUMBLE_EC_SETTING_WAS_REMOVED, + MUMBLE_EC_DATA_TOO_BIG, + MUMBLE_EC_DATA_ID_TOO_LONG, + MUMBLE_EC_API_REQUEST_TIMEOUT, + MUMBLE_EC_OPERATION_UNSUPPORTED_BY_SERVER, }; /// This enum's values represent error codes specific to the framework of handling positional data /// gathering (needed for Mumble's positional audio feature). enum Mumble_PositionalDataErrorCode { - /// Positional data has been initialized properly - MUMBLE_PDEC_OK = 0, - /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be - /// at another point in time. - MUMBLE_PDEC_ERROR_TEMP, - /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). - MUMBLE_PDEC_ERROR_PERM + /// Positional data has been initialized properly + MUMBLE_PDEC_OK = 0, + /// Positional data is temporarily unavailable (e.g. because the corresponding process isn't running) but might be + /// at another point in time. + MUMBLE_PDEC_ERROR_TEMP, + /// Positional data is permanently unavailable (e.g. because the respective memory offsets are outdated). + MUMBLE_PDEC_ERROR_PERM }; /// This enum's values represent keys for specific settings inside Mumble. enum Mumble_SettingsKey { - MUMBLE_SK_INVALID = -1, - MUMBLE_SK_AUDIO_INPUT_VOICE_HOLD = 0, - MUMBLE_SK_AUDIO_INPUT_VAD_SILENCE_THRESHOLD = 1, - MUMBLE_SK_AUDIO_INPUT_VAD_SPEECH_THRESHOLD = 2, - MUMBLE_SK_AUDIO_OUTPUT_PA_MINIMUM_DISTANCE = 3, - MUMBLE_SK_AUDIO_OUTPUT_PA_MAXIMUM_DISTANCE = 4, - MUMBLE_SK_AUDIO_OUTPUT_PA_BLOOM = 5, - MUMBLE_SK_AUDIO_OUTPUT_PA_MINIMUM_VOLUME = 6, + MUMBLE_SK_INVALID = -1, + MUMBLE_SK_AUDIO_INPUT_VOICE_HOLD = 0, + MUMBLE_SK_AUDIO_INPUT_VAD_SILENCE_THRESHOLD = 1, + MUMBLE_SK_AUDIO_INPUT_VAD_SPEECH_THRESHOLD = 2, + MUMBLE_SK_AUDIO_OUTPUT_PA_MINIMUM_DISTANCE = 3, + MUMBLE_SK_AUDIO_OUTPUT_PA_MAXIMUM_DISTANCE = 4, + MUMBLE_SK_AUDIO_OUTPUT_PA_BLOOM = 5, + MUMBLE_SK_AUDIO_OUTPUT_PA_MINIMUM_VOLUME = 6, }; /// This enum's values represent the key-codes Mumble's API uses to reference keys on the keyboard. enum Mumble_KeyCode { - MUMBLE_KC_INVALID = -1, - - // Non-printable characters first - MUMBLE_KC_NULL = 0, - MUMBLE_KC_END = 1, - MUMBLE_KC_LEFT = 2, - MUMBLE_KC_RIGHT = 4, - MUMBLE_KC_UP = 5, - MUMBLE_KC_DOWN = 6, - MUMBLE_KC_DELETE = 7, - MUMBLE_KC_BACKSPACE = 8, - MUMBLE_KC_TAB = 9, - MUMBLE_KC_ENTER = 10, // == '\n' - MUMBLE_KC_ESCAPE = 27, - MUMBLE_KC_PAGE_UP = 11, - MUMBLE_KC_PAGE_DOWN = 12, - MUMBLE_KC_SHIFT = 13, - MUMBLE_KC_CONTROL = 14, - MUMBLE_KC_META = 15, - MUMBLE_KC_ALT = 16, - MUMBLE_KC_ALT_GR = 17, - MUMBLE_KC_CAPSLOCK = 18, - MUMBLE_KC_NUMLOCK = 19, - MUMBLE_KC_SUPER = 20, // == windows key - MUMBLE_KC_HOME = 21, // == Pos1 - MUMBLE_KC_PRINT = 22, - MUMBLE_KC_SCROLLLOCK = 23, - - // Printable characters are assigned to their ASCII code - MUMBLE_KC_SPACE = ' ', - MUMBLE_KC_EXCLAMATION_MARK = '!', - MUMBLE_KC_DOUBLE_QUOTE = '"', - MUMBLE_KC_HASHTAG = '#', - MUMBLE_KC_DOLLAR = '$', - MUMBLE_KC_PERCENT = '%', - MUMBLE_KC_AMPERSAND = '&', - MUMBLE_KC_SINGLE_QUOTE = '\'', - MUMBLE_KC_OPEN_PARENTHESIS = '(', - MUMBLE_KC_CLOSE_PARENTHESIS = ')', - MUMBLE_KC_ASTERISK = '*', - MUMBLE_KC_PLUS = '+', - MUMBLE_KC_COMMA = ',', - MUMBLE_KC_MINUS = '-', - MUMBLE_KC_PERIOD = '.', - MUMBLE_KC_SLASH = '/', - MUMBLE_KC_0 = '0', - MUMBLE_KC_1 = '1', - MUMBLE_KC_2 = '2', - MUMBLE_KC_3 = '3', - MUMBLE_KC_4 = '4', - MUMBLE_KC_5 = '5', - MUMBLE_KC_6 = '6', - MUMBLE_KC_7 = '7', - MUMBLE_KC_8 = '8', - MUMBLE_KC_9 = '9', - MUMBLE_KC_COLON = ':', - MUMBLE_KC_SEMICOLON = ';', - MUMBLE_KC_LESS_THAN = '<', - MUMBLE_KC_EQUALS = '=', - MUMBLE_KC_GREATER_THAN = '>', - MUMBLE_KC_QUESTION_MARK = '?', - MUMBLE_KC_AT_SYMBOL = '@', - MUMBLE_KC_A = 'A', - MUMBLE_KC_B = 'B', - MUMBLE_KC_C = 'C', - MUMBLE_KC_D = 'D', - MUMBLE_KC_E = 'E', - MUMBLE_KC_F = 'F', - MUMBLE_KC_G = 'G', - MUMBLE_KC_H = 'H', - MUMBLE_KC_I = 'I', - MUMBLE_KC_J = 'J', - MUMBLE_KC_K = 'K', - MUMBLE_KC_L = 'L', - MUMBLE_KC_M = 'M', - MUMBLE_KC_N = 'N', - MUMBLE_KC_O = 'O', - MUMBLE_KC_P = 'P', - MUMBLE_KC_Q = 'Q', - MUMBLE_KC_R = 'R', - MUMBLE_KC_S = 'S', - MUMBLE_KC_T = 'T', - MUMBLE_KC_U = 'U', - MUMBLE_KC_V = 'V', - MUMBLE_KC_W = 'W', - MUMBLE_KC_X = 'X', - MUMBLE_KC_Y = 'Y', - MUMBLE_KC_Z = 'Z', - // leave out lowercase letters (for now) - MUMBLE_KC_OPEN_BRACKET = '[', - MUMBLE_KC_BACKSLASH = '\\', - MUMBLE_KC_CLOSE_BRACKET = ']', - MUMBLE_KC_CIRCUMFLEX = '^', - MUMBLE_KC_UNDERSCORE = '_', - MUMBLE_KC_GRAVE_AKCENT = '`', - MUMBLE_KC_OPEN_BRACE = '{', - MUMBLE_KC_VERTICAL_BAR = '|', - MUMBLE_KC_CLOSE_BRACE = '}', - MUMBLE_KC_TILDE = '~', - - // Some characters from the extended ASCII code - MUMBLE_KC_DEGREE_SIGN = 176, - - - - // F-keys - // Start at a value of 256 as extended ASCII codes range up to 255 - MUMBLE_KC_F1 = 256, - MUMBLE_KC_F2 = 257, - MUMBLE_KC_F3 = 258, - MUMBLE_KC_F4 = 259, - MUMBLE_KC_F5 = 260, - MUMBLE_KC_F6 = 261, - MUMBLE_KC_F7 = 262, - MUMBLE_KC_F8 = 263, - MUMBLE_KC_F9 = 264, - MUMBLE_KC_F10 = 265, - MUMBLE_KC_F11 = 266, - MUMBLE_KC_F12 = 267, - MUMBLE_KC_F13 = 268, - MUMBLE_KC_F14 = 269, - MUMBLE_KC_F15 = 270, - MUMBLE_KC_F16 = 271, - MUMBLE_KC_F17 = 272, - MUMBLE_KC_F18 = 273, - MUMBLE_KC_F19 = 274, + MUMBLE_KC_INVALID = -1, + + // Non-printable characters first + MUMBLE_KC_NULL = 0, + MUMBLE_KC_END = 1, + MUMBLE_KC_LEFT = 2, + MUMBLE_KC_RIGHT = 4, + MUMBLE_KC_UP = 5, + MUMBLE_KC_DOWN = 6, + MUMBLE_KC_DELETE = 7, + MUMBLE_KC_BACKSPACE = 8, + MUMBLE_KC_TAB = 9, + MUMBLE_KC_ENTER = 10, // == '\n' + MUMBLE_KC_ESCAPE = 27, + MUMBLE_KC_PAGE_UP = 11, + MUMBLE_KC_PAGE_DOWN = 12, + MUMBLE_KC_SHIFT = 13, + MUMBLE_KC_CONTROL = 14, + MUMBLE_KC_META = 15, + MUMBLE_KC_ALT = 16, + MUMBLE_KC_ALT_GR = 17, + MUMBLE_KC_CAPSLOCK = 18, + MUMBLE_KC_NUMLOCK = 19, + MUMBLE_KC_SUPER = 20, // == windows key + MUMBLE_KC_HOME = 21, // == Pos1 + MUMBLE_KC_PRINT = 22, + MUMBLE_KC_SCROLLLOCK = 23, + + // Printable characters are assigned to their ASCII code + MUMBLE_KC_SPACE = ' ', + MUMBLE_KC_EXCLAMATION_MARK = '!', + MUMBLE_KC_DOUBLE_QUOTE = '"', + MUMBLE_KC_HASHTAG = '#', + MUMBLE_KC_DOLLAR = '$', + MUMBLE_KC_PERCENT = '%', + MUMBLE_KC_AMPERSAND = '&', + MUMBLE_KC_SINGLE_QUOTE = '\'', + MUMBLE_KC_OPEN_PARENTHESIS = '(', + MUMBLE_KC_CLOSE_PARENTHESIS = ')', + MUMBLE_KC_ASTERISK = '*', + MUMBLE_KC_PLUS = '+', + MUMBLE_KC_COMMA = ',', + MUMBLE_KC_MINUS = '-', + MUMBLE_KC_PERIOD = '.', + MUMBLE_KC_SLASH = '/', + MUMBLE_KC_0 = '0', + MUMBLE_KC_1 = '1', + MUMBLE_KC_2 = '2', + MUMBLE_KC_3 = '3', + MUMBLE_KC_4 = '4', + MUMBLE_KC_5 = '5', + MUMBLE_KC_6 = '6', + MUMBLE_KC_7 = '7', + MUMBLE_KC_8 = '8', + MUMBLE_KC_9 = '9', + MUMBLE_KC_COLON = ':', + MUMBLE_KC_SEMICOLON = ';', + MUMBLE_KC_LESS_THAN = '<', + MUMBLE_KC_EQUALS = '=', + MUMBLE_KC_GREATER_THAN = '>', + MUMBLE_KC_QUESTION_MARK = '?', + MUMBLE_KC_AT_SYMBOL = '@', + MUMBLE_KC_A = 'A', + MUMBLE_KC_B = 'B', + MUMBLE_KC_C = 'C', + MUMBLE_KC_D = 'D', + MUMBLE_KC_E = 'E', + MUMBLE_KC_F = 'F', + MUMBLE_KC_G = 'G', + MUMBLE_KC_H = 'H', + MUMBLE_KC_I = 'I', + MUMBLE_KC_J = 'J', + MUMBLE_KC_K = 'K', + MUMBLE_KC_L = 'L', + MUMBLE_KC_M = 'M', + MUMBLE_KC_N = 'N', + MUMBLE_KC_O = 'O', + MUMBLE_KC_P = 'P', + MUMBLE_KC_Q = 'Q', + MUMBLE_KC_R = 'R', + MUMBLE_KC_S = 'S', + MUMBLE_KC_T = 'T', + MUMBLE_KC_U = 'U', + MUMBLE_KC_V = 'V', + MUMBLE_KC_W = 'W', + MUMBLE_KC_X = 'X', + MUMBLE_KC_Y = 'Y', + MUMBLE_KC_Z = 'Z', + // leave out lowercase letters (for now) + MUMBLE_KC_OPEN_BRACKET = '[', + MUMBLE_KC_BACKSLASH = '\\', + MUMBLE_KC_CLOSE_BRACKET = ']', + MUMBLE_KC_CIRCUMFLEX = '^', + MUMBLE_KC_UNDERSCORE = '_', + MUMBLE_KC_GRAVE_AKCENT = '`', + MUMBLE_KC_OPEN_BRACE = '{', + MUMBLE_KC_VERTICAL_BAR = '|', + MUMBLE_KC_CLOSE_BRACE = '}', + MUMBLE_KC_TILDE = '~', + + // Some characters from the extended ASCII code + MUMBLE_KC_DEGREE_SIGN = 176, + + + + // F-keys + // Start at a value of 256 as extended ASCII codes range up to 255 + MUMBLE_KC_F1 = 256, + MUMBLE_KC_F2 = 257, + MUMBLE_KC_F3 = 258, + MUMBLE_KC_F4 = 259, + MUMBLE_KC_F5 = 260, + MUMBLE_KC_F6 = 261, + MUMBLE_KC_F7 = 262, + MUMBLE_KC_F8 = 263, + MUMBLE_KC_F9 = 264, + MUMBLE_KC_F10 = 265, + MUMBLE_KC_F11 = 266, + MUMBLE_KC_F12 = 267, + MUMBLE_KC_F13 = 268, + MUMBLE_KC_F14 = 269, + MUMBLE_KC_F15 = 270, + MUMBLE_KC_F16 = 271, + MUMBLE_KC_F17 = 272, + MUMBLE_KC_F18 = 273, + MUMBLE_KC_F19 = 274, }; /// A struct for representing a version of the form major.minor.patch struct MumbleVersion { - int32_t major; - int32_t minor; - int32_t patch; + int32_t major; + int32_t minor; + int32_t patch; #ifdef __cplusplus - bool operator<(const MumbleVersion &other) const { - if (this->major != other.major) { - return this->major < other.major; - } - if (this->minor != other.minor) { - return this->minor < other.minor; - } - // Major and Minor are equal - return this->patch < other.patch; - } - - bool operator>(const MumbleVersion &other) const { - if (this->major != other.major) { - return this->major > other.major; - } - if (this->minor != other.minor) { - return this->minor > other.minor; - } - // Major and Minor are equal - return this->patch > other.patch; - } - - bool operator>=(const MumbleVersion &other) const { - if (this->major != other.major) { - return this->major > other.major; - } - if (this->minor != other.minor) { - return this->minor > other.minor; - } - // Major and Minor are equal - return this->patch >= other.patch; - } - - bool operator<=(const MumbleVersion &other) const { - if (this->major != other.major) { - return this->major < other.major; - } - if (this->minor != other.minor) { - return this->minor < other.minor; - } - // Major and Minor are equal - return this->patch <= other.patch; - } - - bool operator==(const MumbleVersion &other) const { - return this->major == other.major && this->minor == other.minor && this->patch == other.patch; - } - - bool operator!=(const MumbleVersion &other) const { - return this->major != other.major || this->minor != other.minor || this->patch != other.patch; - } - - operator std::string() const { - return std::string("v") + std::to_string(this->major) + std::string(".") + std::to_string(this->minor) - + std::string(".") + std::to_string(this->patch); - } + bool operator<(const MumbleVersion& other) const { + if (this->major != other.major) { + return this->major < other.major; + } + if (this->minor != other.minor) { + return this->minor < other.minor; + } + // Major and Minor are equal + return this->patch < other.patch; + } + + bool operator>(const MumbleVersion& other) const { + if (this->major != other.major) { + return this->major > other.major; + } + if (this->minor != other.minor) { + return this->minor > other.minor; + } + // Major and Minor are equal + return this->patch > other.patch; + } + + bool operator>=(const MumbleVersion& other) const { + if (this->major != other.major) { + return this->major > other.major; + } + if (this->minor != other.minor) { + return this->minor > other.minor; + } + // Major and Minor are equal + return this->patch >= other.patch; + } + + bool operator<=(const MumbleVersion& other) const { + if (this->major != other.major) { + return this->major < other.major; + } + if (this->minor != other.minor) { + return this->minor < other.minor; + } + // Major and Minor are equal + return this->patch <= other.patch; + } + + bool operator==(const MumbleVersion& other) const { + return this->major == other.major && this->minor == other.minor && this->patch == other.patch; + } + + bool operator!=(const MumbleVersion& other) const { + return this->major != other.major || this->minor != other.minor || this->patch != other.patch; + } + + operator std::string() const { + return std::string("v") + std::to_string(this->major) + std::string(".") + std::to_string(this->minor) + + std::string(".") + std::to_string(this->patch); + } # if defined(QT_CORE_LIB) || defined(QT_VERSION) - operator QString() const { - return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); - } + operator QString() const { + return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); + } # endif #endif }; @@ -316,51 +318,56 @@ struct MumbleVersion { /// @returns The error message coresponding to the given error code. The message /// is encoded as a C-string and is static, meaning that it is safe to use the /// returned pointer in your code. -inline const char *mumble_errorMessage(int16_t errorCode) { - switch (errorCode) { - case MUMBLE_EC_GENERIC_ERROR: - return "Generic error"; - case MUMBLE_EC_OK: - return "Ok - this is not an error"; - case MUMBLE_EC_POINTER_NOT_FOUND: - return "Can't find the passed pointer"; - case MUMBLE_EC_NO_ACTIVE_CONNECTION: - return "There is currently no active connection to a server"; - case MUMBLE_EC_USER_NOT_FOUND: - return "Can't find the requested user"; - case MUMBLE_EC_CHANNEL_NOT_FOUND: - return "Can't find the requested channel"; - case MUMBLE_EC_CONNECTION_NOT_FOUND: - return "Can't identify the requested connection"; - case MUMBLE_EC_UNKNOWN_TRANSMISSION_MODE: - return "Unknown transmission mode encountered"; - case MUMBLE_EC_AUDIO_NOT_AVAILABLE: - return "There is currently no audio output available"; - case MUMBLE_EC_INVALID_SAMPLE: - return "Attempted to use invalid sample (can't play it)"; - case MUMBLE_EC_INVALID_PLUGIN_ID: - return "Used an invalid plugin ID"; - case MUMBLE_EC_INVALID_MUTE_TARGET: - return "Used an invalid mute-target"; - case MUMBLE_EC_CONNECTION_UNSYNCHRONIZED: - return "The requested server connection has not yet finished synchronizing"; - case MUMBLE_EC_INVALID_API_VERSION: - return "The used API version is invalid or not supported"; - case MUMBLE_EC_UNSYNCHRONIZED_BLOB: - return "The requested blob (content) has not yet been synchronized between the client and the server"; - case MUMBLE_EC_UNKNOWN_SETTINGS_KEY: - return "The used settings-key does not match any key known to Mumble"; - case MUMBLE_EC_WRONG_SETTINGS_TYPE: - return "The referenced setting has a different type than requested"; - case MUMBLE_EC_SETTING_WAS_REMOVED: - return "The referenced setting got removed from Mumble and is no longer used"; - case MUMBLE_EC_DATA_TOO_BIG: - return "The given data is too large (exceeds limit)"; - case MUMBLE_EC_DATA_ID_TOO_LONG: - return "The given data ID is too long (exceeds limit)"; - default: - return "Unknown error code"; - } +inline const char* mumble_errorMessage(int16_t errorCode) { + switch (errorCode) { + case MUMBLE_EC_GENERIC_ERROR: + return "Generic error"; + case MUMBLE_EC_OK: + return "Ok - this is not an error"; + case MUMBLE_EC_POINTER_NOT_FOUND: + return "Can't find the passed pointer"; + case MUMBLE_EC_NO_ACTIVE_CONNECTION: + return "There is currently no active connection to a server"; + case MUMBLE_EC_USER_NOT_FOUND: + return "Can't find the requested user"; + case MUMBLE_EC_CHANNEL_NOT_FOUND: + return "Can't find the requested channel"; + case MUMBLE_EC_CONNECTION_NOT_FOUND: + return "Can't identify the requested connection"; + case MUMBLE_EC_UNKNOWN_TRANSMISSION_MODE: + return "Unknown transmission mode encountered"; + case MUMBLE_EC_AUDIO_NOT_AVAILABLE: + return "There is currently no audio output available"; + case MUMBLE_EC_INVALID_SAMPLE: + return "Attempted to use invalid sample (can't play it)"; + case MUMBLE_EC_INVALID_PLUGIN_ID: + return "Used an invalid plugin ID"; + case MUMBLE_EC_INVALID_MUTE_TARGET: + return "Used an invalid mute-target"; + case MUMBLE_EC_CONNECTION_UNSYNCHRONIZED: + return "The requested server connection has not yet finished synchronizing"; + case MUMBLE_EC_INVALID_API_VERSION: + return "The used API version is invalid or not supported"; + case MUMBLE_EC_UNSYNCHRONIZED_BLOB: + return "The requested blob (content) has not yet been synchronized between the client and the server"; + case MUMBLE_EC_UNKNOWN_SETTINGS_KEY: + return "The used settings-key does not match any key known to Mumble"; + case MUMBLE_EC_WRONG_SETTINGS_TYPE: + return "The referenced setting has a different type than requested"; + case MUMBLE_EC_SETTING_WAS_REMOVED: + return "The referenced setting got removed from Mumble and is no longer used"; + case MUMBLE_EC_DATA_TOO_BIG: + return "The given data is too large (exceeds limit)"; + case MUMBLE_EC_DATA_ID_TOO_LONG: + return "The given data ID is too long (exceeds limit)"; + case MUMBLE_EC_API_REQUEST_TIMEOUT: + return "A blocking API call took too long and was this aborted (probably preventing a deadlock)"; + case MUMBLE_EC_OPERATION_UNSUPPORTED_BY_SERVER: + return "The requested API operation depends on server-side functionality, not supported by the server " + "you're connected to"; + default: + return "Unknown error code"; + } } @@ -368,14 +375,14 @@ inline const char *mumble_errorMessage(int16_t errorCode) { /// work around the limitation of std::string not being part of C (it holds important information /// about the String's lifetime management requirements). struct MumbleStringWrapper { - /// The pointer to the actual String data - const char *data; - /// The size of the pointed String data - size_t size; - /// Whether the wrapped String needs to be released - /// after its usage. Instances for which this would be - /// false: Static Strings, String literals - bool needsReleasing; + /// The pointer to the actual String data + const char* data; + /// The size of the pointed String data + size_t size; + /// Whether the wrapped String needs to be released + /// after its usage. Instances for which this would be + /// false: Static Strings, String literals + bool needsReleasing; }; /// Typedef for the type of a talking state From c61270beacb823b03c5d90ff99366ea2c5121f7a Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:16:45 +0100 Subject: [PATCH 090/104] Add additional error log --- extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 4e7ed3f95..065ee6e55 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -89,4 +89,5 @@ void mumble_shutdown() { void mumble_releaseResource(const void *) { // Nothing to do here since we never pass allocated resourced to Mumble // that needed freeing + LOG("ERROR: Unexpectedly called mumble_releaseResource"); } From 11c67b99f5a6f911d0192b4c45be8fafe92f4378 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:17:38 +0100 Subject: [PATCH 091/104] Explicitly start event loop on plugin init --- extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 065ee6e55..8fceccfa6 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -25,6 +25,8 @@ void mumble_registerAPIFunctions(void *apiStruct) { mumble_error_t mumble_init(mumble_plugin_id_t id) { pluginID = id; + acre::MumbleEventLoop::getInstance().start(); + if (mumAPI.getActiveServerConnection(pluginID, &activeConnection) != MUMBLE_STATUS_OK) { activeConnection = -1; } From f4b3f87d7b9d31e62ba569a96a36dc9ae1084bd8 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:18:38 +0100 Subject: [PATCH 092/104] Fix potential endless wait on end of plugin event queue --- .../src/ACRE2Mumble/MumbleEventLoop.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp b/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp index a5057e8b9..ae49effba 100644 --- a/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp +++ b/extensions/src/ACRE2Mumble/MumbleEventLoop.cpp @@ -28,9 +28,9 @@ namespace acre { { std::lock_guard guard(m_lock); m_keepRunning = false; - } - m_waiter.notify_all(); + m_waiter.notify_all(); + } if (m_thread.joinable()) { // Wait until the worker thread has finished @@ -39,21 +39,17 @@ namespace acre { } void MumbleEventLoop::queue(const std::function& callable) { - { - std::lock_guard guard(m_lock); + std::lock_guard guard(m_lock); - m_queuedFunctions.push_back(callable); - } + m_queuedFunctions.push_back(callable); m_waiter.notify_all(); } void MumbleEventLoop::queue(std::function&& callable) { - { - std::unique_lock guard(m_lock); + std::unique_lock guard(m_lock); - m_queuedFunctions.push_back(std::move(callable)); - } + m_queuedFunctions.push_back(std::move(callable)); m_waiter.notify_all(); } @@ -77,6 +73,10 @@ namespace acre { guard.lock(); } + if (!m_keepRunning) { + break; + } + // Wait for something to happen. Note that during the waiting the lock is released and // re-aquired once the waiting ends m_waiter.wait(guard); From 4e54964e96a4acc586c7af7e731481b1adc6b0ae Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sun, 19 Dec 2021 16:19:05 +0100 Subject: [PATCH 093/104] Added missing static plugin info functions --- .../ACRE2Mumble/MumbleCallbacks_static.cpp | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp index aab0ac8e0..07d2c4838 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -30,6 +30,28 @@ mumble_version_t mumble_getVersion() { return mumble_version_t{ACRE_VERSION_MAJOR, ACRE_VERSION_MINOR, ACRE_VERSION_SUBMINOR}; } +struct MumbleStringWrapper mumble_getAuthor() { + static const char* author = "ACRE2 developers"; + + MumbleStringWrapper wrapper; + wrapper.data = author; + wrapper.size = strlen(author); + wrapper.needsReleasing = false; + + return wrapper; +} + +struct MumbleStringWrapper mumble_getDescription() { + static const char* description = "ACRE2 is a full fledged communications suite for Arma 3, allowing realistic radio and voice communications."; + + MumbleStringWrapper wrapper; + wrapper.data = description; + wrapper.size = strlen(description); + wrapper.needsReleasing = false; + + return wrapper; +} + mumble_version_t mumble_getPluginFunctionsVersion() { return MUMBLE_PLUGIN_FUNCTIONS_VERSION; } From 1bf13fdf1c25c214ac228179fda10b39396cc151 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Mon, 20 Dec 2021 11:33:54 +0100 Subject: [PATCH 094/104] Use proper macros for author & description --- extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp index 07d2c4838..f4b745897 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -31,7 +31,7 @@ mumble_version_t mumble_getVersion() { } struct MumbleStringWrapper mumble_getAuthor() { - static const char* author = "ACRE2 developers"; + static const char* author = ACRE_TEAM; MumbleStringWrapper wrapper; wrapper.data = author; @@ -42,7 +42,7 @@ struct MumbleStringWrapper mumble_getAuthor() { } struct MumbleStringWrapper mumble_getDescription() { - static const char* description = "ACRE2 is a full fledged communications suite for Arma 3, allowing realistic radio and voice communications."; + static const char* description = ACRE_DESC; MumbleStringWrapper wrapper; wrapper.data = description; From 3e7743c434e480faf2acc6422e34ad52ab9ce571 Mon Sep 17 00:00:00 2001 From: jonpas Date: Tue, 21 Dec 2021 12:03:58 +0100 Subject: [PATCH 095/104] Fix indentation --- .../src/ACRE2Mumble/MumbleCallbacks_init.cpp | 2 +- .../src/ACRE2Mumble/MumbleCallbacks_sound.cpp | 4 ++-- .../src/ACRE2Mumble/MumbleCallbacks_static.cpp | 10 +++++----- extensions/src/ACRE2Mumble/MumbleClient.cpp | 4 ++-- .../mumble_includes/MumbleAPI_v_1_0_x.h | 4 ++-- .../mumble_includes/MumblePlugin_v_1_1_x.h | 8 ++++---- .../mumble_includes/PluginComponents_v_1_0_x.h | 14 +++++++------- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp index 8fceccfa6..80ea6abf2 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_init.cpp @@ -23,7 +23,7 @@ void mumble_registerAPIFunctions(void *apiStruct) { } mumble_error_t mumble_init(mumble_plugin_id_t id) { - pluginID = id; + pluginID = id; acre::MumbleEventLoop::getInstance().start(); diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp index 2c325b007..6022f882e 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_sound.cpp @@ -17,7 +17,7 @@ using LIMITER = std::numeric_limits; bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, uint32_t sampleRate, bool isSpeech, mumble_userid_t userID) { - (void) sampleRate; + (void) sampleRate; if (CEngine::getInstance()->getSoundSystemOverride()) { return false; @@ -104,7 +104,7 @@ bool mumble_onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_ } bool mumble_onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, uint32_t sampleRate) { - (void) sampleRate; + (void) sampleRate; if (CEngine::getInstance()->getSoundSystemOverride()) { return false; diff --git a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp index f4b745897..b6454e62d 100644 --- a/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp +++ b/extensions/src/ACRE2Mumble/MumbleCallbacks_static.cpp @@ -12,12 +12,12 @@ #include "Log.h" struct MumbleStringWrapper mumble_getName() { - static const char *name = ACRE_NAME; + static const char *name = ACRE_NAME; - MumbleStringWrapper wrapper; - wrapper.data = name; - wrapper.size = strlen(name); - wrapper.needsReleasing = false; + MumbleStringWrapper wrapper; + wrapper.data = name; + wrapper.size = strlen(name); + wrapper.needsReleasing = false; return wrapper; } diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 16083c597..0ea52fefe 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -330,8 +330,8 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { if (mumAPI.getChannelName(pluginID, activeConnection, channelId, &channelName) == MUMBLE_STATUS_OK) { // Copy the channel name into a std::string and then get rid of the Mumble resource again - std::string channelNameString(channelName); - mumAPI.freeMemory(pluginID, (void *) channelName); + std::string channelNameString(channelName); + mumAPI.freeMemory(pluginID, (void *) channelName); if (channelNameString.find(default_mumble_channel) != -1 || (!details_.at(0).empty() && channelNameString == name)) { if (channelNameString == default_mumble_channel) { diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h index 1b8b722b6..7e97f6643 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumbleAPI_v_1_0_x.h @@ -28,8 +28,8 @@ const mumble_version_t MUMBLE_PLUGIN_API_VERSION = { MUMBLE_PLUGIN_API_MAJOR, MU #define MUMBLE_CONCAT_HELPER(a, b) a##_##b #define MUMBLE_CONCAT(a, b) MUMBLE_CONCAT_HELPER(a, b) #define MUMBLE_API_STRUCT \ - MUMBLE_CONCAT(MumbleAPI_v, \ - MUMBLE_CONCAT(MUMBLE_PLUGIN_API_MAJOR_MACRO, MUMBLE_CONCAT(MUMBLE_PLUGIN_API_MINOR_MACRO, x))) + MUMBLE_CONCAT(MumbleAPI_v, \ + MUMBLE_CONCAT(MUMBLE_PLUGIN_API_MAJOR_MACRO, MUMBLE_CONCAT(MUMBLE_PLUGIN_API_MINOR_MACRO, x))) #define MUMBLE_API_CAST(ptrName) (*((struct MUMBLE_API_STRUCT *) ptrName)) diff --git a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_1_x.h b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_1_x.h index 0d646ac86..c2f78580e 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_1_x.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/MumblePlugin_v_1_1_x.h @@ -14,13 +14,13 @@ #include #if defined(__GNUC__) && !defined(__MINGW32__) // GCC on Unix-like systems -# define PLUGIN_EXPORT __attribute__((visibility("default"))) +# define PLUGIN_EXPORT __attribute__((visibility("default"))) #elif defined(_MSC_VER) -# define PLUGIN_EXPORT __declspec(dllexport) +# define PLUGIN_EXPORT __declspec(dllexport) #elif defined(__MINGW32__) -# define PLUGIN_EXPORT __attribute__((dllexport)) +# define PLUGIN_EXPORT __attribute__((dllexport)) #else -# error No PLUGIN_EXPORT definition available +# error No PLUGIN_EXPORT definition available #endif diff --git a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h index cad868362..99f00d5b3 100644 --- a/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h +++ b/extensions/src/ACRE2Mumble/mumble_includes/PluginComponents_v_1_0_x.h @@ -13,20 +13,20 @@ #include #ifdef __cplusplus -# include +# include #endif #if defined(QT_CORE_LIB) || defined(QT_VERSION) -# include +# include #endif // define the calling convention macro based on the compiler being used #if defined(_MSC_VER) -# define PLUGIN_CALLING_CONVENTION __cdecl +# define PLUGIN_CALLING_CONVENTION __cdecl #elif defined(__MINGW32__) -# define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) +# define PLUGIN_CALLING_CONVENTION __attribute__((cdecl)) #else -# define PLUGIN_CALLING_CONVENTION +# define PLUGIN_CALLING_CONVENTION #endif @@ -301,11 +301,11 @@ struct MumbleVersion { + std::string(".") + std::to_string(this->patch); } -# if defined(QT_CORE_LIB) || defined(QT_VERSION) +# if defined(QT_CORE_LIB) || defined(QT_VERSION) operator QString() const { return QString::fromLatin1("v%0.%1.%2").arg(this->major).arg(this->minor).arg(this->patch); } -# endif +# endif #endif }; From 495e1d11e00a842fbfc526ab0fd4948d557bfa69 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 23 Dec 2021 08:58:56 +0100 Subject: [PATCH 096/104] Add docs for event loop --- extensions/src/ACRE2Mumble/MumbleEventLoop.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/extensions/src/ACRE2Mumble/MumbleEventLoop.h b/extensions/src/ACRE2Mumble/MumbleEventLoop.h index 599880a29..f46656bf0 100644 --- a/extensions/src/ACRE2Mumble/MumbleEventLoop.h +++ b/extensions/src/ACRE2Mumble/MumbleEventLoop.h @@ -8,6 +8,24 @@ namespace acre { + /** + * This class represents a separate event loop that allows to process events in their own thread. This is needed, because + * the synchronization of the Mumble API works by executing all API functions within Mumble's main thread, which also + * happens to be the thread almost all plugin callbacks are called from. Thus, blocking these callbacks (e.g. due to waiting + * on obtaining a lock) and simultaneously executing an API function from the thread that is the cause of the blocking (e.g. + * because it is holding the mentioned lock) will yield a deadlock, since the API call will block until it can be executed + * in Mumble's main thread, but the main thread is currently stuck in the plugin callback. + * Mumble does have a mechanism built-in that prevents an actual deadlock from happening (using a timed-wait) but such calls + * will still cause a lag in the program and will also cause the API call to fail (with a timeout error). Thus, these + * situations should be avoided. + * This is achieved by not executing the plugin callbacks synchronously but instead queuing them into this event loop for + * async execution. Therefore Mumble's main thread will not be blocked and we avoid this entire situation. + * + * Note that when shutting the event loop down from within a plugin callback (typically the shutdown callback), the + * abovementioned situation can still easily occur (since we have to wait for the event loop to end before returning + * from that callback). However, due to Mumble's deadlock prevention, this shouldn't cause any major issues. It could lead to + * small delays during shutdown, though (and some Mumble API calls failing under that circumstances). + */ class MumbleEventLoop { public: MumbleEventLoop(); From d6cb2d51c7b47c13e9d1e8936985df80de73a9d4 Mon Sep 17 00:00:00 2001 From: jonpas Date: Tue, 19 Apr 2022 21:32:53 +0200 Subject: [PATCH 097/104] Update extensions/src/ACRE2Steam/CallExt_DllMain.cpp Co-authored-by: Drofseh --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 2207f7393..87da162d7 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -160,7 +160,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!update_ts3_ok || !update_mumble_ok) { std::ostringstream oss; oss << "ACRE2 was unable to copy the Mumble/TeamSpeak 3 plugin. Please check if you have write access to the plugin " - << "folder, close any instances of Mumble and/or TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you " + << "folder, close any instances of TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you " << "would like to close Arma 3 click Cancel. Press Continue to launch Arma 3 regardless.\n\n" << error_msg; const int32_t result = MessageBoxA( From 29e80d658acd79dacc4b148e864b940ca352ce8a Mon Sep 17 00:00:00 2001 From: jonpas Date: Tue, 19 Apr 2022 23:18:27 +0200 Subject: [PATCH 098/104] Build Mumble plugin in CI --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4198443d1..ffc4e60a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -80,13 +80,13 @@ jobs: run: | cd extensions\\vcproj cmake .. -A Win32 - msbuild ACRE.sln /m '/t:ACRE2Arma\acre;ACRE2Arma\arma2ts;ACRE2\ACRE2Steam;ACRE2\ACRE2TS;Extras\Wav2B64' /p:Configuration=RelWithDebInfo + msbuild ACRE.sln /m '/t:ACRE2Arma\acre;ACRE2Arma\arma2ts;ACRE2\ACRE2Mumble;ACRE2\ACRE2Steam;ACRE2\ACRE2TS;Extras\Wav2B64' /p:Configuration=RelWithDebInfo - name: Build Extensions (x64) if: matrix.arch == 'x64' run: | cd extensions\\vcproj64 cmake .. -A x64 - msbuild ACRE.sln /m '/t:ACRE2Arma\acre;ACRE2Arma\arma2ts;ACRE2\ACRE2Steam;ACRE2\ACRE2TS' /p:Configuration=RelWithDebInfo + msbuild ACRE.sln /m '/t:ACRE2Arma\acre;ACRE2Arma\arma2ts;ACRE2\ACRE2Mumble;ACRE2\ACRE2Steam;ACRE2\ACRE2TS' /p:Configuration=RelWithDebInfo - name: Sign (BattlEye) run: | .\ci\battleye\signtool.exe sign /f .\ci\battleye\idi-systems.pfx /p ${{ secrets.BE_CRED_PASSWORD }} /t http://timestamp.digicert.com *.dll From 3cbcd5b27880e3b4add726acb325bd68fe174d4c Mon Sep 17 00:00:00 2001 From: jonpas Date: Wed, 20 Apr 2022 23:18:59 +0200 Subject: [PATCH 099/104] Update documentation for Mumble --- docs/wiki/development/building.md | 2 +- docs/wiki/development/tips-and-tricks.md | 18 +++++++++++++++++- docs/wiki/user/installation.md | 16 ++++++++-------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/wiki/development/building.md b/docs/wiki/development/building.md index fea3f7ce8..77e01bbd3 100644 --- a/docs/wiki/development/building.md +++ b/docs/wiki/development/building.md @@ -112,7 +112,7 @@ To start the game using this build, you can use the following modline: -mod=@CBA_A3;idi\acre ``` -You will also need `acre.dll` and `ACRE2Arma.dll` (or `acre_x64.dll` and `ACRE2Arma_x64.dll` for 64-bit) placed in `idi\acre` folder. You can obtain those from last release or [build them yourself](building-extensions). TeamSpeak plugin is not required for basic operation. +You will also need `acre.dll` and `ACRE2Arma.dll` (or `acre_x64.dll` and `ACRE2Arma_x64.dll` for 64-bit) placed in `idi\acre` folder. You can obtain those from last release or [build them yourself](building-extensions). Mumble/TeamSpeak plugin is not required for basic operation. ### Create a Release Build diff --git a/docs/wiki/development/tips-and-tricks.md b/docs/wiki/development/tips-and-tricks.md index 0afa42848..1e187fdfe 100644 --- a/docs/wiki/development/tips-and-tricks.md +++ b/docs/wiki/development/tips-and-tricks.md @@ -14,8 +14,24 @@ Reference [Radio Signal Debugging](/wiki/frameworks/radio-signal-debugging) page ## Extensions -### TeamSpeak 3 +### VOIP **Skip Plugin Auto-Copy** Run Arma 3 with `-skipAcrePluginCopy` startup parameter. + +#### TeamSpeak 3 + +**Skip TeamSpeak Plugin Auto-Copy** + +Run Arma 3 with `-skipAcreTSPluginCopy` startup parameter. + +#### Mumble + +**Skip Mumble Plugin Auto-Copy** + +Run Arma 3 with `-skipAcreMumblePluginCopy` startup parameter. + +**Specify Mumble Path** + +Run Arma 3 with `-mumblePath=` startup parameter. diff --git a/docs/wiki/user/installation.md b/docs/wiki/user/installation.md index 0e035e7e1..a1f43bba6 100644 --- a/docs/wiki/user/installation.md +++ b/docs/wiki/user/installation.md @@ -8,8 +8,8 @@ title: Installation - Subscribe to [ACRE2 on Steam](http://steamcommunity.com/sharedfiles/filedetails/?id=751965892) (make sure you are also subscribed to [CBA_A3](https://steamcommunity.com/sharedfiles/filedetails/?id=450814997)). - Launch Arma 3. -- ACRE2 will try to copy the plugins to your TeamSpeak 3 installation directory. A pop-up will appear describing what the process did. -- Launch TeamSpeak 3 and assure the ACRE2 plugin is enabled in the `Settings -> Plugins` window. +- ACRE2 will try to copy the plugins to your Mumble/TeamSpeak 3 installation directory. A pop-up will appear describing what the process did. +- Launch Mumble/TeamSpeak 3 and assure the ACRE2 plugin is enabled in the `Settings -> Plugins` window. ### Manual @@ -25,15 +25,15 @@ title: Installation - In the dialogue that appears, navigate to your Arma 3 installation folder and select the `@acre2` folder. - Enable the mod. - Launch Arma 3 in the Launcher. -- ACRE2 will try to copy the plugins to your TeamSpeak 3 installation directory. A pop-up will appear describing what the process did. -- Launch TeamSpeak 3 and assure the ACRE2 plugin is enabled in the `Settings -> Plugins` window. +- ACRE2 will try to copy the plugins to your Mumble/TeamSpeak 3 installation directory. A pop-up will appear describing what the process did. +- Launch Mumble/TeamSpeak 3 and assure the ACRE2 plugin is enabled in the `Settings -> Plugins` window. #### Shortcut - Create a new shortcut for Arma 3, or edit an existing one, and add `@acre2` and `@CBA_A3` to the `-mod` parameter. - Launch Arma 3 through the shortcut you created. -- ACRE2 will try to copy the plugins to your TeamSpeak 3 installation directory. A pop-up will appear describing what the process did. -- Launch TeamSpeak 3 and assure the ACRE2 plugin is enabled in the `Settings -> Plugins` window. +- ACRE2 will try to copy the plugins to your Mumble/TeamSpeak 3 installation directory. A pop-up will appear describing what the process did. +- Launch Mumble/TeamSpeak 3 and assure the ACRE2 plugin is enabled in the `Settings -> Plugins` window. ### Configuration @@ -45,8 +45,8 @@ Server administrators can get available settings using the [export/import featur ### Troubleshooting -- **WARNING: ACRE IS NOT CONNECTED TO TEAMSPEAK!** -Make sure to launch both Arma 3 (Steam) and TeamSpeak 3 as admin, or neither. +- **WARNING: ACRE is not connected to Mumble/TeamSpeak!** +Make sure to launch both Arma 3 (Steam) and Mumble/TeamSpeak 3 as admin, or neither. - **Radio beeps not audible on dedicated server** Make sure your `server.cfg` has `"b64"` whitelisted in `allowedLoadFileExtensions[]` and `allowedPreprocessFileExtensions[]` if you are using that. Let your server administrator know if you have no idea what this means. From 9e76d3fa5f5e72e25460f2f7b3acd3702f288e4a Mon Sep 17 00:00:00 2001 From: jonpas Date: Thu, 21 Apr 2022 00:11:53 +0200 Subject: [PATCH 100/104] Update Mumble plugin auto-copy Copy only to AppData and use installation to determine which architecture of plugin to copy (based on Program Files folder it is installed in). Add 32-bit support for copying a 64-bit extension. Only install the same plugin architecture as the Mumble installation (avoid warning in chat window). Cleanup registry reading in Mumble auto-copy code, as it is not reliable. --- extensions/src/ACRE2Steam/CallExt_DllMain.cpp | 20 ++- extensions/src/ACRE2Steam/mumble_plugin.cpp | 137 +++++++----------- extensions/src/ACRE2Steam/mumble_plugin.hpp | 3 - extensions/src/ACRE2Steam/voip_plugin.cpp | 18 ++- extensions/src/ACRE2Steam/voip_plugin.hpp | 10 +- 5 files changed, 90 insertions(+), 98 deletions(-) diff --git a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp index 87da162d7..af0a6c6a7 100644 --- a/extensions/src/ACRE2Steam/CallExt_DllMain.cpp +++ b/extensions/src/ACRE2Steam/CallExt_DllMain.cpp @@ -70,10 +70,10 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { const bool skip_ts_plugin = cmd_args.has_argument("-skipAcreTSPluginCopy"); const bool skip_mumble_plugin = cmd_args.has_argument("-skipAcreMumblePluginCopy"); - std::string test = cmd_args.get_argument("-mumblePath"); + const std::string mumble_path = cmd_args.get_argument("-mumblePath"); idi::acre::TS3Plugin ts3_plugin(skip_ts_plugin); - idi::acre::MumblePlugin mumble_plugin(skip_mumble_plugin, cmd_args.get_argument("-mumblePath")); + idi::acre::MumblePlugin mumble_plugin(skip_mumble_plugin, mumble_path); switch (command) { case SteamCommand::check: { @@ -102,7 +102,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { std::end(mumble_plugin.get_missing_acre_plugins())); std::ostringstream oss; - oss << "ACRE2 was unable to find ACRE 2 plugin files.\n\n"; + oss << "ACRE2 was unable to find ACRE2 plugin files.\n\n"; for (const auto &missing : missing_plugins) { oss << "\t" << missing << "\n"; } @@ -120,7 +120,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!ts3_locations_success && !mumble_locations_success) { const std::int32_t result = MessageBoxA(nullptr, "ACRE2 was unable to find a TeamSpeak 3 or a Mumble installation. If you do have an installation please copy the plugins " - "yourself or reinstall TeamSpeak 3.\n\nIf you are sure you have Mumble and/or TeamSpeak 3 installed and wish to " + "yourself or reinstall TeamSpeak 3 or Mumble.\n\nIf you are sure you have TeamSpeak 3 and/or Mumble installed and wish to " "prevent this message from appearing again remove ACRE2Steam.dll and ACRE2Steam_x64.dll from your @acre2 " "folder.\n\nContinue anyway?", "ACRE2 Installation Error", MB_YESNO | MB_ICONEXCLAMATION); @@ -163,6 +163,8 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { << "folder, close any instances of TeamSpeak 3 and/or Mumble and click \"Try Again\".\n\nIf you " << "would like to close Arma 3 click Cancel. Press Continue to launch Arma 3 regardless.\n\n" << error_msg; + + const int32_t result = MessageBoxA( nullptr, (LPCSTR) oss.str().c_str(), "ACRE2 Installation Error", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); if (result == IDCANCEL) { @@ -200,8 +202,16 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!mumble_plugin.get_updated_paths().empty()) { oss << "The Mumble plugins have been copied to the following location(s):\n"; + + std::string arch_installed = ""; + if (mumble_plugin.get_arch_to_install() == idi::acre::Architecture::x32) { + arch_installed = " [32-bit only]"; + } else if (mumble_plugin.get_arch_to_install() == idi::acre::Architecture::x64) { + arch_installed = " [64-bit only]"; + } + for (const auto &path : mumble_plugin.get_updated_paths()) { - oss << path << "\n"; + oss << path << arch_installed << "\n"; found_paths.append(path + "\n"); } diff --git a/extensions/src/ACRE2Steam/mumble_plugin.cpp b/extensions/src/ACRE2Steam/mumble_plugin.cpp index 9643badf2..a3f611224 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.cpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.cpp @@ -10,105 +10,78 @@ bool MumblePlugin::collect_plugin_locations() noexcept { } if (!mumble_path.empty()) { + // Install both plugins if a path is given, as there is no official portable Mumble + // and a warning in chat window is fine for development purposes check_plugin_locations(mumble_path); } else { - parse_mumble_registry(false); // 32 bits - parse_mumble_registry(true); // 64 bits + // Mumble location - Default location - Roaming Appdata. + wchar_t *app_data_roaming = nullptr; + SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &app_data_roaming); - // TODO: 32 bits applications will not recognise FOLDERID_ProgramFilesX64 + if (app_data_roaming == nullptr) { + return false; + } + + // Convert to UTF-8 string + std::string app_data = VOIPPlugin::wide_string_to_utf8(app_data_roaming); + CoTaskMemFree(app_data_roaming); // Free it up. + + // Path to install into (AppData/Roaming) + app_data.append("\\Mumble"); + + // Pick which architecture of the plugin to install to avoid Mumble showing warnings in the chat window + bool x32_installed = false; + bool x64_installed = false; std::array folder_ids = {FOLDERID_ProgramFilesX86, FOLDERID_ProgramFilesX64}; - for (const auto folder : folder_ids) { + for (const auto &folder : folder_ids) { + std::string program_data; + wchar_t *folder_path = nullptr; SHGetKnownFolderPath(folder, 0, nullptr, &folder_path); - if (folder_path == nullptr) { - return false; +#ifdef _WIN64 + continue; +#else + // FOLDERID_ProgramFilesX64 (or use of it in SHGetKnownFolderPath) is not supported in a 32-bit application, + // but we may want to install x64 Mumble plugin while running x32 Arma, + // fall back to registry read of x64 Program Files location + program_data = read_reg_value(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProgramFilesDir", true); + if (program_data.empty()) { + continue; + } +#endif + } else { + // Convert to UTF-8 string + program_data = VOIPPlugin::wide_string_to_utf8(folder_path); } - - // Convert to UTF-8 string - std::string app_data = VOIPPlugin::wide_string_to_utf8(folder_path); - - app_data.append("\\Mumble"); - check_plugin_locations(app_data); - - // Now do the same for x64 CoTaskMemFree(folder_path); // Free it up. - } - } - - // Do not delete if we need to copy it - std::vector mumble_locations = get_plugin_locations(); - std::vector mumble_delete_locations = get_plugin_delete_locations(); - - for (const auto &location : mumble_locations) { - mumble_delete_locations.erase( - std::remove(mumble_delete_locations.begin(), mumble_delete_locations.end(), location), mumble_delete_locations.end()); - } - - // No locations to copy to. - return !get_plugin_locations().empty(); -} - -void MumblePlugin::parse_mumble_registry(const bool use_x64_) noexcept { - REGSAM sam_key = KEY_READ | KEY_WOW64_64KEY; - if (!use_x64_) { - sam_key = KEY_READ; - } - - HKEY registry_key; - if (RegOpenKeyEx(HKEY_CURRENT_USER, get_registry_key().c_str(), 0, sam_key, ®istry_key) != ERROR_SUCCESS) { - return; - } - - DWORD num_subkeys = 0; - if (RegQueryInfoKey(registry_key, nullptr, nullptr, nullptr, &num_subkeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr) != ERROR_SUCCESS) { - RegCloseKey(registry_key); - return; - } - - for (DWORD idx = 0; idx < num_subkeys; idx++) { - TCHAR achKey[max_key_length]; - DWORD cbName = max_key_length; - if (RegEnumKeyEx(registry_key, idx, achKey, &cbName, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS) { - continue; - } + program_data.append("\\Mumble"); - HKEY plugin_key; - std::string name = get_registry_key() + "\\" + std::string(achKey); - if (RegOpenKeyEx(HKEY_CURRENT_USER, name.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &plugin_key) != ERROR_SUCCESS) { - continue; - } - - DWORD type; - DWORD cbData; - if (RegQueryValueEx(plugin_key, "path", nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS) { - RegCloseKey(plugin_key); - continue; + if (std::filesystem::exists(program_data)) { + if (folder == folder_ids[0]) { + x32_installed = true; + } else if (folder == folder_ids[1]) { + x64_installed = true; + } + } } - if (type != REG_SZ) { - RegCloseKey(plugin_key); - continue; + // Mumble is not installed at all, don't copy plugins + if (!x32_installed && !x64_installed) { + return false; } - std::string file_path(cbData / sizeof(char), '\0'); - if (RegQueryValueEx(plugin_key, "path", nullptr, nullptr, reinterpret_cast(&file_path[0]), &cbData) == ERROR_SUCCESS) { - RegCloseKey(plugin_key); - - size_t first_null = file_path.find_first_of('\0'); - if (first_null != std::string::npos) { - file_path.resize(first_null); - } + // Otherwise copy to AppData and set the found architecture + check_plugin_locations(app_data); - std::filesystem::path plugin_path(file_path); - if (std::filesystem::exists(plugin_path)) { - const std::string mumble_path = plugin_path.parent_path().parent_path().string(); - check_plugin_locations(mumble_path); - } + if (x32_installed && !x64_installed) { + set_arch_to_install(Architecture::x32); + } else if (!x32_installed && x64_installed) { + set_arch_to_install(Architecture::x64); } } - RegCloseKey(registry_key); + // No locations to copy to. + return !get_plugin_locations().empty(); } diff --git a/extensions/src/ACRE2Steam/mumble_plugin.hpp b/extensions/src/ACRE2Steam/mumble_plugin.hpp index d33b88186..7c018c16b 100644 --- a/extensions/src/ACRE2Steam/mumble_plugin.hpp +++ b/extensions/src/ACRE2Steam/mumble_plugin.hpp @@ -25,9 +25,6 @@ namespace idi::acre { bool collect_plugin_locations() noexcept final; private: - void parse_mumble_registry(const bool use_x64_) noexcept; - - static constexpr std::uint8_t max_key_length = 255U; std::string mumble_path; }; } // namespace idi::acre diff --git a/extensions/src/ACRE2Steam/voip_plugin.cpp b/extensions/src/ACRE2Steam/voip_plugin.cpp index 63b9c41fb..7a279d560 100644 --- a/extensions/src/ACRE2Steam/voip_plugin.cpp +++ b/extensions/src/ACRE2Steam/voip_plugin.cpp @@ -151,16 +151,18 @@ void VOIPPlugin::check_plugin_locations(const std::string &app_data_, const std: bool VOIPPlugin::check_acre_installation() noexcept { const bool x32_plugin_exist = std::filesystem::exists(x32_acre_plugin); const bool x64_plugin_exist = std::filesystem::exists(x64_acre_plugin); + const bool x32_install = arch_to_install == Architecture::both || arch_to_install == Architecture::x32; + const bool x64_install = arch_to_install == Architecture::both || arch_to_install == Architecture::x64; - if (!x32_plugin_exist) { + if (!x32_plugin_exist && x32_install) { missing_acre_plugins.emplace_back(x32_acre_plugin.filename().string()); } - if (!x64_plugin_exist) { + if (!x64_plugin_exist && x64_install) { missing_acre_plugins.emplace_back(x64_acre_plugin.filename().string()); } - return x32_plugin_exist && x64_plugin_exist; + return (x32_plugin_exist || !x32_install) && (x64_plugin_exist || !x64_install); } idi::acre::UpdateCode VOIPPlugin::handle_update_plugin() noexcept { @@ -190,9 +192,13 @@ idi::acre::UpdateCode VOIPPlugin::handle_update_plugin() noexcept { return UpdateCode::other; } - std::array, 2> plugin_paths_array = { - std::make_pair(plugin_folder / "acre2_win32.dll", x32_acre_plugin), - std::make_pair(plugin_folder / "acre2_win64.dll", x64_acre_plugin)}; + std::vector> plugin_paths_array; + if (arch_to_install == Architecture::both || arch_to_install == Architecture::x32) { + plugin_paths_array.push_back(std::make_pair(plugin_folder / "acre2_win32.dll", x32_acre_plugin)); + } + if (arch_to_install == Architecture::both || arch_to_install == Architecture::x64) { + plugin_paths_array.push_back(std::make_pair(plugin_folder / "acre2_win64.dll", x64_acre_plugin)); + } for (const auto &path : plugin_paths_array) { if (!compare_file(path.first.string(), path.second.string())) { diff --git a/extensions/src/ACRE2Steam/voip_plugin.hpp b/extensions/src/ACRE2Steam/voip_plugin.hpp index 1d6de0831..17a8b2073 100644 --- a/extensions/src/ACRE2Steam/voip_plugin.hpp +++ b/extensions/src/ACRE2Steam/voip_plugin.hpp @@ -26,6 +26,7 @@ namespace idi::acre { std::string find_mod_file(const std::string &filename); enum class UpdateCode : std::uint8_t { update_not_necessary, update_ok, update_failed, other }; + enum class Architecture : std::uint8_t { both, x32, x64 }; class VOIPPlugin { public: @@ -56,6 +57,8 @@ namespace idi::acre { std::string read_reg_value(HKEY root_, const std::string &key_, const std::string &name_, bool use_x64_) noexcept; + const Architecture &get_arch_to_install() const noexcept { return arch_to_install; } + protected: // Convert a wide Unicode string to an UTF8 string @@ -94,20 +97,23 @@ namespace idi::acre { std::vector &get_plugin_delete_locations() noexcept { return plugin_delete_locations; } void set_plugin_delete_locations(const std::vector locations_) { plugin_delete_locations = locations_; } + void set_arch_to_install(Architecture arch_) { arch_to_install = arch_; } + private: bool skip_plugin = false; std::string registry_key; std::string last_error_msg; std::error_code last_error; - std::vector plugin_locations; // Locations to copy the TS dll to. - std::vector plugin_delete_locations; // Locations to remove the TS dll from. + std::vector plugin_locations; // Locations to copy the VOIP dll to. + std::vector plugin_delete_locations; // Locations to remove the VOIP dll from. std::vector updated_paths; std::vector removed_paths; std::filesystem::path x32_acre_plugin; std::filesystem::path x64_acre_plugin; + Architecture arch_to_install = Architecture::both; std::vector missing_acre_plugins; }; } // namespace idi::acre From ff2be64fa84dd8b45d590192bdd49831b0aeba8c Mon Sep 17 00:00:00 2001 From: jonpas Date: Thu, 21 Apr 2022 00:33:02 +0200 Subject: [PATCH 101/104] Print Plugin version to Mumble log --- extensions/src/ACRE2Mumble/MumbleClient.cpp | 7 +++---- extensions/src/ACRE2Mumble/MumbleClient.h | 6 ------ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/extensions/src/ACRE2Mumble/MumbleClient.cpp b/extensions/src/ACRE2Mumble/MumbleClient.cpp index 0ea52fefe..d883b6076 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.cpp +++ b/extensions/src/ACRE2Mumble/MumbleClient.cpp @@ -68,9 +68,8 @@ acre::Result CMumbleClient::start(const acre::id_t id_) { this->setState(acre::State::running); this->setIsX3DInitialized(false); - // this->m_versionThreadHandle = std::thread(&CMumbleClient::exPersistVersion, this); - - mumAPI.log(pluginID, "started"); + mumAPI.log(pluginID, "Started"); + mumAPI.log(pluginID, ACRE_VERSION_METADATA); return acre::Result::ok; } @@ -324,7 +323,7 @@ uint64_t CMumbleClient::findChannelByNames(std::vector details_) { name = details_.at(0); } - for (std::size_t idx = 0U; idx < channelCount; idx++) { + for (std::int32_t idx = 0U; idx < channelCount; idx++) { channelId = *channelList + idx; const char *channelName = nullptr; diff --git a/extensions/src/ACRE2Mumble/MumbleClient.h b/extensions/src/ACRE2Mumble/MumbleClient.h index 1fffd0361..74c4137c7 100644 --- a/extensions/src/ACRE2Mumble/MumbleClient.h +++ b/extensions/src/ACRE2Mumble/MumbleClient.h @@ -22,14 +22,8 @@ class CMumbleClient : public IClient { acre::Result stop() final; acre::Result start(const acre::id_t id_) final; - acre::Result exPersistVersion(void); - - acre::Result setClientMetadata(const char *const data); - acre::Result enableMicrophone(const bool status_) final; - bool getInputStatus(); - bool getVAD(); /*! From 421b7a7d574ddca827b2ef94b8d9c1acff304f63 Mon Sep 17 00:00:00 2001 From: jonpas Date: Thu, 21 Apr 2022 01:36:49 +0200 Subject: [PATCH 102/104] v2.9.1.1049 - Mumble --- addons/main/script_version.hpp | 2 +- extensions/src/ACRE2Shared/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index 61bbcc75f..3c0d5f2fb 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 2 #define MINOR 9 #define PATCHLVL 1 -#define BUILD 1048 +#define BUILD 1049 diff --git a/extensions/src/ACRE2Shared/version.h b/extensions/src/ACRE2Shared/version.h index e98941c68..b4f359e43 100644 --- a/extensions/src/ACRE2Shared/version.h +++ b/extensions/src/ACRE2Shared/version.h @@ -1,4 +1,4 @@ #define ACRE_VERSION_MAJOR 2 #define ACRE_VERSION_MINOR 9 #define ACRE_VERSION_SUBMINOR 1 -#define ACRE_VERSION_BUILD 1048 +#define ACRE_VERSION_BUILD 1049 From 3a6eaccb6e2fa286e93c812c25f798b9b70b174b Mon Sep 17 00:00:00 2001 From: jonpas Date: Thu, 21 Apr 2022 14:07:44 +0200 Subject: [PATCH 103/104] Cleanup some extension code --- extensions/src/ACRE2Shared/Lockable.h | 4 ++-- extensions/src/ACRE2TS/CommandServer.cpp | 21 +++++++++------------ extensions/src/ACRE2TS/CommandServer.h | 17 ++++++++--------- extensions/src/ACRE2TS/acre2_ts_dllmain.cpp | 6 +++--- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/extensions/src/ACRE2Shared/Lockable.h b/extensions/src/ACRE2Shared/Lockable.h index 3e74fdd24..dfe9d205c 100644 --- a/extensions/src/ACRE2Shared/Lockable.h +++ b/extensions/src/ACRE2Shared/Lockable.h @@ -7,11 +7,11 @@ class CLockable { private: std::recursive_mutex m_lockable_mutex; public: - void lock( void ) { + void lock() { m_lockable_mutex.lock(); }; - void unlock( void ) { + void unlock() { m_lockable_mutex.unlock(); }; }; diff --git a/extensions/src/ACRE2TS/CommandServer.cpp b/extensions/src/ACRE2TS/CommandServer.cpp index e24bf7ce5..d71632992 100644 --- a/extensions/src/ACRE2TS/CommandServer.cpp +++ b/extensions/src/ACRE2TS/CommandServer.cpp @@ -9,13 +9,13 @@ extern TS3Functions ts3Functions; -acre::Result CCommandServer::initialize(void){ +acre::Result CCommandServer::initialize(){ TRACE("enter"); return acre::Result::ok; } -acre::Result CCommandServer::shutdown(void) { +acre::Result CCommandServer::shutdown() { TRACE("enter"); return acre::Result::ok; @@ -26,8 +26,8 @@ acre::Result CCommandServer::sendMessage(IMessage *msg){ LOCK(this); //LOG("Sending: %s", (const char *)msg->getData()); ts3Functions.sendPluginCommand((unsigned __int64)ts3Functions.getCurrentServerConnectionHandlerID(), - (const char *)this->getCommandId(), - (const char *)msg->getData(), + (const char *)this->getCommandId(), + (const char *)msg->getData(), PluginCommandTarget_CURRENT_CHANNEL, NULL, NULL); //LOG("sending [%s], [%s]", this->getCommandId(), msg->getData()); @@ -49,10 +49,10 @@ acre::Result CCommandServer::handleMessage(unsigned char *data){ } -acre::Result CCommandServer::release(void) { - - if (this->getCommandId()) +acre::Result CCommandServer::release() { + if (this->getCommandId()) { free(this->getCommandId()); + } return acre::Result::ok; } @@ -60,14 +60,11 @@ acre::Result CCommandServer::release(void) { // // constructor/destructor foo -// +// CCommandServer::CCommandServer(const acre::id_t id) { this->setId(id); } -CCommandServer::CCommandServer(void) { +CCommandServer::CCommandServer() { this->setCommandId(nullptr); this->setConnected(true); } -CCommandServer::~CCommandServer() { - -} diff --git a/extensions/src/ACRE2TS/CommandServer.h b/extensions/src/ACRE2TS/CommandServer.h index 234e8fced..97d126571 100644 --- a/extensions/src/ACRE2TS/CommandServer.h +++ b/extensions/src/ACRE2TS/CommandServer.h @@ -9,26 +9,25 @@ #include "Engine.h" #include "Lockable.h" -class CCommandServer : public IServer, public CLockable -{ +class CCommandServer : public IServer, public CLockable { public: - CCommandServer(void); + CCommandServer(); CCommandServer(const acre::id_t id); - ~CCommandServer(void); + ~CCommandServer() = default; - acre::Result initialize(void); - acre::Result shutdown(void); + acre::Result initialize(); + acre::Result shutdown(); acre::Result sendMessage(IMessage *msg); acre::Result handleMessage(unsigned char *msg); - acre::Result handleMessage(unsigned char* msg, size_t length) override { + acre::Result handleMessage(unsigned char *msg, size_t length) override { (void)msg; (void)length; return acre::Result::notImplemented; } - acre::Result release(void); + acre::Result release(); inline void setCommandId(char *const value) { m_commandId = value; } inline char* getCommandId() const { return m_commandId; } @@ -37,7 +36,7 @@ class CCommandServer : public IServer, public CLockable inline bool getConnected() const final { return m_connected; } inline void setId(const acre::id_t value) final { m_id = value; } - inline acre::id_t getId() const final { return m_id; } + inline acre::id_t getId() const final { return m_id; } protected: acre::id_t m_id; diff --git a/extensions/src/ACRE2TS/acre2_ts_dllmain.cpp b/extensions/src/ACRE2TS/acre2_ts_dllmain.cpp index 48e1cd710..33c9aa38f 100644 --- a/extensions/src/ACRE2TS/acre2_ts_dllmain.cpp +++ b/extensions/src/ACRE2TS/acre2_ts_dllmain.cpp @@ -16,9 +16,9 @@ BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID) { if (reason == DLL_PROCESS_ATTACH){ //g_Log = (Log *)new Log("acre.log"); } - if (reason == DLL_PROCESS_DETACH) { - + if (reason == DLL_PROCESS_DETACH) { + } return 1; } -*/ \ No newline at end of file +*/ From bd90476da71d7ebcdc1f5d7637dcd010e177c209 Mon Sep 17 00:00:00 2001 From: jonpas Date: Wed, 25 May 2022 16:16:52 +0200 Subject: [PATCH 104/104] v2.10.0.1051 - Mumble --- addons/main/script_version.hpp | 2 +- extensions/src/ACRE2Shared/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index aeb4be999..33bfd4658 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 2 #define MINOR 10 #define PATCHLVL 0 -#define BUILD 1050 +#define BUILD 1051 diff --git a/extensions/src/ACRE2Shared/version.h b/extensions/src/ACRE2Shared/version.h index da6827751..c8c9079d0 100644 --- a/extensions/src/ACRE2Shared/version.h +++ b/extensions/src/ACRE2Shared/version.h @@ -1,4 +1,4 @@ #define ACRE_VERSION_MAJOR 2 #define ACRE_VERSION_MINOR 10 #define ACRE_VERSION_SUBMINOR 0 -#define ACRE_VERSION_BUILD 1050 +#define ACRE_VERSION_BUILD 1051