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

API.h « mumble « src - github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 74d8196ae7b9b2c812b2116a7ffae3c17923ed3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// 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_API_H_
#define MUMBLE_MUMBLE_API_H_

// In here the MumbleAPI struct is defined
#include "MumbleAPI_v_1_0_x.h"

#include <atomic>
#include <functional>
#include <future>
#include <unordered_map>

#include <QObject>

namespace API {

using api_future_t  = std::future< mumble_error_t >;
using api_promise_t = std::promise< mumble_error_t >;

/// A "curator" that will keep track of allocated resources and how to delete them
struct MumbleAPICurator {
	struct Entry {
		/// The function used to delete the corresponding pointer
		std::function< void(const void *) > m_deleter;
		/// The ID of the plugin the resource pointed at was allocated for
		mumble_plugin_id_t m_pluginID;
		/// The name of the API function the resource pointed to was allocated in
		/// NOTE: This must only ever be a pointer to a String literal.
		const char *m_sourceFunctionName;
	};

	std::unordered_map< const void *, Entry > m_entries;

	~MumbleAPICurator();
};

/// This object contains the actual API implementation. It also takes care of synchronizing API calls
/// with Mumble's main thread so that plugins can call them from an arbitrary thread without causing
/// issues.
/// This class is a singleton as a way to be able to write C function wrappers for the member functions
/// that are needed for passing to the plugins.
class MumbleAPI : public QObject {
	Q_OBJECT;
	Q_DISABLE_COPY(MumbleAPI);

public:
	static MumbleAPI &get();

public slots:
	// The description of the functions is provided in MumbleAPI.h

	// Note that every slot is synchronized and is therefore guaranteed to be executed in the main
	// thread. For the synchronization strategy see below.
	void freeMemory_v_1_0_x(mumble_plugin_id_t callerID, const void *ptr, api_promise_t *promise);
	void getActiveServerConnection_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t *connection,
										   api_promise_t *promise);
	void isConnectionSynchronized_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection,
										  bool *synchronized, api_promise_t *promise);
	void getLocalUserID_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t *userID,
								api_promise_t *promise);
	void getUserName_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID,
							 const char **name, api_promise_t *promise);
	void getChannelName_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection,
								mumble_channelid_t channelID, const char **name, api_promise_t *promise);
	void getAllUsers_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t **users,
							 size_t *userCount, api_promise_t *promise);
	void getAllChannels_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection,
								mumble_channelid_t **channels, size_t *channelCount, api_promise_t *promise);
	void getChannelOfUser_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID,
								  mumble_channelid_t *channelID, api_promise_t *promise);
	void getUsersInChannel_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection,
								   mumble_channelid_t channelID, mumble_userid_t **users, size_t *userCount,
								   api_promise_t *promise);
	void getLocalUserTransmissionMode_v_1_0_x(mumble_plugin_id_t callerID, mumble_transmission_mode_t *transmissionMode,
											  api_promise_t *promise);
	void isUserLocallyMuted_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID,
									bool *muted, api_promise_t *promise);
	void isLocalUserMuted_v_1_0_x(mumble_plugin_id_t callerID, bool *muted, api_promise_t *promise);
	void isLocalUserDeafened_v_1_0_x(mumble_plugin_id_t callerID, bool *deafened, api_promise_t *promise);
	void getUserHash_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID,
							 const char **hash, api_promise_t *promise);
	void getServerHash_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, const char **hash,
							   api_promise_t *promise);
	void requestLocalUserTransmissionMode_v_1_0_x(mumble_plugin_id_t callerID,
												  mumble_transmission_mode_t transmissionMode, api_promise_t *promise);
	void getUserComment_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID,
								const char **comment, api_promise_t *promise);
	void getChannelDescription_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection,
									   mumble_channelid_t channelID, const char **description, api_promise_t *promise);
	void requestUserMove_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID,
								 mumble_channelid_t channelID, const char *password, api_promise_t *promise);
	void requestMicrophoneActivationOverwrite_v_1_0_x(mumble_plugin_id_t callerID, bool activate,
													  api_promise_t *promise);
	void requestLocalMute_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID,
								  bool muted, api_promise_t *promise);
	void requestLocalUserMute_v_1_0_x(mumble_plugin_id_t callerID, bool muted, api_promise_t *promise);
	void requestLocalUserDeaf_v_1_0_x(mumble_plugin_id_t callerID, bool deafened, api_promise_t *promise);
	void requestSetLocalUserComment_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection,
											const char *comment, api_promise_t *promise);
	void findUserByName_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, const char *userName,
								mumble_userid_t *userID, api_promise_t *promise);
	void findChannelByName_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection, const char *channelName,
								   mumble_channelid_t *channelID, api_promise_t *promise);
	void getMumbleSetting_bool_v_1_0_x(mumble_plugin_id_t callerID, mumble_settings_key_t key, bool *outValue,
									   api_promise_t *promise);
	void getMumbleSetting_int_v_1_0_x(mumble_plugin_id_t callerID, mumble_settings_key_t key, int64_t *outValue,
									  api_promise_t *promise);
	void getMumbleSetting_double_v_1_0_x(mumble_plugin_id_t callerID, mumble_settings_key_t key, double *outValue,
										 api_promise_t *promise);
	void getMumbleSetting_string_v_1_0_x(mumble_plugin_id_t callerID, mumble_settings_key_t key, const char **outValue,
										 api_promise_t *promise);
	void setMumbleSetting_bool_v_1_0_x(mumble_plugin_id_t callerID, mumble_settings_key_t key, bool value,
									   api_promise_t *promise);
	void setMumbleSetting_int_v_1_0_x(mumble_plugin_id_t callerID, mumble_settings_key_t key, int64_t value,
									  api_promise_t *promise);
	void setMumbleSetting_double_v_1_0_x(mumble_plugin_id_t callerID, mumble_settings_key_t key, double value,
										 api_promise_t *promise);
	void setMumbleSetting_string_v_1_0_x(mumble_plugin_id_t callerID, mumble_settings_key_t key, const char *value,
										 api_promise_t *promise);
	void sendData_v_1_0_x(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,
						  api_promise_t *promise);
	void log_v_1_0_x(mumble_plugin_id_t callerID, const char *message, api_promise_t *promise);
	void playSample_v_1_0_x(mumble_plugin_id_t callerID, const char *samplePath, api_promise_t *promise);


private:
	MumbleAPI();

	MumbleAPICurator m_curator;
};

/// @returns The Mumble API struct (v1.0.x)
MumbleAPI_v_1_0_x getMumbleAPI_v_1_0_x();

/// Converts from the Qt key-encoding to the API's key encoding.
///
/// @param keyCode The Qt key-code that shall be converted
/// @returns The converted key code or KC_INVALID if conversion failed
mumble_keycode_t qtKeyCodeToAPIKeyCode(unsigned int keyCode);

/// A class holding non-permanent data set by plugins. Non-permanent means that this data
/// will not be stored between restarts.
/// All member field should be atomic in order to be thread-safe
class PluginData {
public:
	/// Constructor
	PluginData();
	/// Destructor
	~PluginData();

	/// A flag indicating whether a plugin has requested the microphone to be permanently on (mirroring the
	/// behaviour of the continous transmission mode.
	std::atomic_bool overwriteMicrophoneActivation;

	/// @returns A reference to the PluginData singleton
	static PluginData &get();
}; // class PluginData
}; // namespace API


// Declare the meta-types that we require in order for the API to work
Q_DECLARE_METATYPE(mumble_settings_key_t);
Q_DECLARE_METATYPE(mumble_settings_key_t *);
Q_DECLARE_METATYPE(mumble_transmission_mode_t);
Q_DECLARE_METATYPE(mumble_transmission_mode_t *);
Q_DECLARE_METATYPE(API::api_promise_t *);

//////////////////////////////////////////////////////////////
///////////// SYNCHRONIZATION STRATEGY ///////////////////////
//////////////////////////////////////////////////////////////

/**
 * Every API function call checks whether it is being called from the main thread. If it is,
 * it continues executing as usual. If it is not however, it uses Qt's signal/slot mechanism
 * to schedule the respective function to be run in the main thread in the next iteration of
 * the event loop.
 * In order to synchronize with the calling thread, the return value (error code) of these
 * functions is "returned" as a promise. Thus by accessing the exit code via the corresponding
 * future, the calling thread is blocked until the function has been executed in the main thread
 * (and thereby set the exit code once it is done allowing the calling thread to unblock).
 */

#endif