{"owner":"mumble-voip","repo":"mumble","hasSkills":true,"totalSkillsCount":3,"totalTokensCount":2545,"categories":["anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["docs/dev/plugins/Bundling.md","docs/dev/plugins/LanguageBindings.md","docs/dev/plugins/MumbleAPI.md"],"skills":{"docs/dev/plugins/Bundling.md":"# Bundling a Mumble plugin\n\nAfter you have built your plugin you will have a shared library for the respective target OS. While it is possible to just give users this shared\nlibrary and tell them to install them, it might get inconvenient at times. Especially if you want to support your plugin for multiple OS.\n\nTherefore Mumble provides a way to package your plugin in a user-friendly and cross-platform way.\n\nMumble plugin bundles are essentially zip-files with a special contents structure and the file extension `.mumble_plugin` instead of `.zip`. Such a\nbundle must contain a `manifest.xml` as a top-level entry in the archive. The manifest file is used to specify which plugin library (also bundled\nwithin the archive) is to be used for which OS and architecture.\n\n## The manifest file format\n\nThe manifest file _always_ has to be named `manifest.xml` (case-sensitive!) and it must use the `bundle` tag as the top-level element of the XML\nstructure. Furthermore the `bundle` opening tag needs to specify the `format` attribute which will determine the rules the rest of the XML tree has to\nfollow.\n\nUnless otherwise noted the entire manifest file is case-sensitive (including paths specified in it)!\n\n### v1.0.0\n\n| Property | Value |\n| -------- | ----- |\n| `version` attribute | `1.0.0` |\n| Available since: | Mumble v1.4.0 |\n\nInside  the `bundle` element there have to be the `assets`, `name` and `version` elements. `name` is just the name of your plugin (arbitrary String)\nwhereas `version` is the version of your plugin. Note that the version must be given in the format `<major>.<minor>.<patch>`.\n\nInside the `assets` element comes a list of one or more `plugin` elements. Each of these must specify the `os` and `arch` attributes for specifying\nthe operating system and architecture respectively. The contents of these elements is the path to the corresponding plugin library inside the archive\n(relative to the `manifest.xml` file). Note that the paths _must not_ start with `./` and as path separator a single forward slash is to be used (even\non Windows).\n\nThe possible values for the `os` attribute are\n| **OS** | **Attribute** |\n| ------ | ------------- |\n| Windows | `windows` |\n| Linux | `linux` |\n| macOS | `macos` |\n\nand the possible values for the `arch` attribute are\n| **Architecture** | **Attribute** |\n| ---------------- | ------------- |\n| x86 (32-bit) | `x86` |\n| x86 (64-bit) | `x64`|\n\nPutting this together a sample `manifest.xml` can look like this:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<bundle version=\"1.0.0\">\n  <assets>\n    <plugin os=\"windows\" arch=\"x86\">myPlugin.dll</plugin>\n    <plugin os=\"windows\" arch=\"x64\">sub/myPlugin.dll</plugin>\n    <plugin os=\"linux\" arch=\"x64\">sub/libmyPlugin.so</plugin>\n  </assets>\n  <name>MyPlugin</name>\n  <version>1.0.0</version>\n</bundle>\n```\n\n## Creating a plugin bundle\n\nAs written before, a plugin bundle essentially is just a zip file. The only restriction here is that it must not be created using the proprietary\n`Deflate64` algorithm.\n\nThe steps to create a bundle file are as follows\n1. Create an empty working directory\n2. Copy the plugin libraries for the different OS and architectures into this directory (potentially in sub-directories)\n3. Create a `manifest.xml` at the root of the working directory\n4. Add all files and folders in your working directory (but not the working directory itself!) to a zip file\n5. Change the file extension from `.zip` to `.mumble_plugin`\n\nOn Linux you can do this by using the `zip` command line tool like this:\n```bash\nzip my_plugin.mumble_plugin myPlugin.dll sub/myPlugin.dll sub/libmyPlugin.so manifest.xml\n```\n\n## Notes\n\n- You **must not** add any additional files to this archive. Keep the contents of the created archive strictly to the parts mentioned above. It\n  might be tempting to treat the plugin bundle as a regular zip file that can be filled with arbitrary contents but this is not allowed! Instead\n  consider the plugin bundle a binary of its own that has to follow a strict format as outlined above.\n- Plugin names **must not** contain version numbers. At least not when they are distributed to end users. This is because Mumble assumes that\n  the new version of a plugin will use a shared library with the exact same name as the old one. If this assumption is violated, the update mechanism\n  will not work properly causing the new and the old version of the plugin to be installed in parallel.\n\n","docs/dev/plugins/LanguageBindings.md":"# Mumble plugin - Language bindings\n\n## C\n\n`C` is the native language of the plugin API. If you intend to use it, you don't need any special bindings.\n\n\n## C++\n\nThere exists an official `C++` wrapper around the C API. It can be found at https://github.com/mumble-voip/mumble-plugin-cpp.\n\n## Rust\n\n`Rust` bindings are maintained independently from the main Mumble project. They can be found at https://crates.io/crates/mumble-sys.\n\n","docs/dev/plugins/MumbleAPI.md":"# The Mumble-API\n\nThe Mumble-API is a set of function pointers that is given to the plugin during the [initialization process](PluginLifecycle.md#initialization) via\nthe `mumble_registerAPIFunctions` function in the [plugin-API](PluginAPI.md).\n\n\n## How it works\n\nAs a plugin developer you don't have to worry about the implementation of these functions. They are implemented on Mumble's side. All you have to care\nabout is that certain functions exist and that you are free to call any of them.\n\nIn order to do so, you need to know the function signature which is defined in the Mumble-API header file. Functions in there are defined as e.g.\n```cpp\nmumble_error_t(PLUGIN_CALLING_CONVENTION *isConnectionSynchronized)(mumble_plugin_id_t callerID, mumble_connection_t connection, bool *synchronized);\n```\nThe definition may seem a bit odd and intimidating at first glance but that is only because these functions need to be specified as [function\npointers](https://www.geeksforgeeks.org/function-pointer-in-c/). Here are a set of easy steps to (mentally) convert this notation into a (probably)\nmore familiar format:\n1. Ignore `PLUGIN_CALLING_CONVENTION`. The [calling convention](https://en.wikipedia.org/wiki/Calling_convention) is nothing you have to worry about.\n   This is handled for you by your compiler\n2. Remove the first set of parenthesis and the star within them. What remains is the function name\n\nApplying these steps to the above function yields the following definition:\n```cpp\nmumble_error_t isConnectionSynchronized(mumble_plugin_id_t callerID, mumble_connection_t connection, bool *synchronized);\n```\n\nThus we can see that this is a function called `isConnectionSynchronized` that takes 3 parameters and returns a `mumble_error_t`. Therefore if we\nassume that you have stored the Mumble-API in a variable named `mumbleAPI` in your plugin, you could call this function as\n```cpp\nmumble_error_t returnedError = mumbleAPI.isConnectionSynchronized(...);\n```\n\n## General function structure\n\nEach function follows the general signature\n```cpp\nmumble_error_t myFunction(mumble_plugin_id_t callerID /* potentially more arguments */);\n```\n\nThat means that each function _always_ returns an error code that indicates whether the API call was successful. How to handle this returned error\ncode is described in the [error handling section](#error-handling).\n\nFurthermore the first parameter is _always_ the ID of the plugin that makes the API call. Your plugin's ID is given to you during the [initialization\nprocess](PluginLifecycle.md#initialization) via the `mumble_init` function. You have to store this ID and use it every time you make a call to the\nMumble-API as otherwise your calls will be ignored by Mumble.\n\nGiven that the return value of Mumble-API functions are always occupied with the error code, all functions that query some sort of information use an\n_out parameter_. That means that you pre-allocate a variable of the respective type and then pass a pointer to that variable to the API function. On\nsuccessful execution this function will then set the value of your variable through the given pointer.\n\nA good example is obtaining the currently active server connection:\n```cpp\nmumble_connection_t activeConnection;\nif (mumbleAPI.getActiveServerConnection(pluginID, &activeConnection) == MUMBLE_STATUS_OK) {\n    // Do something with activeConnection\n}\n```\n\n\n## Error handling\n\nThe error code returned by Mumble-API functions can (and often must) be used to determine whether the given function call was successful. If the error\ncode compares equal to `MUMBLE_STATUS_OK` (a macro defined in the `PluginComponents` header that is automatically included in the Mumble-API header),\nthen the API call was successful. **Every other value indicates failure**.\n\nIn case of an error, the error code will give information on the exact problem that was found. The possible error codes are defined in the\n`Mumble_ErrorCode` enum (also defined in `PluginComponents`). These values can be used to check the error code against certain expected errors in the\nerror-handling branch of your code.\n\nIf you want to log the error in some way, it is recommended to use the `errorMessage` function (yet again defined in the `PluginComponents` header).\nThis function will return a String-representation of the respective error.\n\nGiven that errors are only reported in form of error codes, it is essential to always explicitly check for them. This is especially important when\nthese API function are used to query information. Accessing the variable passed as an out-parameter to a Mumble-API function may lead to undefined\nbehavior unless you have initialized that variable to a defined value before passing it to the function.\n\nThe only guarantee about variables given as out-parameters to API functions in case of an error is that they remain unchanged by the function.\n\n\n## Multithreading\n\nAll API functions are synchronized. That means they can be called from an arbitrary thread. In order to achieve this synchronization, the functions\nare executed in the main thread on Mumble's side. As the functions return a value, the caller has to wait for the execution to have finished in order\nto continue. In other words: API function calls are **blocking**.\n\nTherefore special care is to be taken as this can easily lead to deadlocks as soon as the plugin spawns a custom thread and uses the API functions\nfrom it. An example of an easy way to run into such a deadlock is as follows:\n\nAssume the plugin has spawned a worker thread that performs some kind of work asynchronously. Let's call that thread \"W\". Now an event occurs that\ncauses a event callback to be called in the plugin-API which usually happens in the already mentioned main thread (see also\n[Threading](PluginAPI.md#threading)). Inside this event callback, the plugin notifies W to perform some sort of work and waits for that to finish. For\nperforming that work W needs to call an API function which blocks until the function can be executed in the main thread. Given that the main thread is\ncurrently blocked by the plugin callback, a deadlock occurs.\n\nThat is to say: You must not wait for a job to finish asynchronously that might call an API function from the plugin-API.\n\n\n## Header files\n\nThe Mumble API definition is contained in the [MumblePlugin.h](https://github.com/mumble-voip/mumble/blob/master/plugins/MumblePlugin.h) header. It\ncontains a list of all available functions as well as documentation for every function.\n\n"},"files":{"docs/dev/plugins/Bundling.md":"# Bundling a Mumble plugin\n\nAfter you have built your plugin you will have a shared library for the respective target OS. While it is possible to just give users this shared\nlibrary and tell them to install them, it might get inconvenient at times. Especially if you want to support your plugin for multiple OS.\n\nTherefore Mumble provides a way to package your plugin in a user-friendly and cross-platform way.\n\nMumble plugin bundles are essentially zip-files with a special contents structure and the file extension `.mumble_plugin` instead of `.zip`. Such a\nbundle must contain a `manifest.xml` as a top-level entry in the archive. The manifest file is used to specify which plugin library (also bundled\nwithin the archive) is to be used for which OS and architecture.\n\n## The manifest file format\n\nThe manifest file _always_ has to be named `manifest.xml` (case-sensitive!) and it must use the `bundle` tag as the top-level element of the XML\nstructure. Furthermore the `bundle` opening tag needs to specify the `format` attribute which will determine the rules the rest of the XML tree has to\nfollow.\n\nUnless otherwise noted the entire manifest file is case-sensitive (including paths specified in it)!\n\n### v1.0.0\n\n| Property | Value |\n| -------- | ----- |\n| `version` attribute | `1.0.0` |\n| Available since: | Mumble v1.4.0 |\n\nInside  the `bundle` element there have to be the `assets`, `name` and `version` elements. `name` is just the name of your plugin (arbitrary String)\nwhereas `version` is the version of your plugin. Note that the version must be given in the format `<major>.<minor>.<patch>`.\n\nInside the `assets` element comes a list of one or more `plugin` elements. Each of these must specify the `os` and `arch` attributes for specifying\nthe operating system and architecture respectively. The contents of these elements is the path to the corresponding plugin library inside the archive\n(relative to the `manifest.xml` file). Note that the paths _must not_ start with `./` and as path separator a single forward slash is to be used (even\non Windows).\n\nThe possible values for the `os` attribute are\n| **OS** | **Attribute** |\n| ------ | ------------- |\n| Windows | `windows` |\n| Linux | `linux` |\n| macOS | `macos` |\n\nand the possible values for the `arch` attribute are\n| **Architecture** | **Attribute** |\n| ---------------- | ------------- |\n| x86 (32-bit) | `x86` |\n| x86 (64-bit) | `x64`|\n\nPutting this together a sample `manifest.xml` can look like this:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<bundle version=\"1.0.0\">\n  <assets>\n    <plugin os=\"windows\" arch=\"x86\">myPlugin.dll</plugin>\n    <plugin os=\"windows\" arch=\"x64\">sub/myPlugin.dll</plugin>\n    <plugin os=\"linux\" arch=\"x64\">sub/libmyPlugin.so</plugin>\n  </assets>\n  <name>MyPlugin</name>\n  <version>1.0.0</version>\n</bundle>\n```\n\n## Creating a plugin bundle\n\nAs written before, a plugin bundle essentially is just a zip file. The only restriction here is that it must not be created using the proprietary\n`Deflate64` algorithm.\n\nThe steps to create a bundle file are as follows\n1. Create an empty working directory\n2. Copy the plugin libraries for the different OS and architectures into this directory (potentially in sub-directories)\n3. Create a `manifest.xml` at the root of the working directory\n4. Add all files and folders in your working directory (but not the working directory itself!) to a zip file\n5. Change the file extension from `.zip` to `.mumble_plugin`\n\nOn Linux you can do this by using the `zip` command line tool like this:\n```bash\nzip my_plugin.mumble_plugin myPlugin.dll sub/myPlugin.dll sub/libmyPlugin.so manifest.xml\n```\n\n## Notes\n\n- You **must not** add any additional files to this archive. Keep the contents of the created archive strictly to the parts mentioned above. It\n  might be tempting to treat the plugin bundle as a regular zip file that can be filled with arbitrary contents but this is not allowed! Instead\n  consider the plugin bundle a binary of its own that has to follow a strict format as outlined above.\n- Plugin names **must not** contain version numbers. At least not when they are distributed to end users. This is because Mumble assumes that\n  the new version of a plugin will use a shared library with the exact same name as the old one. If this assumption is violated, the update mechanism\n  will not work properly causing the new and the old version of the plugin to be installed in parallel.\n\n","docs/dev/plugins/LanguageBindings.md":"# Mumble plugin - Language bindings\n\n## C\n\n`C` is the native language of the plugin API. If you intend to use it, you don't need any special bindings.\n\n\n## C++\n\nThere exists an official `C++` wrapper around the C API. It can be found at https://github.com/mumble-voip/mumble-plugin-cpp.\n\n## Rust\n\n`Rust` bindings are maintained independently from the main Mumble project. They can be found at https://crates.io/crates/mumble-sys.\n\n","docs/dev/plugins/MumbleAPI.md":"# The Mumble-API\n\nThe Mumble-API is a set of function pointers that is given to the plugin during the [initialization process](PluginLifecycle.md#initialization) via\nthe `mumble_registerAPIFunctions` function in the [plugin-API](PluginAPI.md).\n\n\n## How it works\n\nAs a plugin developer you don't have to worry about the implementation of these functions. They are implemented on Mumble's side. All you have to care\nabout is that certain functions exist and that you are free to call any of them.\n\nIn order to do so, you need to know the function signature which is defined in the Mumble-API header file. Functions in there are defined as e.g.\n```cpp\nmumble_error_t(PLUGIN_CALLING_CONVENTION *isConnectionSynchronized)(mumble_plugin_id_t callerID, mumble_connection_t connection, bool *synchronized);\n```\nThe definition may seem a bit odd and intimidating at first glance but that is only because these functions need to be specified as [function\npointers](https://www.geeksforgeeks.org/function-pointer-in-c/). Here are a set of easy steps to (mentally) convert this notation into a (probably)\nmore familiar format:\n1. Ignore `PLUGIN_CALLING_CONVENTION`. The [calling convention](https://en.wikipedia.org/wiki/Calling_convention) is nothing you have to worry about.\n   This is handled for you by your compiler\n2. Remove the first set of parenthesis and the star within them. What remains is the function name\n\nApplying these steps to the above function yields the following definition:\n```cpp\nmumble_error_t isConnectionSynchronized(mumble_plugin_id_t callerID, mumble_connection_t connection, bool *synchronized);\n```\n\nThus we can see that this is a function called `isConnectionSynchronized` that takes 3 parameters and returns a `mumble_error_t`. Therefore if we\nassume that you have stored the Mumble-API in a variable named `mumbleAPI` in your plugin, you could call this function as\n```cpp\nmumble_error_t returnedError = mumbleAPI.isConnectionSynchronized(...);\n```\n\n## General function structure\n\nEach function follows the general signature\n```cpp\nmumble_error_t myFunction(mumble_plugin_id_t callerID /* potentially more arguments */);\n```\n\nThat means that each function _always_ returns an error code that indicates whether the API call was successful. How to handle this returned error\ncode is described in the [error handling section](#error-handling).\n\nFurthermore the first parameter is _always_ the ID of the plugin that makes the API call. Your plugin's ID is given to you during the [initialization\nprocess](PluginLifecycle.md#initialization) via the `mumble_init` function. You have to store this ID and use it every time you make a call to the\nMumble-API as otherwise your calls will be ignored by Mumble.\n\nGiven that the return value of Mumble-API functions are always occupied with the error code, all functions that query some sort of information use an\n_out parameter_. That means that you pre-allocate a variable of the respective type and then pass a pointer to that variable to the API function. On\nsuccessful execution this function will then set the value of your variable through the given pointer.\n\nA good example is obtaining the currently active server connection:\n```cpp\nmumble_connection_t activeConnection;\nif (mumbleAPI.getActiveServerConnection(pluginID, &activeConnection) == MUMBLE_STATUS_OK) {\n    // Do something with activeConnection\n}\n```\n\n\n## Error handling\n\nThe error code returned by Mumble-API functions can (and often must) be used to determine whether the given function call was successful. If the error\ncode compares equal to `MUMBLE_STATUS_OK` (a macro defined in the `PluginComponents` header that is automatically included in the Mumble-API header),\nthen the API call was successful. **Every other value indicates failure**.\n\nIn case of an error, the error code will give information on the exact problem that was found. The possible error codes are defined in the\n`Mumble_ErrorCode` enum (also defined in `PluginComponents`). These values can be used to check the error code against certain expected errors in the\nerror-handling branch of your code.\n\nIf you want to log the error in some way, it is recommended to use the `errorMessage` function (yet again defined in the `PluginComponents` header).\nThis function will return a String-representation of the respective error.\n\nGiven that errors are only reported in form of error codes, it is essential to always explicitly check for them. This is especially important when\nthese API function are used to query information. Accessing the variable passed as an out-parameter to a Mumble-API function may lead to undefined\nbehavior unless you have initialized that variable to a defined value before passing it to the function.\n\nThe only guarantee about variables given as out-parameters to API functions in case of an error is that they remain unchanged by the function.\n\n\n## Multithreading\n\nAll API functions are synchronized. That means they can be called from an arbitrary thread. In order to achieve this synchronization, the functions\nare executed in the main thread on Mumble's side. As the functions return a value, the caller has to wait for the execution to have finished in order\nto continue. In other words: API function calls are **blocking**.\n\nTherefore special care is to be taken as this can easily lead to deadlocks as soon as the plugin spawns a custom thread and uses the API functions\nfrom it. An example of an easy way to run into such a deadlock is as follows:\n\nAssume the plugin has spawned a worker thread that performs some kind of work asynchronously. Let's call that thread \"W\". Now an event occurs that\ncauses a event callback to be called in the plugin-API which usually happens in the already mentioned main thread (see also\n[Threading](PluginAPI.md#threading)). Inside this event callback, the plugin notifies W to perform some sort of work and waits for that to finish. For\nperforming that work W needs to call an API function which blocks until the function can be executed in the main thread. Given that the main thread is\ncurrently blocked by the plugin callback, a deadlock occurs.\n\nThat is to say: You must not wait for a job to finish asynchronously that might call an API function from the plugin-API.\n\n\n## Header files\n\nThe Mumble API definition is contained in the [MumblePlugin.h](https://github.com/mumble-voip/mumble/blob/master/plugins/MumblePlugin.h) header. It\ncontains a list of all available functions as well as documentation for every function.\n\n"},"items":[{"name":"Bundling.md","path":"docs/dev/plugins/Bundling.md","rawUrl":"https://raw.githubusercontent.com/mumble-voip/mumble/HEAD/docs/dev/plugins/Bundling.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Bundling a Mumble plugin\n\nAfter you have built your plugin you will have a shared library for the respective target OS. While it is possible to just give users this shared\nlibrary and tell them to install them, it might get inconvenient at times. Especially if you want to support your plugin for multiple OS.\n\nTherefore Mumble provides a way to package your plugin in a user-friendly and cross-platform way.\n\nMumble plugin bundles are essentially zip-files with a special contents structure and the file extension `.mumble_plugin` instead of `.zip`. Such a\nbundle must contain a `manifest.xml` as a top-level entry in the archive. The manifest file is used to specify which plugin library (also bundled\nwithin the archive) is to be used for which OS and architecture.\n\n## The manifest file format\n\nThe manifest file _always_ has to be named `manifest.xml` (case-sensitive!) and it must use the `bundle` tag as the top-level element of the XML\nstructure. Furthermore the `bundle` opening tag needs to specify the `format` attribute which will determine the rules the rest of the XML tree has to\nfollow.\n\nUnless otherwise noted the entire manifest file is case-sensitive (including paths specified in it)!\n\n### v1.0.0\n\n| Property | Value |\n| -------- | ----- |\n| `version` attribute | `1.0.0` |\n| Available since: | Mumble v1.4.0 |\n\nInside  the `bundle` element there have to be the `assets`, `name` and `version` elements. `name` is just the name of your plugin (arbitrary String)\nwhereas `version` is the version of your plugin. Note that the version must be given in the format `<major>.<minor>.<patch>`.\n\nInside the `assets` element comes a list of one or more `plugin` elements. Each of these must specify the `os` and `arch` attributes for specifying\nthe operating system and architecture respectively. The contents of these elements is the path to the corresponding plugin library inside the archive\n(relative to the `manifest.xml` file). Note that the paths _must not_ start with `./` and as path separator a single forward slash is to be used (even\non Windows).\n\nThe possible values for the `os` attribute are\n| **OS** | **Attribute** |\n| ------ | ------------- |\n| Windows | `windows` |\n| Linux | `linux` |\n| macOS | `macos` |\n\nand the possible values for the `arch` attribute are\n| **Architecture** | **Attribute** |\n| ---------------- | ------------- |\n| x86 (32-bit) | `x86` |\n| x86 (64-bit) | `x64`|\n\nPutting this together a sample `manifest.xml` can look like this:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<bundle version=\"1.0.0\">\n  <assets>\n    <plugin os=\"windows\" arch=\"x86\">myPlugin.dll</plugin>\n    <plugin os=\"windows\" arch=\"x64\">sub/myPlugin.dll</plugin>\n    <plugin os=\"linux\" arch=\"x64\">sub/libmyPlugin.so</plugin>\n  </assets>\n  <name>MyPlugin</name>\n  <version>1.0.0</version>\n</bundle>\n```\n\n## Creating a plugin bundle\n\nAs written before, a plugin bundle essentially is just a zip file. The only restriction here is that it must not be created using the proprietary\n`Deflate64` algorithm.\n\nThe steps to create a bundle file are as follows\n1. Create an empty working directory\n2. Copy the plugin libraries for the different OS and architectures into this directory (potentially in sub-directories)\n3. Create a `manifest.xml` at the root of the working directory\n4. Add all files and folders in your working directory (but not the working directory itself!) to a zip file\n5. Change the file extension from `.zip` to `.mumble_plugin`\n\nOn Linux you can do this by using the `zip` command line tool like this:\n```bash\nzip my_plugin.mumble_plugin myPlugin.dll sub/myPlugin.dll sub/libmyPlugin.so manifest.xml\n```\n\n## Notes\n\n- You **must not** add any additional files to this archive. Keep the contents of the created archive strictly to the parts mentioned above. It\n  might be tempting to treat the plugin bundle as a regular zip file that can be filled with arbitrary contents but this is not allowed! Instead\n  consider the plugin bundle a binary of its own that has to follow a strict format as outlined above.\n- Plugin names **must not** contain version numbers. At least not when they are distributed to end users. This is because Mumble assumes that\n  the new version of a plugin will use a shared library with the exact same name as the old one. If this assumption is violated, the update mechanism\n  will not work properly causing the new and the old version of the plugin to be installed in parallel.\n\n","isInternal":false,"tokens":1048,"sizeBytes":4441},{"name":"LanguageBindings.md","path":"docs/dev/plugins/LanguageBindings.md","rawUrl":"https://raw.githubusercontent.com/mumble-voip/mumble/HEAD/docs/dev/plugins/LanguageBindings.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Mumble plugin - Language bindings\n\n## C\n\n`C` is the native language of the plugin API. If you intend to use it, you don't need any special bindings.\n\n\n## C++\n\nThere exists an official `C++` wrapper around the C API. It can be found at https://github.com/mumble-voip/mumble-plugin-cpp.\n\n## Rust\n\n`Rust` bindings are maintained independently from the main Mumble project. They can be found at https://crates.io/crates/mumble-sys.\n\n","isInternal":false,"tokens":110,"sizeBytes":431},{"name":"MumbleAPI.md","path":"docs/dev/plugins/MumbleAPI.md","rawUrl":"https://raw.githubusercontent.com/mumble-voip/mumble/HEAD/docs/dev/plugins/MumbleAPI.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# The Mumble-API\n\nThe Mumble-API is a set of function pointers that is given to the plugin during the [initialization process](PluginLifecycle.md#initialization) via\nthe `mumble_registerAPIFunctions` function in the [plugin-API](PluginAPI.md).\n\n\n## How it works\n\nAs a plugin developer you don't have to worry about the implementation of these functions. They are implemented on Mumble's side. All you have to care\nabout is that certain functions exist and that you are free to call any of them.\n\nIn order to do so, you need to know the function signature which is defined in the Mumble-API header file. Functions in there are defined as e.g.\n```cpp\nmumble_error_t(PLUGIN_CALLING_CONVENTION *isConnectionSynchronized)(mumble_plugin_id_t callerID, mumble_connection_t connection, bool *synchronized);\n```\nThe definition may seem a bit odd and intimidating at first glance but that is only because these functions need to be specified as [function\npointers](https://www.geeksforgeeks.org/function-pointer-in-c/). Here are a set of easy steps to (mentally) convert this notation into a (probably)\nmore familiar format:\n1. Ignore `PLUGIN_CALLING_CONVENTION`. The [calling convention](https://en.wikipedia.org/wiki/Calling_convention) is nothing you have to worry about.\n   This is handled for you by your compiler\n2. Remove the first set of parenthesis and the star within them. What remains is the function name\n\nApplying these steps to the above function yields the following definition:\n```cpp\nmumble_error_t isConnectionSynchronized(mumble_plugin_id_t callerID, mumble_connection_t connection, bool *synchronized);\n```\n\nThus we can see that this is a function called `isConnectionSynchronized` that takes 3 parameters and returns a `mumble_error_t`. Therefore if we\nassume that you have stored the Mumble-API in a variable named `mumbleAPI` in your plugin, you could call this function as\n```cpp\nmumble_error_t returnedError = mumbleAPI.isConnectionSynchronized(...);\n```\n\n## General function structure\n\nEach function follows the general signature\n```cpp\nmumble_error_t myFunction(mumble_plugin_id_t callerID /* potentially more arguments */);\n```\n\nThat means that each function _always_ returns an error code that indicates whether the API call was successful. How to handle this returned error\ncode is described in the [error handling section](#error-handling).\n\nFurthermore the first parameter is _always_ the ID of the plugin that makes the API call. Your plugin's ID is given to you during the [initialization\nprocess](PluginLifecycle.md#initialization) via the `mumble_init` function. You have to store this ID and use it every time you make a call to the\nMumble-API as otherwise your calls will be ignored by Mumble.\n\nGiven that the return value of Mumble-API functions are always occupied with the error code, all functions that query some sort of information use an\n_out parameter_. That means that you pre-allocate a variable of the respective type and then pass a pointer to that variable to the API function. On\nsuccessful execution this function will then set the value of your variable through the given pointer.\n\nA good example is obtaining the currently active server connection:\n```cpp\nmumble_connection_t activeConnection;\nif (mumbleAPI.getActiveServerConnection(pluginID, &activeConnection) == MUMBLE_STATUS_OK) {\n    // Do something with activeConnection\n}\n```\n\n\n## Error handling\n\nThe error code returned by Mumble-API functions can (and often must) be used to determine whether the given function call was successful. If the error\ncode compares equal to `MUMBLE_STATUS_OK` (a macro defined in the `PluginComponents` header that is automatically included in the Mumble-API header),\nthen the API call was successful. **Every other value indicates failure**.\n\nIn case of an error, the error code will give information on the exact problem that was found. The possible error codes are defined in the\n`Mumble_ErrorCode` enum (also defined in `PluginComponents`). These values can be used to check the error code against certain expected errors in the\nerror-handling branch of your code.\n\nIf you want to log the error in some way, it is recommended to use the `errorMessage` function (yet again defined in the `PluginComponents` header).\nThis function will return a String-representation of the respective error.\n\nGiven that errors are only reported in form of error codes, it is essential to always explicitly check for them. This is especially important when\nthese API function are used to query information. Accessing the variable passed as an out-parameter to a Mumble-API function may lead to undefined\nbehavior unless you have initialized that variable to a defined value before passing it to the function.\n\nThe only guarantee about variables given as out-parameters to API functions in case of an error is that they remain unchanged by the function.\n\n\n## Multithreading\n\nAll API functions are synchronized. That means they can be called from an arbitrary thread. In order to achieve this synchronization, the functions\nare executed in the main thread on Mumble's side. As the functions return a value, the caller has to wait for the execution to have finished in order\nto continue. In other words: API function calls are **blocking**.\n\nTherefore special care is to be taken as this can easily lead to deadlocks as soon as the plugin spawns a custom thread and uses the API functions\nfrom it. An example of an easy way to run into such a deadlock is as follows:\n\nAssume the plugin has spawned a worker thread that performs some kind of work asynchronously. Let's call that thread \"W\". Now an event occurs that\ncauses a event callback to be called in the plugin-API which usually happens in the already mentioned main thread (see also\n[Threading](PluginAPI.md#threading)). Inside this event callback, the plugin notifies W to perform some sort of work and waits for that to finish. For\nperforming that work W needs to call an API function which blocks until the function can be executed in the main thread. Given that the main thread is\ncurrently blocked by the plugin callback, a deadlock occurs.\n\nThat is to say: You must not wait for a job to finish asynchronously that might call an API function from the plugin-API.\n\n\n## Header files\n\nThe Mumble API definition is contained in the [MumblePlugin.h](https://github.com/mumble-voip/mumble/blob/master/plugins/MumblePlugin.h) header. It\ncontains a list of all available functions as well as documentation for every function.\n\n","isInternal":false,"tokens":1387,"sizeBytes":6497}],"systemPromptSnippet":"<yakaai_skills repo=\"mumble-voip/mumble\">\n<!-- File: docs/dev/plugins/Bundling.md (Tokens: ~1048 | Category: anthropic-skill) -->\n# Bundling a Mumble plugin\n\nAfter you have built your plugin you will have a shared library for the respective target OS. While it is possible to just give users this shared\nlibrary and tell them to install them, it might get inconvenient at times. Especially if you want to support your plugin for multiple OS.\n\nTherefore Mumble provides a way to package your plugin in a user-friendly and cross-platform way.\n\nMumble plugin bundles are essentially zip-files with a special contents structure and the file extension `.mumble_plugin` instead of `.zip`. Such a\nbundle must contain a `manifest.xml` as a top-level entry in the archive. The manifest file is used to specify which plugin library (also bundled\nwithin the archive) is to be used for which OS and architecture.\n\n## The manifest file format\n\nThe manifest file _always_ has to be named `manifest.xml` (case-sensitive!) and it must use the `bundle` tag as the top-level element of the XML\nstructure. Furthermore the `bundle` opening tag needs to specify the `format` attribute which will determine the rules the rest of the XML tree has to\nfollow.\n\nUnless otherwise noted the entire manifest file is case-sensitive (including paths specified in it)!\n\n### v1.0.0\n\n| Property | Value |\n| -------- | ----- |\n| `version` attribute | `1.0.0` |\n| Available since: | Mumble v1.4.0 |\n\nInside  the `bundle` element there have to be the `assets`, `name` and `version` elements. `name` is just the name of your plugin (arbitrary String)\nwhereas `version` is the version of your plugin. Note that the version must be given in the format `<major>.<minor>.<patch>`.\n\nInside the `assets` element comes a list of one or more `plugin` elements. Each of these must specify the `os` and `arch` attributes for specifying\nthe operating system and architecture respectively. The contents of these elements is the path to the corresponding plugin library inside the archive\n(relative to the `manifest.xml` file). Note that the paths _must not_ start with `./` and as path separator a single forward slash is to be used (even\non Windows).\n\nThe possible values for the `os` attribute are\n| **OS** | **Attribute** |\n| ------ | ------------- |\n| Windows | `windows` |\n| Linux | `linux` |\n| macOS | `macos` |\n\nand the possible values for the `arch` attribute are\n| **Architecture** | **Attribute** |\n| ---------------- | ------------- |\n| x86 (32-bit) | `x86` |\n| x86 (64-bit) | `x64`|\n\nPutting this together a sample `manifest.xml` can look like this:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<bundle version=\"1.0.0\">\n  <assets>\n    <plugin os=\"windows\" arch=\"x86\">myPlugin.dll</plugin>\n    <plugin os=\"windows\" arch=\"x64\">sub/myPlugin.dll</plugin>\n    <plugin os=\"linux\" arch=\"x64\">sub/libmyPlugin.so</plugin>\n  </assets>\n  <name>MyPlugin</name>\n  <version>1.0.0</version>\n</bundle>\n```\n\n## Creating a plugin bundle\n\nAs written before, a plugin bundle essentially is just a zip file. The only restriction here is that it must not be created using the proprietary\n`Deflate64` algorithm.\n\nThe steps to create a bundle file are as follows\n1. Create an empty working directory\n2. Copy the plugin libraries for the different OS and architectures into this directory (potentially in sub-directories)\n3. Create a `manifest.xml` at the root of the working directory\n4. Add all files and folders in your working directory (but not the working directory itself!) to a zip file\n5. Change the file extension from `.zip` to `.mumble_plugin`\n\nOn Linux you can do this by using the `zip` command line tool like this:\n```bash\nzip my_plugin.mumble_plugin myPlugin.dll sub/myPlugin.dll sub/libmyPlugin.so manifest.xml\n```\n\n## Notes\n\n- You **must not** add any additional files to this archive. Keep the contents of the created archive strictly to the parts mentioned above. It\n  might be tempting to treat the plugin bundle as a regular zip file that can be filled with arbitrary contents but this is not allowed! Instead\n  consider the plugin bundle a binary of its own that has to follow a strict format as outlined above.\n- Plugin names **must not** contain version numbers. At least not when they are distributed to end users. This is because Mumble assumes that\n  the new version of a plugin will use a shared library with the exact same name as the old one. If this assumption is violated, the update mechanism\n  will not work properly causing the new and the old version of the plugin to be installed in parallel.\n\n<!-- File: docs/dev/plugins/LanguageBindings.md (Tokens: ~110 | Category: anthropic-skill) -->\n# Mumble plugin - Language bindings\n\n## C\n\n`C` is the native language of the plugin API. If you intend to use it, you don't need any special bindings.\n\n\n## C++\n\nThere exists an official `C++` wrapper around the C API. It can be found at https://github.com/mumble-voip/mumble-plugin-cpp.\n\n## Rust\n\n`Rust` bindings are maintained independently from the main Mumble project. They can be found at https://crates.io/crates/mumble-sys.\n\n<!-- File: docs/dev/plugins/MumbleAPI.md (Tokens: ~1387 | Category: anthropic-skill) -->\n# The Mumble-API\n\nThe Mumble-API is a set of function pointers that is given to the plugin during the [initialization process](PluginLifecycle.md#initialization) via\nthe `mumble_registerAPIFunctions` function in the [plugin-API](PluginAPI.md).\n\n\n## How it works\n\nAs a plugin developer you don't have to worry about the implementation of these functions. They are implemented on Mumble's side. All you have to care\nabout is that certain functions exist and that you are free to call any of them.\n\nIn order to do so, you need to know the function signature which is defined in the Mumble-API header file. Functions in there are defined as e.g.\n```cpp\nmumble_error_t(PLUGIN_CALLING_CONVENTION *isConnectionSynchronized)(mumble_plugin_id_t callerID, mumble_connection_t connection, bool *synchronized);\n```\nThe definition may seem a bit odd and intimidating at first glance but that is only because these functions need to be specified as [function\npointers](https://www.geeksforgeeks.org/function-pointer-in-c/). Here are a set of easy steps to (mentally) convert this notation into a (probably)\nmore familiar format:\n1. Ignore `PLUGIN_CALLING_CONVENTION`. The [calling convention](https://en.wikipedia.org/wiki/Calling_convention) is nothing you have to worry about.\n   This is handled for you by your compiler\n2. Remove the first set of parenthesis and the star within them. What remains is the function name\n\nApplying these steps to the above function yields the following definition:\n```cpp\nmumble_error_t isConnectionSynchronized(mumble_plugin_id_t callerID, mumble_connection_t connection, bool *synchronized);\n```\n\nThus we can see that this is a function called `isConnectionSynchronized` that takes 3 parameters and returns a `mumble_error_t`. Therefore if we\nassume that you have stored the Mumble-API in a variable named `mumbleAPI` in your plugin, you could call this function as\n```cpp\nmumble_error_t returnedError = mumbleAPI.isConnectionSynchronized(...);\n```\n\n## General function structure\n\nEach function follows the general signature\n```cpp\nmumble_error_t myFunction(mumble_plugin_id_t callerID /* potentially more arguments */);\n```\n\nThat means that each function _always_ returns an error code that indicates whether the API call was successful. How to handle this returned error\ncode is described in the [error handling section](#error-handling).\n\nFurthermore the first parameter is _always_ the ID of the plugin that makes the API call. Your plugin's ID is given to you during the [initialization\nprocess](PluginLifecycle.md#initialization) via the `mumble_init` function. You have to store this ID and use it every time you make a call to the\nMumble-API as otherwise your calls will be ignored by Mumble.\n\nGiven that the return value of Mumble-API functions are always occupied with the error code, all functions that query some sort of information use an\n_out parameter_. That means that you pre-allocate a variable of the respective type and then pass a pointer to that variable to the API function. On\nsuccessful execution this function will then set the value of your variable through the given pointer.\n\nA good example is obtaining the currently active server connection:\n```cpp\nmumble_connection_t activeConnection;\nif (mumbleAPI.getActiveServerConnection(pluginID, &activeConnection) == MUMBLE_STATUS_OK) {\n    // Do something with activeConnection\n}\n```\n\n\n## Error handling\n\nThe error code returned by Mumble-API functions can (and often must) be used to determine whether the given function call was successful. If the error\ncode compares equal to `MUMBLE_STATUS_OK` (a macro defined in the `PluginComponents` header that is automatically included in the Mumble-API header),\nthen the API call was successful. **Every other value indicates failure**.\n\nIn case of an error, the error code will give information on the exact problem that was found. The possible error codes are defined in the\n`Mumble_ErrorCode` enum (also defined in `PluginComponents`). These values can be used to check the error code against certain expected errors in the\nerror-handling branch of your code.\n\nIf you want to log the error in some way, it is recommended to use the `errorMessage` function (yet again defined in the `PluginComponents` header).\nThis function will return a String-representation of the respective error.\n\nGiven that errors are only reported in form of error codes, it is essential to always explicitly check for them. This is especially important when\nthese API function are used to query information. Accessing the variable passed as an out-parameter to a Mumble-API function may lead to undefined\nbehavior unless you have initialized that variable to a defined value before passing it to the function.\n\nThe only guarantee about variables given as out-parameters to API functions in case of an error is that they remain unchanged by the function.\n\n\n## Multithreading\n\nAll API functions are synchronized. That means they can be called from an arbitrary thread. In order to achieve this synchronization, the functions\nare executed in the main thread on Mumble's side. As the functions return a value, the caller has to wait for the execution to have finished in order\nto continue. In other words: API function calls are **blocking**.\n\nTherefore special care is to be taken as this can easily lead to deadlocks as soon as the plugin spawns a custom thread and uses the API functions\nfrom it. An example of an easy way to run into such a deadlock is as follows:\n\nAssume the plugin has spawned a worker thread that performs some kind of work asynchronously. Let's call that thread \"W\". Now an event occurs that\ncauses a event callback to be called in the plugin-API which usually happens in the already mentioned main thread (see also\n[Threading](PluginAPI.md#threading)). Inside this event callback, the plugin notifies W to perform some sort of work and waits for that to finish. For\nperforming that work W needs to call an API function which blocks until the function can be executed in the main thread. Given that the main thread is\ncurrently blocked by the plugin callback, a deadlock occurs.\n\nThat is to say: You must not wait for a job to finish asynchronously that might call an API function from the plugin-API.\n\n\n## Header files\n\nThe Mumble API definition is contained in the [MumblePlugin.h](https://github.com/mumble-voip/mumble/blob/master/plugins/MumblePlugin.h) header. It\ncontains a list of all available functions as well as documentation for every function.\n</yakaai_skills>"}