Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT(plugin-api): Add function to mumble api to obtain current positional audio data provided by another plugin #6556

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
53 changes: 52 additions & 1 deletion plugins/MumblePlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
# define MUMBLE_PLUGIN_API_MAJOR_MACRO 1
# endif
# ifndef MUMBLE_PLUGIN_API_MINOR_MACRO
# define MUMBLE_PLUGIN_API_MINOR_MACRO 2
# define MUMBLE_PLUGIN_API_MINOR_MACRO 3
# endif
# ifndef MUMBLE_PLUGIN_API_PATCH_MACRO
# define MUMBLE_PLUGIN_API_PATCH_MACRO 0
Expand Down Expand Up @@ -444,6 +444,42 @@ struct MumbleStringWrapper {
bool needsReleasing;
};

struct PositionalDataNoQt;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a different name


static void freePositionalDataStruct(PositionalDataNoQt *positionalData);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this.


struct PositionalDataNoQt {
#ifdef __cplusplus
// Prevents compilation but generic functions
// such as the one below doesn't hinder compilation
// ~PositionalDataNoQt() {
// freePositionalDataStruct(this);
// }
//
void freeStruct() {
freePositionalDataStruct(this);
}
#endif

float m_playerPos[3];
float m_playerDir[3];
float m_playerAxis[3];
float m_cameraPos[3];
float m_cameraDir[3];
float m_cameraAxis[3];
char *m_context;
char *m_identity;
};

void freePositionalDataStruct(PositionalDataNoQt *positionalData) {
if (positionalData) {
free(positionalData->m_context);
free(positionalData->m_identity);
}

free(positionalData);
}

MUMBLE_EXTERN_C_END

#endif // EXTERNAL_MUMBLE_PLUGIN_TYPES_
Expand Down Expand Up @@ -1515,6 +1551,21 @@ struct MUMBLE_API_STRUCT_NAME {
mumble_channelid_t channelID,
const char **description);

#if SELECTED_API_VERSION >= MUMBLE_PLUGIN_VERSION_CHECK(1, 3, 0)
/**
* Gets the positional audio data provided by OTHER plugins
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Gets the positional audio data provided by OTHER plugins
* Gets the currently used positional data

which plugin has supplied the data is left unspecified. It's not like this function won't work if the positional data has been supplied by the same plugin that now asks for it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah true, your wording is better and conveys what I wanted to get across, made other in caps to convey it is not like the similarly named (imo it is similar names) fetchPositionalData (in my brain, get and fetch are similar, now get and put are more distinct imo but I see no reason to change the existing name of api functions when we can just be clear in the doc comments)

*
* @param callerID The ID of the plugin calling this function
* @param[out] outPositionalData A pointer to the memory location the PositionalData object should be written to
* @returns The error code. If everything went well, STATUS_OK will be returned.
*
* @since Plugin interface v1.3.0
*/
mumble_error_t(MUMBLE_PLUGIN_CALLING_CONVENTION *getPositionalAudioData)(mumble_plugin_id_t callerID,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would turn this into multiple functions: One for retrieving the positional data, one for retrieving the identity and one for retrieving the context. Only the latter two involve dynamic memory allocations due to the involvement of strings (for which you should use the existing string wrapper classes).

PositionalDataNoQt **outPositionalData);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
PositionalDataNoQt **outPositionalData);
PositionalDataNoQt *outPositionalData);

No need to allocate the passed struct on the heap (using e.g. new). The only thing required is that the plugin allocates some space for this struct (by creating an instance on the Stack) and then the Mumble side can simply populate the fields of that struct with the correct data.

#endif



// -------- Request functions --------

Expand Down
5 changes: 5 additions & 0 deletions src/mumble/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ public slots:
void getChannelDescription_v_1_0_x(mumble_plugin_id_t callerID, mumble_connection_t connection,
mumble_channelid_t channelID, const char **description,
std::shared_ptr< api_promise_t > promise);
void getPositionalAudioData_v_1_3_x(mumble_plugin_id_t callerID, PositionalDataNoQt **outPositionalData,
std::shared_ptr< 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,
std::shared_ptr< api_promise_t > promise);
Expand Down Expand Up @@ -174,6 +176,9 @@ MumbleAPI_v_1_0_x getMumbleAPI_v_1_0_x();
/// @returns The Mumble API struct (v1.2.x)
MumbleAPI_v_1_2_x getMumbleAPI_v_1_2_x();

/// @returns The Mumble API struct (v1.3.x)
MumbleAPI_v_1_3_x getMumbleAPI_v_1_3_x();

/// Converts from the Qt key-encoding to the API's key encoding.
///
/// @param keyCode The Qt key-code that shall be converted
Expand Down
102 changes: 102 additions & 0 deletions src/mumble/API_v_1_x_x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,59 @@ void MumbleAPI::getChannelDescription_v_1_0_x(mumble_plugin_id_t callerID, mumbl
EXIT_WITH(MUMBLE_STATUS_OK);
}

void MumbleAPI::getPositionalAudioData_v_1_3_x(mumble_plugin_id_t callerID,
PositionalDataNoQt **outPositionalData,
std::shared_ptr< api_promise_t > promise) {
if (QThread::currentThread() != thread()) {
// Invoke in main thread
QMetaObject::invokeMethod(this, "getPositionalAudioData_v_1_3_x", Qt::QueuedConnection,
Q_ARG(mumble_plugin_id_t, callerID), Q_ARG(PositionalDataNoQt **, outPositionalData),
Q_ARG(std::shared_ptr< api_promise_t >, promise));
return;
}

api_promise_t::lock_guard_t guard = promise->lock();
if (promise->isCancelled()) {
return;
}

VERIFY_PLUGIN_ID(callerID);

PluginManager *pluginManager = Global::get().pluginManager;
if (!pluginManager) {
EXIT_WITH(MUMBLE_EC_INTERNAL_ERROR);
}

const PositionalData &posData = pluginManager->getPositionalData();

PositionalDataNoQt positionalDataNoQt = PositionalDataNoQt();

for (int i = 0; i < 3; i++) {
Coord coord = static_cast< Coord >(i);

positionalDataNoQt.m_playerPos[i] = posData.getPlayerPos()[coord];
positionalDataNoQt.m_playerDir[i] = posData.getPlayerDir()[coord];
positionalDataNoQt.m_playerAxis[i] = posData.getPlayerAxis()[coord];

positionalDataNoQt.m_cameraPos[i] = posData.getCameraPos()[coord];
positionalDataNoQt.m_cameraDir[i] = posData.getCameraDir()[coord];
positionalDataNoQt.m_cameraAxis[i] = posData.getCameraAxis()[coord];
}

char *context = posData.getContext().toUtf8().data();
size_t size = strlen(context) + 1;
positionalDataNoQt.m_context = static_cast< char * >(malloc(size));
std::memcpy(positionalDataNoQt.m_context, context, size);

char *identity = posData.getPlayerIdentity().toUtf8().data();
size = strlen(identity) + 1;
positionalDataNoQt.m_identity = static_cast< char * >(malloc(size));
std::memcpy(positionalDataNoQt.m_identity, identity, size);

std::memcpy(*outPositionalData, &positionalDataNoQt, sizeof(PositionalDataNoQt));
EXIT_WITH(MUMBLE_STATUS_OK);
}

void MumbleAPI::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,
std::shared_ptr< api_promise_t > promise) {
Expand Down Expand Up @@ -1800,6 +1853,13 @@ C_WRAPPER(getChannelDescription_v_1_0_x)
#undef TYPED_ARGS
#undef ARG_NAMES

#define TYPED_ARGS \
mumble_plugin_id_t callerID, PositionalDataNoQt **outPositionalData
#define ARG_NAMES callerID, outPositionalData
C_WRAPPER(getPositionalAudioData_v_1_3_x)
#undef TYPED_ARGS
#undef ARG_NAMES

#define TYPED_ARGS \
mumble_plugin_id_t callerID, mumble_connection_t connection, mumble_userid_t userID, mumble_channelid_t channelID, \
const char *password
Expand Down Expand Up @@ -2016,6 +2076,48 @@ MumbleAPI_v_1_2_x getMumbleAPI_v_1_2_x() {
playSample_v_1_2_x };
}

MumbleAPI_v_1_3_x getMumbleAPI_v_1_3_x() {
return { freeMemory_v_1_0_x,
getActiveServerConnection_v_1_0_x,
isConnectionSynchronized_v_1_0_x,
getLocalUserID_v_1_0_x,
getUserName_v_1_0_x,
getChannelName_v_1_0_x,
getAllUsers_v_1_0_x,
getAllChannels_v_1_0_x,
getChannelOfUser_v_1_0_x,
getUsersInChannel_v_1_0_x,
getLocalUserTransmissionMode_v_1_0_x,
isUserLocallyMuted_v_1_0_x,
isLocalUserMuted_v_1_0_x,
isLocalUserDeafened_v_1_0_x,
getUserHash_v_1_0_x,
getServerHash_v_1_0_x,
getUserComment_v_1_0_x,
getChannelDescription_v_1_0_x,
getPositionalAudioData_v_1_3_x,
requestLocalUserTransmissionMode_v_1_0_x,
requestUserMove_v_1_0_x,
requestMicrophoneActivationOverwrite_v_1_0_x,
requestLocalMute_v_1_0_x,
requestLocalUserMute_v_1_0_x,
requestLocalUserDeaf_v_1_0_x,
requestSetLocalUserComment_v_1_0_x,
findUserByName_v_1_0_x,
findChannelByName_v_1_0_x,
getMumbleSetting_bool_v_1_0_x,
getMumbleSetting_int_v_1_0_x,
getMumbleSetting_double_v_1_0_x,
getMumbleSetting_string_v_1_0_x,
setMumbleSetting_bool_v_1_0_x,
setMumbleSetting_int_v_1_0_x,
setMumbleSetting_double_v_1_0_x,
setMumbleSetting_string_v_1_0_x,
sendData_v_1_0_x,
log_v_1_0_x,
playSample_v_1_2_x };
}

#define MAP(qtName, apiName) \
case Qt::Key_##qtName: \
return MUMBLE_KC_##apiName
Expand Down
10 changes: 10 additions & 0 deletions src/mumble/MumbleAPI_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@
// First, include the latest plugin API header file completely
#include "MumblePlugin.h"

// Now, include all older API structs for backward compatibility
// Re-include the API definition
#undef EXTERNAL_MUMBLE_PLUGIN_MUMBLE_API_
// But this time, overwrite the version
#undef MUMBLE_PLUGIN_API_MAJOR_MACRO
#define MUMBLE_PLUGIN_API_MAJOR_MACRO 1
#undef MUMBLE_PLUGIN_API_MINOR_MACRO
#define MUMBLE_PLUGIN_API_MINOR_MACRO 2

#include "MumblePlugin.h"

// Re-include the API definition
#undef EXTERNAL_MUMBLE_PLUGIN_MUMBLE_API_
Expand Down
3 changes: 3 additions & 0 deletions src/mumble/Plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,9 @@ mumble_error_t Plugin::init() {
} else if (apiVersion >= mumble_version_t({ 1, 2, 0 }) && apiVersion < mumble_version_t({ 1, 3, 0 })) {
MumbleAPI_v_1_2_x api = API::getMumbleAPI_v_1_2_x();
registerAPIFunctions(&api);
} else if (apiVersion >= mumble_version_t({ 1, 3, 0 })) {
MumbleAPI_v_1_3_x api = API::getMumbleAPI_v_1_3_x();
registerAPIFunctions(&api);
} else {
// The API version could not be obtained -> this is an invalid plugin that shouldn't have been loaded in the
// first place
Expand Down
Loading