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/PluginManager.h')
-rw-r--r--src/mumble/PluginManager.h279
1 files changed, 279 insertions, 0 deletions
diff --git a/src/mumble/PluginManager.h b/src/mumble/PluginManager.h
new file mode 100644
index 000000000..02f4db5fa
--- /dev/null
+++ b/src/mumble/PluginManager.h
@@ -0,0 +1,279 @@
+// 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_PLUGINMANAGER_H_
+#define MUMBLE_MUMBLE_PLUGINMANAGER_H_
+
+#include <QObject>
+#include <QReadWriteLock>
+#include <QString>
+#include <QTimer>
+#include <QHash>
+#include <QMutex>
+#ifdef Q_OS_WIN
+ #ifndef NOMINMAX
+ #define NOMINMAX
+ #endif
+ #include <windows.h>
+#endif
+#include "Plugin.h"
+#include "MumbleApplication.h"
+#include "PositionalData.h"
+
+#include "User.h"
+#include "ClientUser.h"
+#include "Channel.h"
+#include "Settings.h"
+#include "PluginUpdater.h"
+
+#include <functional>
+
+/// A struct for holding the values of the current context and identity that have been sent to the server
+struct PluginManager_SentData {
+ QString context;
+ QString identity;
+};
+
+
+/// The plugin manager is the central object dealing with everything plugin-related. It is responsible for
+/// finding, loading and managing the plugins. It also is responsible for invoking callback functions in the plugins
+/// and can be used by Mumble to communicate with them
+class PluginManager : public QObject {
+ private:
+ Q_OBJECT
+ Q_DISABLE_COPY(PluginManager)
+ protected:
+ /// Lock for pluginHashMap. This lock has to be aquired when accessing pluginHashMap
+ mutable QReadWriteLock m_pluginCollectionLock;
+ /// A map between plugin-IDs and the actual plugin objects. You have to aquire pluginCollectionLock before
+ /// accessing this map.
+ QHash<plugin_id_t, plugin_ptr_t> m_pluginHashMap;
+ /// A set of directories to search plugins in
+ QSet<QString> m_pluginSearchPaths;
+#ifdef Q_OS_WIN
+ // This stuff is apparently needed on Windows in order to deal with DLLs
+ HANDLE m_hToken;
+ TOKEN_PRIVILEGES m_tpPrevious;
+ DWORD m_cbPrevious;
+#endif
+ /// The PositionalData object holding the current positional data (as retrieved by the respective plugin)
+ PositionalData m_positionalData;
+
+ /// A timer that causes the manager to regularly check for available plugins that can currently
+ /// deliver positional data.
+ QTimer m_positionalDataCheckTimer;
+
+ /// The mutex for sentData. This has to be aquired before accessing sentData
+ mutable QMutex m_sentDataMutex;
+ /// The bits of the positional data that have already been sent to the server. It is used to determine whether
+ /// the new data has to be sent to the server (in case it has changed). You have ti aquire sentDataMutex before
+ /// accessing this field.
+ PluginManager_SentData m_sentData;
+
+ /// The lock for activePositionalDataPlugin. It has to be aquired before accessing the respective field.
+ mutable QReadWriteLock m_activePosDataPluginLock;
+ /// The plugin that is currently used to retrieve positional data. You have to aquire activePosDataPluginLock before
+ /// accessing this field.
+ plugin_ptr_t m_activePositionalDataPlugin;
+ /// The PluginUpdater used to handle plugin updates.
+ PluginUpdater m_updater;
+
+ // We override the QObject::eventFilter function in order to be able to install the pluginManager as an event filter
+ // to the main application in order to get notified about keystrokes.
+ bool eventFilter(QObject *target, QEvent *event) Q_DECL_OVERRIDE;
+
+ /// Unloads all plugins that are currently loaded.
+ void unloadPlugins() const;
+ /// Clears the current list of plugins
+ void clearPlugins();
+ /// Iterates over the plugins and tries to select a plugin that currently claims to be able to deliver positional data. If
+ /// it found a plugin, activePositionalDataPlugin is set accordingly. If not, it is set to nullptr.
+ ///
+ /// @returns Whether this function succeeded in finding such a plugin
+ bool selectActivePositionalDataPlugin();
+
+ /// A internal helper function that iterates over all plugins and calls the given function providing the current plugin as
+ /// a parameter.
+ void foreachPlugin(std::function<void(Plugin&)>) const;
+ public:
+ // How often positional data (identity & context) should be synched with the server if there is any (in ms)
+ static constexpr int POSITIONAL_SERVER_SYNC_INTERVAL = 500;
+ // How often the manager should check for available positional data plugins
+ static constexpr int POSITIONAL_DATA_CHECK_INTERVAL = 1000;
+
+ /// Constructor
+ ///
+ /// @param additionalSearchPaths A pointer to a set of additional search paths or nullptr if no additional
+ /// paths are required.
+ /// @param p The parent QObject
+ PluginManager(QSet<QString> *additionalSearchPaths = nullptr, QObject *p = nullptr);
+ /// Destructor
+ virtual ~PluginManager() Q_DECL_OVERRIDE;
+
+ /// @param pluginID The ID of the plugin that should be retreved
+ /// @returns A pointer to the plugin with the given ID or nullptr if no such plugin could be found
+ const_plugin_ptr_t getPlugin(plugin_id_t pluginID) const;
+ /// Checks whether there are any updates for the plugins and if there are it invokes the PluginUpdater.
+ void checkForPluginUpdates();
+ /// Fetches positional data from the activePositionalDataPlugin if there is one set. This function will update the
+ /// positionalData field
+ ///
+ /// @returns Whether the positional data could be retrieved successfully
+ bool fetchPositionalData();
+ /// Unlinks the currently active positional data plugin. Effectively this sets activePositionalDataPlugin to nullptr
+ void unlinkPositionalData();
+ /// @returns Whether positional data is currently available (it has been successfully set via fetchPositionalData)
+ bool isPositionalDataAvailable() const;
+ /// @returns The most recent positional data
+ const PositionalData& getPositionalData() const;
+ /// Enables positional data gathering for the plugin with the given ID. A plugin is only even asked whether it can deliver
+ /// positional data if this is enabled.
+ ///
+ /// @param pluginID The ID of the plugin to access
+ /// @param enable Whether to enable positional data (alternative is to disable it)
+ void enablePositionalDataFor(plugin_id_t pluginID, bool enable = true) const;
+ /// @returns A const vector of the plugins
+ const QVector<const_plugin_ptr_t> getPlugins(bool sorted = false) const;
+ /// Loads the plugin with the given ID. Loading means initializing the plugin.
+ ///
+ /// @param pluginID The ID of the plugin to load
+ /// @returns Whether the plugin could be successfully loaded
+ bool loadPlugin(plugin_id_t pluginID) const;
+ /// Unloads the plugin with the given ID. Unloading means shutting the plugign down.
+ ///
+ /// @param pluginID The ID of the plugin to unload
+ void unloadPlugin(plugin_id_t pluginID) const;
+ /// Unloads the given plugin. Unloading means shutting the plugign down.
+ ///
+ /// @param plugin The plugin to unload
+ void unloadPlugin(Plugin &plugin) const;
+ /// Clears the plugin from the list of known plugins
+ ///
+ /// @param pluginID The ID of the plugin to forget about
+ /// @returns Whether the plugin has been cleared successfully
+ bool clearPlugin(plugin_id_t pluginID);
+ /// Deactivates the given features for the plugin with the given ID
+ ///
+ /// @param pluginID The ID of the plugin to access
+ /// @param features The feature set that should be deactivated. The features are or'ed together.
+ /// @returns The feature set that could not be deactivated
+ uint32_t deactivateFeaturesFor(plugin_id_t pluginID, uint32_t features) const;
+ /// Allows or forbids the given plugin to monitor keyboard events.
+ ///
+ /// @param pluginID The ID of the plugin to access
+ /// @param allow Whether to allow the monitoring or not
+ void allowKeyboardMonitoringFor(plugin_id_t pluginID, bool allow) const;
+ /// Checks whether a plugin with the given ID exists.
+ ///
+ /// @param pluginID The ID to check
+ /// @returns Whether such a plugin exists
+ bool pluginExists(plugin_id_t pluginID) const;
+
+ public slots:
+ /// Rescans the plugin directory and load all plugins from there after having cleared the current plugin list
+ void rescanPlugins();
+ /// Slot that gets called whenever data from another plugin has been received. This function will then delegate
+ /// this to the respective plugin callback
+ ///
+ /// @param sender A pointer to the ClientUser whose client has sent the data
+ /// @param data The byte-array representing the sent data
+ /// @param dataLength The length of the data array
+ /// @param dataID The ID of the data
+ void on_receiveData(const ClientUser *sender, const uint8_t *data, size_t dataLength, const char *dataID) const;
+ /// Slot that gets called when the local client connects to a server. It will delegate it to the respective plugin callback.
+ void on_serverConnected() const;
+ /// Slot that gets called when the local client disconnects to a server. It will delegate it to the respective plugin callback.
+ void on_serverDisconnected() const;
+ /// Slot that gets called when a client enters a channel. It will delegate it to the respective plugin callback.
+ ///
+ /// @param newChannel A pointer to the new channel
+ /// @param prevChannel A pointer to the previous channel or nullptr if no such channel exists
+ /// @param user A pointer to the user that entered the channel
+ void on_channelEntered(const Channel *newChannel, const Channel *prevChannel, const User *user) const;
+ /// Slot that gets called when a client leaves a channel. It will delegate it to the respective plugin callback.
+ ///
+ /// @param channel A pointer to the channel that has been left
+ /// @param user A pointer to the user that entered the channel
+ void on_channelExited(const Channel *channel, const User *user) const;
+ /// Slot that gets called when the local client changes its talking state. It will delegate it to the respective plugin callback.
+ void on_userTalkingStateChanged() const;
+ /// Slot that gets called when the local client receives audio input. It will delegate it to the respective plugin callback.
+ ///
+ /// @param inputPCM The array containing the input PCM (pulse-code-modulation). Its length is sampleCount * channelCount
+ /// @param sampleCount The amount of samples in the PCM array
+ /// @param channelCount The amount of channels in the PCM array
+ /// @param sampleRate The used sample rate in Hz
+ /// @param isSpeech Whether Mumble considers this input as speech
+ void on_audioInput(short *inputPCM, unsigned int sampleCount, unsigned int channelCount, unsigned int sampleRate, bool isSpeech) const;
+ /// Slot that gets called when the local client has fetched an audio source. It will delegate it to the respective plugin callback.
+ ///
+ /// @param outputPCM The array containing the output-PCM (pulse-code-modulation). Its length is sampleCount * channelCount
+ /// @param sampleCount The amount of samples in the PCM array
+ /// @param channelCount The amount of channels in the PCM array
+ /// @param sampleRate The used sample rate in Hz
+ /// @param isSpeech Whether Mumble considers this input as speech
+ /// @param user A pointer to the ClientUser the audio source corresposnds to
+ void on_audioSourceFetched(float *outputPCM, unsigned int sampleCount, unsigned int channelCount, unsigned int sampleRate, bool isSpeech,
+ const ClientUser *user) const;
+ /// Slot that gets called when the local client is about to play some audio. It will delegate it to the respective plugin callback.
+ ///
+ /// @param outputPCM The array containing the output-PCM (pulse-code-modulation). Its length is sampleCount * channelCount
+ /// @param sampleCount The amount of samples in the PCM array
+ /// @param channelCount The amount of channels in the PCM array
+ /// @param sampleRate The used sample rate in Hz
+ void on_audioOutputAboutToPlay(float *outputPCM, unsigned int sampleCount, unsigned int channelCount, unsigned int sampleRate,
+ bool *modifiedAudio) const;
+ /// Slot that gets called after the local client has finished synchronizing with the server. It will delegate it to the respective
+ /// plugin callback.
+ void on_serverSynchronized() const;
+ /// Slot that gets called when a new user is added to the user model. It will delegate it to the respective plugin callbacks.
+ ///
+ /// @param userID The ID of the added user
+ void on_userAdded(unsigned int userID) const;
+ /// Slot that gets called when a user is removed from the user model. It will delegate it to the respective plugin callbacks.
+ ///
+ /// @param userID The ID of the removed user
+ void on_userRemoved(unsigned int userID) const;
+ /// Slot that gets called when a new channel is added to the user model. It will delegate it to the respective plugin callbacks.
+ ///
+ /// @param channelID The ID of the added channel
+ void on_channelAdded(int channelID) const;
+ /// Slot that gets called when a channel is removed from the user model. It will delegate it to the respective plugin callbacks.
+ ///
+ /// @param channelID The ID of the removed channel
+ void on_channelRemoved(int channelID) const;
+ /// Slot that gets called when a channel is renamed. It will delegate it to the respective plugin callbacks.
+ ///
+ /// @param channelID The ID of the renamed channel
+ void on_channelRenamed(int channelID) const;
+ /// Slot that gets called when a key has been pressed or released while Mumble has keyboard focus.
+ ///
+ /// @param key The code of the affected key (as encoded by Qt::Key)
+ /// @param modifiers The modifiers that were active in the moment of the event
+ /// @param isPress True if the key has been pressed, false if it has been released
+ void on_keyEvent(unsigned int key, Qt::KeyboardModifiers modifiers, bool isPress) const;
+
+ /// Slot that gets called whenever the positional data should be synchronized with the server. Before it does that, it tries to
+ /// fetch new data.
+ void on_syncPositionalData();
+ /// Slot called if there are plugin updates available
+ void on_updatesAvailable();
+
+ protected slots:
+ /// If there is no active positional data plugin, this function will initiate searching for a
+ /// new one.
+ void checkForAvailablePositionalDataPlugin();
+
+ signals:
+ /// A signal emitted if the PluginManager (acting as an event filter) detected
+ /// a QKeyEvent.
+ ///
+ /// @param key The code of the affected key (as encoded by Qt::Key)
+ /// @param modifiers The modifiers that were active in the moment of the event
+ /// @param isPress True if the key has been pressed, false if it has been released
+ void keyEvent(unsigned int key, Qt::KeyboardModifiers modifiers, bool isPress);
+};
+
+#endif