home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / TeamSpeak / TeamSpeak3-Client-win32-3.0.0.exe / pluginsdk / src / plugin.c next >
C/C++ Source or Header  |  2011-08-08  |  40KB  |  915 lines

  1. /*
  2.  * TeamSpeak 3 demo plugin
  3.  *
  4.  * Copyright (c) 2008-2011 TeamSpeak Systems GmbH
  5.  */
  6.  
  7. #ifdef WINDOWS
  8. #pragma warning (disable : 4100)  /* Disable Unreferenced parameter warning */
  9. #endif
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "public_errors.h"
  15. #include "public_errors_rare.h"
  16. #include "public_definitions.h"
  17. #include "public_rare_definitions.h"
  18. #include "ts3_functions.h"
  19. #include "plugin_events.h"
  20. #include "plugin.h"
  21.  
  22. static struct TS3Functions ts3Functions;
  23.  
  24. #ifdef WINDOWS
  25. #define _strcpy(dest, destSize, src) strcpy_s(dest, destSize, src)
  26. #define snprintf sprintf_s
  27. #else
  28. #define _strcpy(dest, destSize, src) { strncpy(dest, src, destSize-1); dest[destSize-1] = '\0'; }
  29. #endif
  30.  
  31. #define PLUGIN_API_VERSION 13
  32.  
  33. #define PATH_BUFSIZE 512
  34. #define COMMAND_BUFSIZE 128
  35. #define INFODATA_BUFSIZE 128
  36. #define SERVERINFO_BUFSIZE 256
  37. #define CHANNELINFO_BUFSIZE 512
  38. #define RETURNCODE_BUFSIZE 128
  39. #define REQUESTCLIENTMOVERETURNCODES_SLOTS 5
  40.  
  41. static char* pluginID = NULL;
  42.  
  43. /* Array for request client move return codes. See comments within ts3plugin_processCommand for details */
  44. static char requestClientMoveReturnCodes[REQUESTCLIENTMOVERETURNCODES_SLOTS][RETURNCODE_BUFSIZE];
  45.  
  46. /*********************************** Required functions ************************************/
  47. /*
  48.  * If any of these required functions is not implemented, TS3 will refuse to load the plugin
  49.  */
  50.  
  51. /* Unique name identifying this plugin */
  52. const char* ts3plugin_name() {
  53.     return "Test Plugin";
  54. }
  55.  
  56. /* Plugin version */
  57. const char* ts3plugin_version() {
  58.     return "1.2";
  59. }
  60.  
  61. /* Plugin API version. Must be the same as the clients API major version, else the plugin fails to load. */
  62. int ts3plugin_apiVersion() {
  63.     return PLUGIN_API_VERSION;
  64. }
  65.  
  66. /* Plugin author */
  67. const char* ts3plugin_author() {
  68.     return "TeamSpeak Systems GmbH";
  69. }
  70.  
  71. /* Plugin description */
  72. const char* ts3plugin_description() {
  73.     return "This plugin demonstrates the TeamSpeak 3 client plugin architecture.";
  74. }
  75.  
  76. /* Set TeamSpeak 3 callback functions */
  77. void ts3plugin_setFunctionPointers(const struct TS3Functions funcs) {
  78.     ts3Functions = funcs;
  79. }
  80.  
  81. /*
  82.  * Custom code called right after loading the plugin. Returns 0 on success, 1 on failure.
  83.  * If the function returns 1 on failure, the plugin will be unloaded again.
  84.  */
  85. int ts3plugin_init() {
  86.     char appPath[PATH_BUFSIZE];
  87.     char resourcesPath[PATH_BUFSIZE];
  88.     char configPath[PATH_BUFSIZE];
  89.     char pluginPath[PATH_BUFSIZE];
  90.  
  91.     /* Your plugin init code here */
  92.     printf("PLUGIN: init\n");
  93.  
  94.     /* Show API versions */
  95.     printf("PLUGIN: Client API Version: %d, Plugin API Version: %d\n", ts3Functions.getAPIVersion(), ts3plugin_apiVersion());
  96.  
  97.     /* Example on how to query application, resources and configuration paths from client */
  98.     /* Note: Console client returns empty string for app and resources path */
  99.     ts3Functions.getAppPath(appPath, PATH_BUFSIZE);
  100.     ts3Functions.getResourcesPath(resourcesPath, PATH_BUFSIZE);
  101.     ts3Functions.getConfigPath(configPath, PATH_BUFSIZE);
  102.     ts3Functions.getPluginPath(pluginPath, PATH_BUFSIZE);
  103.  
  104.     printf("PLUGIN: App path: %s\nResources path: %s\nConfig path: %s\nPlugin path: %s\n", appPath, resourcesPath, configPath, pluginPath);
  105.  
  106.     /* Initialize return codes array for requestClientMove */
  107.     memset(requestClientMoveReturnCodes, 0, REQUESTCLIENTMOVERETURNCODES_SLOTS * RETURNCODE_BUFSIZE);
  108.  
  109.     return 0;  /* 0 = success, 1 = failure */
  110. }
  111.  
  112. /* Custom code called right before the plugin is unloaded */
  113. void ts3plugin_shutdown() {
  114.     /* Your plugin cleanup code here */
  115.     printf("PLUGIN: shutdown\n");
  116.  
  117.     /*
  118.      * Note:
  119.      * If your plugin implements a settings dialog, it must be closed and deleted here, else the
  120.      * TeamSpeak client will most likely crash (DLL removed but dialog from DLL code still open).
  121.      */
  122.  
  123.     /* Free pluginID if we registered it */
  124.     if(pluginID) {
  125.         free(pluginID);
  126.         pluginID = NULL;
  127.     }
  128. }
  129.  
  130. /****************************** Optional functions ********************************/
  131. /*
  132.  * Following functions are optional, if not needed you don't need to implement them.
  133.  */
  134.  
  135. /* Tell client if plugin offers a configuration window. If this function is not implemented, it's an assumed "does not offer" (PLUGIN_OFFERS_NO_CONFIGURE). */
  136. int ts3plugin_offersConfigure() {
  137.     printf("PLUGIN: offersConfigure\n");
  138.     /*
  139.      * Return values:
  140.      * PLUGIN_OFFERS_NO_CONFIGURE         - Plugin does not implement ts3plugin_configure
  141.      * PLUGIN_OFFERS_CONFIGURE_NEW_THREAD - Plugin does implement ts3plugin_configure and requests to run this function in an own thread
  142.      * PLUGIN_OFFERS_CONFIGURE_QT_THREAD  - Plugin does implement ts3plugin_configure and requests to run this function in the Qt GUI thread
  143.      */
  144.     return PLUGIN_OFFERS_NO_CONFIGURE;  /* In this case ts3plugin_configure does not need to be implemented */
  145. }
  146.  
  147. /* Plugin might offer a configuration window. If ts3plugin_offersConfigure returns 0, this function does not need to be implemented. */
  148. void ts3plugin_configure(void* handle, void* qParentWidget) {
  149.     printf("PLUGIN: configure\n");
  150. }
  151.  
  152. /*
  153.  * If the plugin wants to use error return codes or plugin commands, it needs to register a command ID. This function will be automatically
  154.  * called after the plugin was initialized. This function is optional. If you don't use error return codes or plugin commands, the function
  155.  * can be omitted.
  156.  * Note the passed pluginID parameter is no longer valid after calling this function, so you must copy it and store it in the plugin.
  157.  */
  158. void ts3plugin_registerPluginID(const char* id) {
  159.     const size_t sz = strlen(id) + 1;
  160.     pluginID = (char*)malloc(sz * sizeof(char));
  161.     _strcpy(pluginID, sz, id);  /* The id buffer will invalidate after exiting this function */
  162.     printf("PLUGIN: registerPluginID: %s\n", pluginID);
  163. }
  164.  
  165. /* Plugin command keyword. Return NULL or "" if not used. */
  166. const char* ts3plugin_commandKeyword() {
  167.     return "test";
  168. }
  169.  
  170. /* Plugin processes console command. Return 0 if plugin handled the command, 1 if not handled. */
  171. int ts3plugin_processCommand(uint64 serverConnectionHandlerID, const char* command) {
  172.     char buf[COMMAND_BUFSIZE];
  173.     char *s, *param1 = NULL, *param2 = NULL;
  174.     int i = 0;
  175.     enum { CMD_NONE = 0, CMD_JOIN, CMD_COMMAND, CMD_SERVERINFO, CMD_CHANNELINFO, CMD_AVATAR } cmd = CMD_NONE;
  176. #ifdef WINDOWS
  177.     char* context = NULL;
  178. #endif
  179.  
  180.     printf("PLUGIN: process command: '%s'\n", command);
  181.  
  182.     /* Test command: "join <channelID> [password]" */
  183.     _strcpy(buf, COMMAND_BUFSIZE, command);
  184. #ifdef WINDOWS
  185.     s = strtok_s(buf, " ", &context);
  186. #else
  187.     s = strtok(buf, " ");
  188. #endif
  189.     while(s != NULL) {
  190.         if(i == 0) {
  191.             if(!strcmp(s, "join")) {
  192.                 cmd = CMD_JOIN;
  193.             } else if(!strcmp(s, "command")) {
  194.                 cmd = CMD_COMMAND;
  195.             } else if(!strcmp(s, "serverinfo")) {
  196.                 cmd = CMD_SERVERINFO;
  197.             } else if(!strcmp(s, "channelinfo")) {
  198.                 cmd = CMD_CHANNELINFO;
  199.             } else if(!strcmp(s, "avatar")) {
  200.                 cmd = CMD_AVATAR;
  201.             }
  202.         } else if(i == 1) {
  203.             param1 = s;
  204.         } else {
  205.             param2 = s;
  206.         }
  207. #ifdef WINDOWS
  208.         s = strtok_s(NULL, " ", &context);
  209. #else
  210.         s = strtok(NULL, " ");
  211. #endif
  212.         i++;
  213.     }
  214.  
  215.     switch(cmd) {
  216.         case CMD_NONE:
  217.             return 1;  /* Command not handled by plugin */
  218.         case CMD_JOIN:
  219.             if(param1) {
  220.                 uint64 channelID = (uint64)atoi(param1);
  221.                 char* password = param2 ? param2 : "";
  222.                 char returnCode[RETURNCODE_BUFSIZE];
  223.                 anyID myID;
  224.                 int i;
  225.  
  226.                 /* Get own clientID */
  227.                 if(ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) {
  228.                     ts3Functions.logMessage("Error querying client ID", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  229.                     break;
  230.                 }
  231.  
  232.                 /* Create return code for requestClientMove function call. If creation fails, returnCode will be NULL, which can be
  233.                  * passed into the client functions meaning no return code is used.
  234.                  * Note: To use return codes, the plugin needs to register a plugin ID using ts3plugin_registerPluginID */
  235.                 ts3Functions.createReturnCode(pluginID, returnCode, RETURNCODE_BUFSIZE);
  236.  
  237.                 /* Remember return code in requestClientMove return code array. We use an array as it's not guaranteed the server
  238.                  * response is received before a second client move request has been sent. In a C++ plugin it should be a better
  239.                  * idea to use a dynamic STL container instead of a static array. For our example a static array with 5 slots
  240.                  * should be sufficient.
  241.                  * In a real-world application it might be necessary to store additional information like the client or channel ID
  242.                  * to have this data available when handling the server response. */
  243.                 for(i=0; i<REQUESTCLIENTMOVERETURNCODES_SLOTS; ++i) {
  244.                     if(!strlen(requestClientMoveReturnCodes[i])) {  /* Find next free slot */
  245.                         _strcpy(requestClientMoveReturnCodes[i], RETURNCODE_BUFSIZE, returnCode);
  246.                         break;
  247.                     }
  248.                 }
  249.  
  250.                 /* Request joining specified channel using above created return code */
  251.                 if(ts3Functions.requestClientMove(serverConnectionHandlerID, myID, channelID, password, returnCode) != ERROR_ok) {
  252.                     ts3Functions.logMessage("Error requesting client move", LogLevel_INFO, "Plugin", serverConnectionHandlerID);
  253.                     if(i < REQUESTCLIENTMOVERETURNCODES_SLOTS) {
  254.                         memset(requestClientMoveReturnCodes[i], 0, RETURNCODE_BUFSIZE);  /* Clear returnCode slot in array */
  255.                     }
  256.                 }
  257.             } else {
  258.                 ts3Functions.printMessageToCurrentTab("Missing channel ID parameter.");
  259.             }
  260.             break;
  261.         case CMD_COMMAND:
  262.             if(param1) {
  263.                 /* Send plugin command to all clients in current channel. In this case targetIds is unused and can be NULL. */
  264.                 if(pluginID) {
  265.                     /* See ts3plugin_registerPluginID for how to obtain a pluginID */
  266.                     printf("PLUGIN: Sending plugin command to current channel: %s\n", param1);
  267.                     ts3Functions.sendPluginCommand(serverConnectionHandlerID, pluginID, param1, PluginCommandTarget_CURRENT_CHANNEL, NULL, NULL);
  268.                 } else {
  269.                     printf("PLUGIN: Failed to send plugin command, was not registered.\n");
  270.                 }
  271.             } else {
  272.                 ts3Functions.printMessageToCurrentTab("Missing command parameter.");
  273.             }
  274.             break;
  275.         case CMD_SERVERINFO: {
  276.             /* Query host, port and server password of current server tab.
  277.              * The password parameter can be NULL if the plugin does not want to receive the server password.
  278.              * Note: Server password is only available if the user has actually used it when connecting. If a user has
  279.              * connected with the permission to ignore passwords (b_virtualserver_join_ignore_password) and the password,
  280.              * was not entered, it will not be available.
  281.              * getServerConnectInfo returns 0 on success, 1 on error or if current server tab is disconnected. */
  282.             char host[SERVERINFO_BUFSIZE];
  283.             /*char password[SERVERINFO_BUFSIZE];*/
  284.             char* password = NULL;  /* Don't receive server password */
  285.             unsigned short port;
  286.             if(!ts3Functions.getServerConnectInfo(serverConnectionHandlerID, host, &port, password, SERVERINFO_BUFSIZE)) {
  287.                 char msg[SERVERINFO_BUFSIZE];
  288.                 snprintf(msg, sizeof(msg), "Server Connect Info: %s:%d", host, port);
  289.                 ts3Functions.printMessageToCurrentTab(msg);
  290.             } else {
  291.                 ts3Functions.printMessageToCurrentTab("No server connect info available.");
  292.             }
  293.             break;
  294.         }
  295.         case CMD_CHANNELINFO: {
  296.             /* Query channel path and password of current server tab.
  297.              * The password parameter can be NULL if the plugin does not want to receive the channel password.
  298.              * Note: Channel password is only available if the user has actually used it when entering the channel. If a user has
  299.              * entered a channel with the permission to ignore passwords (b_channel_join_ignore_password) and the password,
  300.              * was not entered, it will not be available.
  301.              * getChannelConnectInfo returns 0 on success, 1 on error or if current server tab is disconnected. */
  302.             char path[CHANNELINFO_BUFSIZE];
  303.             /*char password[CHANNELINFO_BUFSIZE];*/
  304.             char* password = NULL;  /* Don't receive channel password */
  305.  
  306.             /* Get own clientID and channelID */
  307.             anyID myID;
  308.             uint64 myChannelID;
  309.             if(ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) {
  310.                 ts3Functions.logMessage("Error querying client ID", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  311.                 break;
  312.             }
  313.             /* Get own channel ID */
  314.             if(ts3Functions.getChannelOfClient(serverConnectionHandlerID, myID, &myChannelID) != ERROR_ok) {
  315.                 ts3Functions.logMessage("Error querying channel ID", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  316.                 break;
  317.             }
  318.  
  319.             /* Get channel connect info of own channel */
  320.             if(!ts3Functions.getChannelConnectInfo(serverConnectionHandlerID, myChannelID, path, password, CHANNELINFO_BUFSIZE)) {
  321.                 char msg[CHANNELINFO_BUFSIZE];
  322.                 snprintf(msg, sizeof(msg), "Channel Connect Info: %s", path);
  323.                 ts3Functions.printMessageToCurrentTab(msg);
  324.             } else {
  325.                 ts3Functions.printMessageToCurrentTab("No channel connect info available.");
  326.             }
  327.             break;
  328.         }
  329.         case CMD_AVATAR: {
  330.             // Type "/test avatar <clientID>" to test getting the avatar file path
  331.             char avatarPath[PATH_BUFSIZE];
  332.             anyID clientID = (anyID)atoi(param1);
  333.             unsigned int error;
  334.  
  335.             memset(avatarPath, 0, PATH_BUFSIZE);
  336.             error = ts3Functions.getAvatar(serverConnectionHandlerID, clientID, avatarPath, PATH_BUFSIZE);
  337.             if(error == ERROR_ok) {  /* ERROR_ok means the client has an avatar set. */
  338.                 if(strlen(avatarPath)) {  /* Avatar path contains the full path to the avatar image in the TS3Client cache directory */
  339.                     printf("Avatar path: %s\n", avatarPath);
  340.                 } else { /* Empty avatar path means the client has an avatar but the image has not yet been cached. The TeamSpeak
  341.                           * client will automatically start the download and call onAvatarUpdated when done */
  342.                     printf("Avatar not yet downloaded, waiting for onAvatarUpdated...\n");
  343.                 }
  344.             } else if(error == ERROR_database_empty_result) {  /* Not an error, the client simply has no avatar set */
  345.                 printf("Client has no avatar\n");
  346.             } else { /* Other error occured (invalid server connection handler ID, invalid client ID, file io error etc) */
  347.                 printf("Error getting avatar: %d\n", error);
  348.             }
  349.         }
  350.     }
  351.  
  352.     return 0;  /* Plugin handled command */
  353. }
  354.  
  355. /* Client changed current server connection handler */
  356. void ts3plugin_currentServerConnectionChanged(uint64 serverConnectionHandlerID) {
  357.     printf("PLUGIN: currentServerConnectionChanged %llu (%llu)\n", (long long unsigned int)serverConnectionHandlerID, (long long unsigned int)ts3Functions.getCurrentServerConnectionHandlerID());
  358. }
  359.  
  360. void ts3plugin_pluginEvent(unsigned short data, const char* message) {
  361.     char type, subtype;
  362.  
  363.     printf("PLUGIN: pluginEvent data = %u\n", data);
  364.     if(message) {
  365.         printf("Message: %s\n", message);
  366.     }
  367.  
  368.     type = data >> 8;
  369.     subtype = data & 0xFF;
  370.     printf("Type = %d, subtype = %d\n", type, subtype);
  371.  
  372.     switch(type) {
  373.         case PLUGIN_EVENT_TYPE_HOTKEY:
  374.             switch(subtype) {
  375.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_TOGGLE_MICRO_ON:
  376.                     printf("Micro on\n");
  377.                     break;
  378.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_TOGGLE_MICRO_OFF:
  379.                     printf("Micro off\n");
  380.                     break;
  381.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_TOGGLE_SPEAKER_ON:
  382.                     printf("Speaker on\n");
  383.                     break;
  384.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_TOGGLE_SPEAKER_OFF:
  385.                     printf("Speaker off\n");
  386.                     break;
  387.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_TOGGLE_AWAY_ON:
  388.                     printf("Away on\n");
  389.                     break;
  390.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_TOGGLE_AWAY_OFF:
  391.                     printf("Away off\n");
  392.                     break;
  393.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_ACTIVATE_MICRO:
  394.                     printf("Activate micro\n");
  395.                     break;
  396.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_ACTIVATE_SPEAKER:
  397.                     printf("Activate speaker\n");
  398.                     break;
  399.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_ACTIVATE_AWAY:
  400.                     printf("Activate away\n");
  401.                     break;
  402.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_DEACTIVATE_MICRO:
  403.                     printf("Deactivate micro\n");
  404.                     break;
  405.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_DEACTIVATE_SPEAKER:
  406.                     printf("Deactivate speakers\n");
  407.                     break;
  408.                 case PLUGIN_EVENT_SUBTYPE_HOTKEY_DEACTIVATE_AWAY:
  409.                     printf("Deactivate away\n");
  410.                     break;
  411.                 default:
  412.                     break;
  413.             }
  414.             break;
  415.         default:
  416.             break;
  417.     }
  418. }
  419.  
  420. /*
  421.  * Implement the following three functions when the plugin should display a line in the server/channel/client info.
  422.  * If any of ts3plugin_infoTitle, ts3plugin_infoData or ts3plugin_freeMemory is missing, the info text will not be displayed.
  423.  */
  424.  
  425. /* Static title shown in the left column in the info frame */
  426. const char* ts3plugin_infoTitle() {
  427.     return "Test plugin info";
  428. }
  429.  
  430. /*
  431.  * Dynamic content shown in the right column in the info frame. Memory for the data string needs to be allocated in this
  432.  * function. The client will call ts3plugin_freeMemory once done with the string to release the allocated memory again.
  433.  * Check the parameter "type" if you want to implement this feature only for specific item types. Set the parameter
  434.  * "data" to NULL to have the client ignore the info data.
  435.  */
  436. void ts3plugin_infoData(uint64 serverConnectionHandlerID, uint64 id, enum PluginItemType type, char** data) {
  437.     char* name;
  438.  
  439.     /* For demonstration purpose, display the name of the currently selected server, channel or client. */
  440.     switch(type) {
  441.         case PLUGIN_SERVER:
  442.             if(ts3Functions.getServerVariableAsString(serverConnectionHandlerID, VIRTUALSERVER_NAME, &name) != ERROR_ok) {
  443.                 printf("Error getting virtual server name\n");
  444.                 return;
  445.             }
  446.             break;
  447.         case PLUGIN_CHANNEL:
  448.             if(ts3Functions.getChannelVariableAsString(serverConnectionHandlerID, id, CHANNEL_NAME, &name) != ERROR_ok) {
  449.                 printf("Error getting channel name\n");
  450.                 return;
  451.             }
  452.             break;
  453.         case PLUGIN_CLIENT:
  454.             if(ts3Functions.getClientVariableAsString(serverConnectionHandlerID, (anyID)id, CLIENT_NICKNAME, &name) != ERROR_ok) {
  455.                 printf("Error getting client nickname\n");
  456.                 return;
  457.             }
  458.             break;
  459.         default:
  460.             printf("Invalid item type: %d\n", type);
  461.             data = NULL;  /* Ignore */
  462.             return;
  463.     }
  464.  
  465.     *data = (char*)malloc(INFODATA_BUFSIZE * sizeof(char));  /* Must be allocated in the plugin! */
  466.     snprintf(*data, INFODATA_BUFSIZE, "The nickname is \"%s\"", name);
  467.     ts3Functions.freeMemory(name);
  468. }
  469.  
  470. /* Required to release the memory for parameter "data" allocated in ts3plugin_infoData */
  471. void ts3plugin_freeMemory(void* data) {
  472.     free(data);
  473. }
  474.  
  475. /*
  476.  * Plugin requests to be always automatically loaded by the TeamSpeak 3 client unless
  477.  * the user manually disabled it in the plugin dialog.
  478.  * This function is optional. If missing, no autoload is assumed.
  479.  */
  480. int ts3plugin_requestAutoload() {
  481.     return 0;  /* 1 = request autoloaded, 0 = do not request autoload */
  482. }
  483.  
  484. /************************** TeamSpeak callbacks ***************************/
  485. /*
  486.  * Following functions are optional, feel free to remove unused callbacks.
  487.  * See the clientlib documentation for details on each function.
  488.  */
  489.  
  490. /* Clientlib */
  491.  
  492. void ts3plugin_onConnectStatusChangeEvent(uint64 serverConnectionHandlerID, int newStatus, unsigned int errorNumber) {
  493.     /* Some example code following to show how to use the information query functions. */
  494.  
  495.     if(newStatus == STATUS_CONNECTION_ESTABLISHED) {  /* connection established and we have client and channels available */
  496.         char* s;
  497.         char msg[1024];
  498.         anyID myID;
  499.         uint64* ids;
  500.         size_t i;
  501.         unsigned int error;
  502.  
  503.         /* Print clientlib version */
  504.         if(ts3Functions.getClientLibVersion(&s) == ERROR_ok) {
  505.             printf("PLUGIN: Client lib version: %s\n", s);
  506.             ts3Functions.freeMemory(s);  /* Release string */
  507.         } else {
  508.             ts3Functions.logMessage("Error querying client lib version", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  509.             return;
  510.         }
  511.  
  512.         /* Write plugin name and version to log */
  513.         snprintf(msg, sizeof(msg), "Plugin %s, Version %s, Author: %s", ts3plugin_name(), ts3plugin_version(), ts3plugin_author());
  514.         ts3Functions.logMessage(msg, LogLevel_INFO, "Plugin", serverConnectionHandlerID);
  515.  
  516.         /* Print virtual server name */
  517.         if((error = ts3Functions.getServerVariableAsString(serverConnectionHandlerID, VIRTUALSERVER_NAME, &s)) != ERROR_ok) {
  518.             if(error != ERROR_not_connected) {  /* Don't spam error in this case (failed to connect) */
  519.                 ts3Functions.logMessage("Error querying server name", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  520.             }
  521.             return;
  522.         }
  523.         printf("PLUGIN: Server name: %s\n", s);
  524.         ts3Functions.freeMemory(s);
  525.  
  526.         /* Print virtual server welcome message */
  527.         if(ts3Functions.getServerVariableAsString(serverConnectionHandlerID, VIRTUALSERVER_WELCOMEMESSAGE, &s) != ERROR_ok) {
  528.             ts3Functions.logMessage("Error querying server welcome message", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  529.             return;
  530.         }
  531.         printf("PLUGIN: Server welcome message: %s\n", s);
  532.         ts3Functions.freeMemory(s);  /* Release string */
  533.  
  534.         /* Print own client ID and nickname on this server */
  535.         if(ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) {
  536.             ts3Functions.logMessage("Error querying client ID", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  537.             return;
  538.         }
  539.         if(ts3Functions.getClientSelfVariableAsString(serverConnectionHandlerID, CLIENT_NICKNAME, &s) != ERROR_ok) {
  540.             ts3Functions.logMessage("Error querying client nickname", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  541.             return;
  542.         }
  543.         printf("PLUGIN: My client ID = %d, nickname = %s\n", myID, s);
  544.         ts3Functions.freeMemory(s);
  545.  
  546.         /* Print list of all channels on this server */
  547.         if(ts3Functions.getChannelList(serverConnectionHandlerID, &ids) != ERROR_ok) {
  548.             ts3Functions.logMessage("Error getting channel list", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  549.             return;
  550.         }
  551.         printf("PLUGIN: Available channels:\n");
  552.         for(i=0; ids[i]; i++) {
  553.             /* Query channel name */
  554.             if(ts3Functions.getChannelVariableAsString(serverConnectionHandlerID, ids[i], CHANNEL_NAME, &s) != ERROR_ok) {
  555.                 ts3Functions.logMessage("Error querying channel name", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  556.                 return;
  557.             }
  558.             printf("PLUGIN: Channel ID = %llu, name = %s\n", (long long unsigned int)ids[i], s);
  559.             ts3Functions.freeMemory(s);
  560.         }
  561.         ts3Functions.freeMemory(ids);  /* Release array */
  562.  
  563.         /* Print list of existing server connection handlers */
  564.         printf("PLUGIN: Existing server connection handlers:\n");
  565.         if(ts3Functions.getServerConnectionHandlerList(&ids) != ERROR_ok) {
  566.             ts3Functions.logMessage("Error getting server list", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  567.             return;
  568.         }
  569.         for(i=0; ids[i]; i++) {
  570.             if((error = ts3Functions.getServerVariableAsString(ids[i], VIRTUALSERVER_NAME, &s)) != ERROR_ok) {
  571.                 if(error != ERROR_not_connected) {  /* Don't spam error in this case (failed to connect) */
  572.                     ts3Functions.logMessage("Error querying server name", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  573.                 }
  574.                 continue;
  575.             }
  576.             printf("- %llu - %s\n", (long long unsigned int)ids[i], s);
  577.             ts3Functions.freeMemory(s);
  578.         }
  579.         ts3Functions.freeMemory(ids);
  580.     }
  581. }
  582.  
  583. void ts3plugin_onNewChannelEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 channelParentID) {
  584. }
  585.  
  586. void ts3plugin_onNewChannelCreatedEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 channelParentID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) {
  587. }
  588.  
  589. void ts3plugin_onDelChannelEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) {
  590. }
  591.  
  592. void ts3plugin_onChannelMoveEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 newChannelParentID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) {
  593. }
  594.  
  595. void ts3plugin_onUpdateChannelEvent(uint64 serverConnectionHandlerID, uint64 channelID) {
  596. }
  597.  
  598. void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) {
  599. }
  600.  
  601. void ts3plugin_onUpdateClientEvent(uint64 serverConnectionHandlerID, anyID clientID) {
  602. }
  603.  
  604. void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage) {
  605. }
  606.  
  607. void ts3plugin_onClientMoveSubscriptionEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility) {
  608. }
  609.  
  610. void ts3plugin_onClientMoveTimeoutEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* timeoutMessage) {
  611. }
  612.  
  613. void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID moverID, const char* moverName, const char* moverUniqueIdentifier, const char* moveMessage) {
  614. }
  615.  
  616. void ts3plugin_onClientKickFromChannelEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID kickerID, const char* kickerName, const char* kickerUniqueIdentifier, const char* kickMessage) {
  617. }
  618.  
  619. void ts3plugin_onClientKickFromServerEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID kickerID, const char* kickerName, const char* kickerUniqueIdentifier, const char* kickMessage) {
  620. }
  621.  
  622. void ts3plugin_onServerEditedEvent(uint64 serverConnectionHandlerID, anyID editerID, const char* editerName, const char* editerUniqueIdentifier) {
  623. }
  624.  
  625. void ts3plugin_onServerUpdatedEvent(uint64 serverConnectionHandlerID) {
  626. }
  627.  
  628. int ts3plugin_onServerErrorEvent(uint64 serverConnectionHandlerID, const char* errorMessage, unsigned int error, const char* returnCode, const char* extraMessage) {
  629.     printf("PLUGIN: onServerErrorEvent %llu %s %d\n", (long long unsigned int)serverConnectionHandlerID, errorMessage, error);
  630.     if(returnCode) {
  631.         /* Check if return code was stored in our request client move returnCode array */
  632.         int i;
  633.         for(i=0; i<REQUESTCLIENTMOVERETURNCODES_SLOTS; ++i) {
  634.             if(!strcmp(requestClientMoveReturnCodes[i], returnCode)) {
  635.                 printf("request client move return code found in slot %d\n", i);
  636.                 memset(requestClientMoveReturnCodes[i], 0, RETURNCODE_BUFSIZE);  /* Clear returnCode slot in array */
  637.                 /* In case of using a a plugin return code, the plugin can return:
  638.                  * 0: Client will continue handling this error (print to chat tab)
  639.                  * 1: Client will ignore this error, the plugin announces it has handled it */
  640.                 return 1;
  641.             }
  642.         }
  643.     }
  644.     return 0;  /* If no plugin return code was used, the return value of this function is ignored */
  645. }
  646.  
  647. void ts3plugin_onServerStopEvent(uint64 serverConnectionHandlerID, const char* shutdownMessage) {
  648. }
  649.  
  650. int ts3plugin_onTextMessageEvent(uint64 serverConnectionHandlerID, anyID targetMode, anyID toID, anyID fromID, const char* fromName, const char* fromUniqueIdentifier, const char* message, int ffIgnored) {
  651.     printf("PLUGIN: onTextMessageEvent %llu %d %d %s %s %d\n", (long long unsigned int)serverConnectionHandlerID, targetMode, fromID, fromName, message, ffIgnored);
  652.  
  653.     /* Friend/Foe manager has ignored the message, so ignore here as well. */
  654.     if(ffIgnored) {
  655.         return 0; /* Client will ignore the message anyways, so return value here doesn't matter */
  656.     }
  657.  
  658. #if 0
  659.     {
  660.         /* Example code: Autoreply to sender */
  661.         /* Disabled because quite annoying, but should give you some ideas what is possible here */
  662.         /* Careful, when two clients use this, they will get banned quickly... */
  663.         anyID myID;
  664.         if(ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) {
  665.             ts3Functions.logMessage("Error querying own client id", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  666.             return 0;
  667.         }
  668.         if(fromID != myID) {  /* Don't reply when source is own client */
  669.             if(ts3Functions.requestSendPrivateTextMsg(serverConnectionHandlerID, "Text message back!", fromID, NULL) != ERROR_ok) {
  670.                 ts3Functions.logMessage("Error requesting send text message", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  671.             }
  672.         }
  673.     }
  674. #endif
  675.  
  676.     return 0;  /* 0 = handle normally, 1 = client will ignore the text message */
  677. }
  678.  
  679. void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int status, int isReceivedWhisper, anyID clientID) {
  680. }
  681.  
  682. void ts3plugin_onConnectionInfoEvent(uint64 serverConnectionHandlerID, anyID clientID) {
  683. }
  684.  
  685. void ts3plugin_onServerConnectionInfoEvent(uint64 serverConnectionHandlerID) {
  686. }
  687.  
  688. void ts3plugin_onChannelSubscribeEvent(uint64 serverConnectionHandlerID, uint64 channelID) {
  689. }
  690.  
  691. void ts3plugin_onChannelSubscribeFinishedEvent(uint64 serverConnectionHandlerID) {
  692. }
  693.  
  694. void ts3plugin_onChannelUnsubscribeEvent(uint64 serverConnectionHandlerID, uint64 channelID) {
  695. }
  696.  
  697. void ts3plugin_onChannelUnsubscribeFinishedEvent(uint64 serverConnectionHandlerID) {
  698. }
  699.  
  700. void ts3plugin_onChannelDescriptionUpdateEvent(uint64 serverConnectionHandlerID, uint64 channelID) {
  701. }
  702.  
  703. void ts3plugin_onChannelPasswordChangedEvent(uint64 serverConnectionHandlerID, uint64 channelID) {
  704. }
  705.  
  706. void ts3plugin_onPlaybackShutdownCompleteEvent(uint64 serverConnectionHandlerID) {
  707. }
  708.  
  709. void ts3plugin_onSoundDeviceListChangedEvent(const char* modeID, int playOrCap) {
  710. }
  711.  
  712. void ts3plugin_onEditPlaybackVoiceDataEvent(uint64 serverConnectionHandlerID, anyID clientID, short* samples, int sampleCount, int channels) {
  713. }
  714.  
  715. void ts3plugin_onEditPostProcessVoiceDataEvent(uint64 serverConnectionHandlerID, anyID clientID, short* samples, int sampleCount, int channels) {
  716. }
  717.  
  718. void ts3plugin_onEditMixedPlaybackVoiceDataEvent(uint64 serverConnectionHandlerID, short* samples, int sampleCount, int channels) {
  719. }
  720.  
  721. void ts3plugin_onEditRecordedVoiceDataEvent(uint64 serverConnectionHandlerID, short* samples, int sampleCount, int channels, int* edited) {
  722. }
  723.  
  724. void ts3plugin_onCustom3dRolloffCalculationEvent(uint64 serverConnectionHandlerID, anyID clientID, float distance , float* volume ){
  725. }
  726.  
  727. void ts3plugin_onUserLoggingMessageEvent(const char* logMessage, int logLevel, const char* logChannel, uint64 logID, const char* logTime, const char* completeLogString) {
  728. }
  729.  
  730. /* Clientlib rare */
  731.  
  732. void ts3plugin_onClientBanFromServerEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID kickerID, const char* kickerName, const char* kickerUniqueIdentifier, uint64 time, const char* kickMessage) {
  733. }
  734.  
  735. int ts3plugin_onClientPokeEvent(uint64 serverConnectionHandlerID, anyID fromClientID, const char* pokerName, const char* pokerUniqueIdentity, const char* message, int ffIgnored) {
  736.     anyID myID;
  737.  
  738.     printf("PLUGIN onClientPokeEvent: %llu %d %s %s %d\n", (long long unsigned int)serverConnectionHandlerID, fromClientID, pokerName, message, ffIgnored);
  739.  
  740.     /* Check if the Friend/Foe manager has already blocked this poke */
  741.     if(ffIgnored) {
  742.         return 0;  /* Client will block anyways, doesn't matter what we return */
  743.     }
  744.  
  745.     /* Example code: Send text message back to poking client */
  746.     if(ts3Functions.getClientID(serverConnectionHandlerID, &myID) != ERROR_ok) {  /* Get own client ID */
  747.         ts3Functions.logMessage("Error querying own client id", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  748.         return 0;
  749.     }
  750.     if(fromClientID != myID) {  /* Don't reply when source is own client */
  751.         if(ts3Functions.requestSendPrivateTextMsg(serverConnectionHandlerID, "Received your poke!", fromClientID, NULL) != ERROR_ok) {
  752.             ts3Functions.logMessage("Error requesting send text message", LogLevel_ERROR, "Plugin", serverConnectionHandlerID);
  753.         }
  754.     }
  755.  
  756.     return 0;  /* 0 = handle normally, 1 = client will ignore the poke */
  757. }
  758.  
  759. void ts3plugin_onClientSelfVariableUpdateEvent(uint64 serverConnectionHandlerID, int flag, const char* oldValue, const char* newValue) {
  760. }
  761.  
  762. void ts3plugin_onFileListEvent(uint64 serverConnectionHandlerID, uint64 channelID, const char* path, const char* name, uint64 size, uint64 datetime, int type, uint64 incompletesize, const char* returnCode) {
  763. }
  764.  
  765. void ts3plugin_onFileListFinishedEvent(uint64 serverConnectionHandlerID, uint64 channelID, const char* path) {
  766. }
  767.  
  768. void ts3plugin_onFileInfoEvent(uint64 serverConnectionHandlerID, uint64 channelID, const char* name, uint64 size, uint64 datetime) {
  769. }
  770.  
  771. void ts3plugin_onServerGroupListEvent(uint64 serverConnectionHandlerID, uint64 serverGroupID, const char* name, int type, int iconID, int saveDB) {
  772. }
  773.  
  774. void ts3plugin_onServerGroupListFinishedEvent(uint64 serverConnectionHandlerID) {
  775. }
  776.  
  777. void ts3plugin_onServerGroupByClientIDEvent(uint64 serverConnectionHandlerID, const char* name, uint64 serverGroupList, uint64 clientDatabaseID) {
  778. }
  779.  
  780. void ts3plugin_onServerGroupPermListEvent(uint64 serverConnectionHandlerID, uint64 serverGroupID, anyID permissionID, int permissionValue, int permissionNegated, int permissionSkip) {
  781. }
  782.  
  783. void ts3plugin_onServerGroupPermListFinishedEvent(uint64 serverConnectionHandlerID, uint64 serverGroupID) {
  784. }
  785.  
  786. void ts3plugin_onServerGroupClientListEvent(uint64 serverConnectionHandlerID, uint64 serverGroupID, uint64 clientDatabaseID, const char* clientNameIdentifier, const char* clientUniqueID) {
  787. }
  788.  
  789. void ts3plugin_onChannelGroupListEvent(uint64 serverConnectionHandlerID, uint64 channelGroupID, const char* name, int type, int iconID, int saveDB) {
  790. }
  791.  
  792. void ts3plugin_onChannelGroupListFinishedEvent(uint64 serverConnectionHandlerID) {
  793. }
  794.  
  795. void ts3plugin_onChannelGroupPermListEvent(uint64 serverConnectionHandlerID, uint64 channelGroupID, anyID permissionID, int permissionValue, int permissionNegated, int permissionSkip) {
  796. }
  797.  
  798. void ts3plugin_onChannelGroupPermListFinishedEvent(uint64 serverConnectionHandlerID, uint64 channelGroupID) {
  799. }
  800.  
  801. void ts3plugin_onChannelPermListEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID permissionID, int permissionValue, int permissionNegated, int permissionSkip) {
  802. }
  803.  
  804. void ts3plugin_onChannelPermListFinishedEvent(uint64 serverConnectionHandlerID, uint64 channelID) {
  805. }
  806.  
  807. void ts3plugin_onClientPermListEvent(uint64 serverConnectionHandlerID, uint64 clientDatabaseID, anyID permissionID, int permissionValue, int permissionNegated, int permissionSkip) {
  808. }
  809.  
  810. void ts3plugin_onClientPermListFinishedEvent(uint64 serverConnectionHandlerID, uint64 clientDatabaseID) {
  811. }
  812.  
  813. void ts3plugin_onChannelClientPermListEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 clientDatabaseID, anyID permissionID, int permissionValue, int permissionNegated, int permissionSkip) {
  814. }
  815.  
  816. void ts3plugin_onChannelClientPermListFinishedEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 clientDatabaseID) {
  817. }
  818.  
  819. void ts3plugin_onClientChannelGroupChangedEvent(uint64 serverConnectionHandlerID, uint64 channelGroupID, uint64 channelID, anyID clientID, anyID invokerClientID, const char* invokerName, const char* invokerUniqueIdentity) {
  820. }
  821.  
  822. int ts3plugin_onServerPermissionErrorEvent(uint64 serverConnectionHandlerID, const char* errorMessage, unsigned int error, const char* returnCode, anyID failedPermissionID) {
  823.     return 0;  /* See onServerErrorEvent for return code description */
  824. }
  825.  
  826. void ts3plugin_onPermissionListEvent(uint64 serverConnectionHandlerID, anyID permissionID, const char* permissionName, const char* permissionDescription) {
  827. }
  828.  
  829. void ts3plugin_onPermissionListFinishedEvent(uint64 serverConnectionHandlerID) {
  830. }
  831.  
  832. void ts3plugin_onPermissionOverviewEvent(uint64 serverConnectionHandlerID, uint64 clientDatabaseID, uint64 channelID, int overviewType, uint64 overviewID1, uint64 overviewID2, anyID permissionID, int permissionValue, int permissionNegated, int permissionSkip) {
  833. }
  834.  
  835. void ts3plugin_onPermissionOverviewFinishedEvent(uint64 serverConnectionHandlerID) {
  836. }
  837.  
  838. void ts3plugin_onServerGroupClientAddedEvent(uint64 serverConnectionHandlerID, anyID clientID, const char* clientName, const char* clientUniqueIdentity, uint64 serverGroupID, anyID invokerClientID, const char* invokerName, const char* invokerUniqueIdentity) {
  839. }
  840.  
  841. void ts3plugin_onServerGroupClientDeletedEvent(uint64 serverConnectionHandlerID, anyID clientID, const char* clientName, const char* clientUniqueIdentity, uint64 serverGroupID, anyID invokerClientID, const char* invokerName, const char* invokerUniqueIdentity) {
  842. }
  843.  
  844. void ts3plugin_onClientNeededPermissionsEvent(uint64 serverConnectionHandlerID, anyID permissionID, int permissionValue) {
  845. }
  846.  
  847. void ts3plugin_onClientNeededPermissionsFinishedEvent(uint64 serverConnectionHandlerID) {
  848. }
  849.  
  850. void ts3plugin_onFileTransferStatusEvent(anyID transferID, unsigned int status, const char* statusMessage, uint64 remotefileSize, uint64 serverConnectionHandlerID) {
  851. }
  852.  
  853. void ts3plugin_onClientChatClosedEvent(uint64 serverConnectionHandlerID, anyID clientID) {
  854. }
  855.  
  856. void ts3plugin_onClientChatComposingEvent(uint64 serverConnectionHandlerID, anyID clientID) {
  857. }
  858.  
  859. void ts3plugin_onServerLogEvent(uint64 serverConnectionHandlerID, const char* logTimestamp, const char* logChannel, int logLevel, const char* logMsg) {
  860. }
  861.  
  862. void ts3plugin_onServerLogFinishedEvent(uint64 serverConnectionHandlerID) {
  863. }
  864.  
  865. void ts3plugin_onServerQueryEvent(uint64 serverConnectionHandlerID, const char* result) {
  866. }
  867.  
  868. void ts3plugin_onMessageListEvent(uint64 serverConnectionHandlerID, uint64 messageID, const char* fromClientUniqueIdentity, const char* subject, uint64 timestamp, int flagRead) {
  869. }
  870.  
  871. void ts3plugin_onMessageGetEvent(uint64 serverConnectionHandlerID, uint64 messageID, const char* fromClientUniqueIdentity, const char* subject, const char* message, uint64 timestamp) {
  872. }
  873.  
  874. void ts3plugin_onClientDBIDfromUIDEvent(uint64 serverConnectionHandlerID, const char* uniqueClientIdentifier, uint64 clientDatabaseID) {
  875. }
  876.  
  877. void ts3plugin_onClientNamefromUIDEvent(uint64 serverConnectionHandlerID, const char* uniqueClientIdentifier, uint64 clientDatabaseID, const char* clientNickName) {
  878. }
  879.  
  880. void ts3plugin_onClientNamefromDBIDEvent(uint64 serverConnectionHandlerID, const char* uniqueClientIdentifier, uint64 clientDatabaseID, const char* clientNickName) {
  881. }
  882.  
  883. void ts3plugin_onComplainListEvent(uint64 serverConnectionHandlerID, uint64 targetClientDatabaseID, const char* targetClientNickName, uint64 fromClientDatabaseID, const char* fromClientNickName, const char* complainReason, uint64 timestamp) {
  884. }
  885.  
  886. void ts3plugin_onBanListEvent(uint64 serverConnectionHandlerID, uint64 banid, const char* ip, const char* name, const char* uid, uint64 creationTime, uint64 durationTime, const char* invokerName,
  887.                               uint64 invokercldbid, const char* invokeruid, const char* reason, int numberOfEnforcements) {
  888. }
  889.  
  890. void ts3plugin_onClientServerQueryLoginPasswordEvent(uint64 serverConnectionHandlerID, const char* loginPassword) {
  891. }
  892.  
  893. void ts3plugin_onPluginCommandEvent(uint64 serverConnectionHandlerID, const char* pluginName, const char* pluginCommand) {
  894.     printf("ON PLUGIN COMMAND: %s %s\n", pluginName, pluginCommand);
  895. }
  896.  
  897. void ts3plugin_onIncomingClientQueryEvent(uint64 serverConnectionHandlerID, const char* commandText) {
  898. }
  899.  
  900. /* Client UI callbacks */
  901.  
  902. /*
  903.  * Called from client when an avatar image has been downloaded to or deleted from cache.
  904.  * This callback can be called spontaneously or in response to ts3Functions.getAvatar()
  905.  */
  906. void ts3plugin_onAvatarUpdated(uint64 serverConnectionHandlerID, anyID clientID, const char* avatarPath) {
  907.     /* If avatarPath is NULL, the avatar got deleted */
  908.     /* If not NULL, avatarPath contains the path to the avatar file in the TS3Client cache */
  909.     if(avatarPath != NULL) {
  910.         printf("onAvatarUpdated: %llu %d %s\n", (long long unsigned int)serverConnectionHandlerID, clientID, avatarPath);
  911.     } else {
  912.         printf("onAvatarUpdated: %llu %d - deleted\n", (long long unsigned int)serverConnectionHandlerID, clientID);
  913.     }
  914. }
  915.