Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/mumble/Plugin.h')
-rw-r--r--src/mumble/Plugin.h417
1 files changed, 417 insertions, 0 deletions
diff --git a/src/mumble/Plugin.h b/src/mumble/Plugin.h
new file mode 100644
index 000000000..049e622f2
--- /dev/null
+++ b/src/mumble/Plugin.h
@@ -0,0 +1,417 @@
+// 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 <https://www.mumble.info/LICENSE>.
+
+#ifndef MUMBLE_MUMBLE_PLUGIN_H_
+#define MUMBLE_MUMBLE_PLUGIN_H_
+
+#include "MumbleAPI_v_1_0_x.h"
+#include "PluginComponents_v_1_0_x.h"
+#include "PositionalData.h"
+#include "MumblePlugin_v_1_0_x.h"
+
+#include <QObject>
+#include <QReadWriteLock>
+#include <QString>
+#include <QLibrary>
+#include <QMutex>
+#include <QUrl>
+
+#include <stdexcept>
+#include <memory>
+
+/// A struct for holding the function pointers to the functions inside the plugin's library
+/// For the documentation of those functions, see the plugin's header file (the one used when developing a plugin)
+struct MumblePluginFunctions {
+ decltype(&mumble_init) init;
+ decltype(&mumble_shutdown) shutdown;
+ decltype(&mumble_getName) getName;
+ decltype(&mumble_getAPIVersion) getAPIVersion;
+ decltype(&mumble_registerAPIFunctions) registerAPIFunctions;
+ decltype(&mumble_releaseResource) releaseResource;
+
+ // Further utility functions the plugin may implement
+ decltype(&mumble_setMumbleInfo) setMumbleInfo;
+ decltype(&mumble_getVersion) getVersion;
+ decltype(&mumble_getAuthor) getAuthor;
+ decltype(&mumble_getDescription) getDescription;
+ decltype(&mumble_getFeatures) getFeatures;
+ decltype(&mumble_deactivateFeatures) deactivateFeatures;
+
+ // Functions for dealing with positional audio (or rather the fetching of the needed data)
+ decltype(&mumble_initPositionalData) initPositionalData;
+ decltype(&mumble_fetchPositionalData) fetchPositionalData;
+ decltype(&mumble_shutdownPositionalData) shutdownPositionalData;
+
+ // Callback functions and EventHandlers
+ decltype(&mumble_onServerConnected) onServerConnected;
+ decltype(&mumble_onServerDisconnected) onServerDisconnected;
+ decltype(&mumble_onChannelEntered) onChannelEntered;
+ decltype(&mumble_onChannelExited) onChannelExited;
+ decltype(&mumble_onUserTalkingStateChanged) onUserTalkingStateChanged;
+ decltype(&mumble_onReceiveData) onReceiveData;
+ decltype(&mumble_onAudioInput) onAudioInput;
+ decltype(&mumble_onAudioSourceFetched) onAudioSourceFetched;
+ decltype(&mumble_onAudioOutputAboutToPlay) onAudioOutputAboutToPlay;
+ decltype(&mumble_onServerSynchronized) onServerSynchronized;
+ decltype(&mumble_onUserAdded) onUserAdded;
+ decltype(&mumble_onUserRemoved) onUserRemoved;
+ decltype(&mumble_onChannelAdded) onChannelAdded;
+ decltype(&mumble_onChannelRemoved) onChannelRemoved;
+ decltype(&mumble_onChannelRenamed) onChannelRenamed;
+ decltype(&mumble_onKeyEvent) onKeyEvent;
+
+ // Plugin updates
+ decltype(&mumble_hasUpdate) hasUpdate;
+ decltype(&mumble_getUpdateDownloadURL) getUpdateDownloadURL;
+};
+
+
+/// An exception that is being thrown by a plugin whenever it encounters an error
+class PluginError : public std::runtime_error {
+ public:
+ // inherit constructors of runtime_error
+ using std::runtime_error::runtime_error;
+};
+
+
+/// An implementation similar to QReadLocker except that this one allows to lock on a lock the same thread is already
+/// holding a write-lock on. This could also result in obtaining a write-lock though so it shouldn't be used for code regions
+/// that take quite some time and rely on other readers still having access to the locked object.
+class PluginReadLocker {
+ protected:
+ /// The lock this lock-guard is acting upon
+ QReadWriteLock *m_lock;
+ /// A flag indicating whether the lock has been unlocked (manually) and thus doesn't have to be unlocked
+ /// in the destructor.
+ bool m_unlocked;
+ public:
+ /// Constructor of the PluginReadLocker. If the passed lock-pointer is not nullptr, the constructor will
+ /// already lock the provided lock.
+ ///
+ /// @param lock A pointer to the QReadWriteLock that shall be managed by this object. May be nullptr
+ PluginReadLocker(QReadWriteLock *lock);
+ /// Locks this lock again after it has been unlocked before (Locking a locked lock results in a runtime error)
+ void relock();
+ /// Unlocks this lock
+ void unlock();
+ ~PluginReadLocker();
+};
+
+class Plugin;
+
+/// Typedef for the plugin ID
+typedef uint32_t plugin_id_t;
+/// Typedef for a plugin pointer
+typedef std::shared_ptr<Plugin> plugin_ptr_t;
+/// Typedef for a const plugin pointer
+typedef std::shared_ptr<const Plugin> const_plugin_ptr_t;
+
+/// A class representing a plugin library attached to Mumble. It can be used to manage (load/unload) and access plugin libraries.
+class Plugin : public QObject {
+ friend class PluginManager;
+ friend class PluginConfig;
+
+ private:
+ Q_OBJECT
+ Q_DISABLE_COPY(Plugin)
+ protected:
+ /// A mutex guarding Plugin::nextID
+ static QMutex s_idLock;
+ /// The ID of the plugin that will be loaded next. Whenever accessing this field, Plugin::idLock should be locked.
+ static plugin_id_t s_nextID;
+
+ /// Constructor of the Plugin.
+ ///
+ /// @param path The path to the plugin's shared library file. This path has to exist unless isBuiltIn is true
+ /// @param isBuiltIn A flag indicating that this is a plugin built into Mumble itself and is does not backed by a shared library
+ /// @param p A pointer to a QObject representing the parent of this object or nullptr if there is no parent
+ Plugin(QString path, bool isBuiltIn = false, QObject *p = nullptr);
+
+ /// A flag indicating whether this plugin is valid. It is mainly used throughout the plugin's initialization.
+ bool m_pluginIsValid;
+ /// The QLibrary representing the shared library of this plugin
+ QLibrary m_lib;
+ /// The path to the shared library file in the host's filesystem
+ QString m_pluginPath;
+ /// The unique ID of this plugin. Note though that this ID is not suitable for uniquely identifying this plugin between restarts of Mumble
+ /// (not even between rescans of the plugins) let alone across clients.
+ plugin_id_t m_pluginID;
+ // a flag indicating whether this plugin has been loaded by calling its init function.
+ bool m_pluginIsLoaded;
+ /// The lock guarding this plugin object. Every time a member is accessed this lock should be locked accordingly.
+ /// After successful construction and initialization (doInitilize()), this member variable is effectively const
+ /// and therefore no locking is required in order to read from it!
+ /// In fact protecting read-accesses by a non-recursive lock can introduce deadlocks by plugins using certain
+ /// API functions.
+ mutable QReadWriteLock m_pluginLock;
+ /// The struct holding the function pointers to the functions in the shared library.
+ MumblePluginFunctions m_pluginFnc;
+ /// A flag indicating whether this plugin is built into Mumble and is thus not represented by a shared library.
+ bool m_isBuiltIn;
+ /// A flag indicating whether positional data gathering is enabled for this plugin (Enabled as in allowed via preferences).
+ bool m_positionalDataIsEnabled;
+ /// A flag indicating whether positional data gathering is currently active (Active as in running)
+ bool m_positionalDataIsActive;
+ /// A flag indicating whether this plugin has permission to monitor keyboard events that occur while
+ /// Mumble has the keyboard focus.
+ bool m_mayMonitorKeyboard;
+
+
+ QString extractWrappedString(MumbleStringWrapper wrapper) const;
+
+
+ // Most of this class's functions are protected in order to only allow access to them via the PluginManager
+ // as some require additional handling before/after calling them.
+
+ /// Initializes this plugin. This function must be called directly after construction. This is guaranteed when the
+ /// plugin is created via Plugin::createNew
+ virtual bool doInitialize();
+ /// Resolves the function pointers in the shared library and sets the respective fields in Plugin::apiFnc
+ virtual void resolveFunctionPointers();
+ /// Enables positional data gathering for this plugin (as in allowing)
+ ///
+ /// @param enable Whether to enable the data gathering
+ virtual void enablePositionalData(bool enable = true);
+ /// Allows or forbids the monitoring of keyboard events for this plugin.
+ ///
+ /// @param allow Whether to allow or forbid it
+ virtual void allowKeyboardMonitoring(bool allow);
+
+
+ /// Initializes this plugin
+ virtual mumble_error_t init();
+ /// Shuts this plugin down
+ virtual void shutdown();
+ /// Delegates the struct of API function pointers to the plugin backend
+ ///
+ /// @param api The pointer to the API struct
+ virtual void registerAPIFunctions(void *api) const;
+ /// Asks the plugin to release (free/delete) the resource pointed to by the given pointer
+ ///
+ /// @param pointer Pointer to the resource
+ virtual void releaseResource(const void *pointer) const;
+ /// Provides the plugin backend with some version information about Mumble
+ ///
+ /// @param mumbleVersion The version of the Mumble client
+ /// @param mumbleAPIVersion The API version used by the Mumble client
+ /// @param minimalExpectedAPIVersion The minimal API version expected to be used by the plugin backend
+ virtual void setMumbleInfo(mumble_version_t mumbleVersion, mumble_version_t mumbleAPIVersion, mumble_version_t minimalExpectedAPIVersion) const;
+ /// Asks the plugin to deactivate certain features
+ ///
+ /// @param features The feature list or'ed together
+ /// @returns The list of features that couldn't be deactivated or'ed together
+ virtual uint32_t deactivateFeatures(uint32_t features) const;
+ /// Shows an about-dialog
+ ///
+ /// @parent A pointer to the QWidget that should be used as a parent
+ /// @returns Whether the dialog could be shown successfully
+ virtual bool showAboutDialog(QWidget *parent) const;
+ /// Shows a config-dialog
+ ///
+ /// @parent A pointer to the QWidget that should be used as a parent
+ /// @returns Whether the dialog could be shown successfully
+ virtual bool showConfigDialog(QWidget *parent) const;
+ /// Initializes the positional data gathering
+ ///
+ /// @params programNames A pointer to an array of const char* representing the program names
+ /// @params programCount A pointer to an array of PIDs corresponding to the program names
+ /// @params programCount The length of the two previous arrays
+ virtual uint8_t initPositionalData(const char *const*programNames, const uint64_t *programPIDs, size_t programCount);
+ /// Fetches the positional data
+ ///
+ /// @param[out] avatarPos The position of the ingame avatar (player)
+ /// @param[out] avatarDir The directiion in which the avatar (player) is looking/facing
+ /// @param[out] avatarAxis The vector from the avatar's toes to its head
+ /// @param[out] cameraPos The position of the ingame camera
+ /// @param[out] cameraDir The direction in which the camera is looking/facing
+ /// @param[out] cameraAxis The vector from the camera's bottom to its top
+ /// @param[out] context The context of the current game-session (includes server/squad info)
+ /// @param[out] identity The ingame identity of the player (name)
+ virtual bool fetchPositionalData(Position3D& avatarPos, Vector3D& avatarDir, Vector3D& avatarAxis, Position3D& cameraPos, Vector3D& cameraDir,
+ Vector3D& cameraAxis, QString& context, QString& identity) const;
+ /// Shuts down positional data gathering
+ virtual void shutdownPositionalData();
+ /// Called to indicate that the client has connected to a server
+ ///
+ /// @param connection An object used to identify the current connection
+ virtual void onServerConnected(mumble_connection_t connection) const;
+ /// Called to indicate that the client disconnected from a server
+ ///
+ /// @param connection An object used to identify the connection that has been disconnected
+ virtual void onServerDisconnected(mumble_connection_t connection) const;
+ /// Called to indicate that a user has switched its channel
+ ///
+ /// @param connection An object used to identify the current connection
+ /// @param userID The ID of the user that switched channel
+ /// @param previousChannelID The ID of the channel the user came from (-1 if there is no previous channel)
+ /// æparam newChannelID The ID of the channel the user has switched to
+ virtual void onChannelEntered(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t previousChannelID,
+ mumble_channelid_t newChannelID) const;
+ /// Called to indicate that a user exited a channel.
+ ///
+ /// @param connection An object used to identify the current connection
+ /// @param userID The ID of the user that switched channel
+ /// @param channelID The ID of the channel the user exited
+ virtual void onChannelExited(mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID) const;
+ /// Called to indicate that a user has changed its talking state
+ ///
+ /// @param connection An object used to identify the current connection
+ /// @param userID The ID of the user that switched channel
+ /// @param talkingState The new talking state of the user
+ virtual void onUserTalkingStateChanged(mumble_connection_t connection, mumble_userid_t userID, mumble_talking_state_t talkingState) const;
+ /// Called to indicate that a data packet has been received
+ ///
+ /// @param connection An object used to identify the current connection
+ /// @param sender The ID of the user whose client sent the data
+ /// @param data The actual data
+ /// @param dataLength The length of the data array
+ /// @param datID The ID of the data used to determine whether this plugin handles this data or not
+ /// @returns Whether this plugin handled the data
+ virtual bool onReceiveData(mumble_connection_t connection, mumble_userid_t sender, const uint8_t *data, size_t dataLength, const char *dataID) const;
+ /// Called to indicate that there is audio input
+ ///
+ /// @param inputPCM A pointer to a short array representing the input PCM
+ /// @param sampleCount The amount of samples per channel
+ /// @param channelCount The amount of channels in the PCM
+ /// @param sampleRate The used sample rate in Hz
+ /// @param isSpeech Whether Mumble considers the input as speech
+ /// @returns Whether this pluign has modified the audio
+ virtual bool onAudioInput(short *inputPCM, uint32_t sampleCount, uint16_t channelCount, uint32_t sampleRate, bool isSpeech) const;
+ /// Called to indicate that an audio source has been fetched
+ ///
+ /// @param outputPCM A pointer to a short array representing the output PCM
+ /// @param sampleCount The amount of samples per channel
+ /// @param channelCount The amount of channels in the PCM
+ /// @param sampleRate The used sample rate in Hz
+ /// @param isSpeech Whether Mumble considers the output as speech
+ /// @param userID The ID of the user responsible for the output (only relevant if isSpeech == true)
+ /// @returns Whether this pluign has modified the audio
+ virtual bool onAudioSourceFetched(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, uint32_t sampleRate, bool isSpeech, mumble_userid_t userID) const;
+ /// Called to indicate that audio is about to be played
+ ///
+ /// @param outputPCM A pointer to a short array representing the output PCM
+ /// @param sampleCount The amount of samples per channel
+ /// @param channelCount The amount of channels in the PCM
+ /// @param sampleRate The used sample rate in Hz
+ /// @returns Whether this pluign has modified the audio
+ virtual bool onAudioOutputAboutToPlay(float *outputPCM, uint32_t sampleCount, uint16_t channelCount, uint32_t sampleRate) const;
+ /// Called when the server has synchronized with the client
+ ///
+ /// @param connection An object used to identify the current connection
+ virtual void onServerSynchronized(mumble_connection_t connection) const;
+ /// 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
+ virtual void onUserAdded(mumble_connection_t connection, mumble_userid_t userID) const;
+ /// 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
+ virtual void onUserRemoved(mumble_connection_t connection, mumble_userid_t userID) const;
+ /// 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
+ virtual void onChannelAdded(mumble_connection_t connection, mumble_channelid_t channelID) const;
+ /// 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
+ virtual void onChannelRemoved(mumble_connection_t connection, mumble_channelid_t channelID) const;
+ /// 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
+ virtual void onChannelRenamed(mumble_connection_t connection, mumble_channelid_t channelID) const;
+ /// Called when a key has been pressed or released while Mumble has keyboard focus.
+ ///
+ /// @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 wasPress Whether the key has been pressed (instead of released)
+ virtual void onKeyEvent(mumble_keycode_t keyCode, bool wasPress) const;
+
+
+ public:
+ /// A template function for instantiating new plugin objects and initializing them. The plugin will be allocated on the heap and has
+ /// thus to be deleted via the delete instruction.
+ ///
+ /// @tparam T The type of the plugin to be instantiated
+ /// @tparam Ts The types of the contructor arguments
+ /// @param args A list of args passed to the contructor of the plugin object
+ /// @returns A pointer to the allocated plugin
+ ///
+ /// @throws PluginError if the plugin could not be loaded
+ template<typename T, typename ... Ts>
+ static T* createNew(Ts&&...args) {
+ static_assert(std::is_base_of<Plugin, T>::value, "The Plugin::create() can only be used to instantiate objects of base-type Plugin");
+ static_assert(!std::is_pointer<T>::value, "Plugin::create() can't be used to instantiate pointers. It will return a pointer automatically");
+
+ T *instancePtr = new T(std::forward<Ts>(args)...);
+
+ // call the initialize-method and throw an exception of it doesn't succeed
+ if (!instancePtr->doInitialize()) {
+ delete instancePtr;
+ // Delete the constructed object to prevent a memory leak
+ throw PluginError("Failed to initialize plugin");
+ }
+
+ return instancePtr;
+ }
+
+ /// Destructor
+ virtual ~Plugin() Q_DECL_OVERRIDE;
+ /// @returns Whether this plugin is in a valid state
+ virtual bool isValid() const;
+ /// @returns Whether this plugin is loaded (has been initialized via Plugin::init())
+ virtual bool isLoaded() const Q_DECL_FINAL;
+ /// @returns The unique ID of this plugin. This ID holds only as long as this plugin isn't "reconstructed".
+ virtual plugin_id_t getID() const Q_DECL_FINAL;
+ /// @returns Whether this plugin is built into Mumble (thus not backed by a shared library)
+ virtual bool isBuiltInPlugin() const Q_DECL_FINAL;
+ /// @returns The path to the shared library in the host's filesystem
+ virtual QString getFilePath() const;
+ /// @returns Whether positional data gathering is enabled (as in allowed via preferences)
+ virtual bool isPositionalDataEnabled() const Q_DECL_FINAL;
+ /// @returns Whether positional data gathering is currently active (as in running)
+ virtual bool isPositionalDataActive() const Q_DECL_FINAL;
+ /// @returns Whether this plugin is currently allowed to monitor keyboard events
+ virtual bool isKeyboardMonitoringAllowed() const Q_DECL_FINAL;
+
+
+ /// @returns Whether this plugin provides an about-dialog
+ virtual bool providesAboutDialog() const;
+ /// @returns Whether this plugin provides an config-dialog
+ virtual bool providesConfigDialog() const;
+ /// @returns The name of this plugin
+ virtual QString getName() const;
+ /// @returns The API version this plugin intends to use
+ virtual mumble_version_t getAPIVersion() const;
+ /// @returns The version of this plugin
+ virtual mumble_version_t getVersion() const;
+ /// @returns The author of this plugin
+ virtual QString getAuthor() const;
+ /// @returns The plugin's description
+ virtual QString getDescription() const;
+ /// @returns The plugin's features or'ed together (See the PluginFeature enum in MumblePlugin.h for what features are available)
+ virtual uint32_t getFeatures() const;
+ /// @return Whether the plugin has found a new/updated version of itself available for download
+ virtual bool hasUpdate() const;
+ /// @return The URL to download the updated plugin. May be empty
+ virtual QUrl getUpdateDownloadURL() const;
+};
+
+#endif