Forum


Notice to all users

We are migrating towards a new forum system located at community.teamspeak.com, as such this forum will become read-only on January 29, 2020

Results 1 to 2 of 2
  1. #1
    Join Date
    December 2009
    Location
    Germany
    Posts
    7

    Solved Problem with ts3client_openCaptureDevice, returns ERROR_undefined

    Out of boredom, I tried to create a plugin for the game garrysmod, in order to allow a direct intigration of teamspeak.

    Everything went pretty smooth to the point where I tried to connect to the server, apparently ts3client_openCaptureDevice returns ERROR_undefined, I didn't find any note about this in the sdk documentation.

    Can anyone tell what the conditions are for this to happen?

    Below the code, ignore everything Lua related as it's not important in this matter.
    Code:
    #include "ILuaModuleManager.h"
    
    #include <cstring>
    
    #include <cstdio>
    
    #include "clientlib.h"
    #include "public_errors.h"
    
    GMOD_MODULE( Open, Close );
    
    ILuaInterface *gLua = NULL;
    
    struct ClientUIFunctions handlerFuncs;
    
    uint64 connectionHandler = NULL;
    
    bool isInitialized = false;
    
    bool isConnected = false;
    
    FILE* debugFile;
    
    using namespace GarrysMod::Lua;
    
    #define TS3LOG(msg) fprintf(debugFile, msg); fflush(debugFile)
    
    /*
     * Callback for connection status change.
     * Connection status switches through the states STATUS_DISCONNECTED, STATUS_CONNECTING, STATUS_CONNECTED and STATUS_CONNECTION_ESTABLISHED.
     *
     * Parameters:
     *   serverConnectionHandlerID - Server connection handler ID
     *   newStatus                 - New connection status, see the enum ConnectStatus in clientlib_publicdefinitions.h
     *   errorNumber               - Error code. Should be zero when connecting or actively disconnection.
     *                               Contains error state when losing connection.
     */
    void onConnectStatusChangeEvent(uint64 serverConnectionHandlerID, int newStatus, unsigned int errorNumber) {
    	printf("Connect status changed: %llu %d %u\n", (unsigned long long)serverConnectionHandlerID, newStatus, errorNumber);
    	/* Failed to connect ? */
    	if(newStatus == STATUS_DISCONNECTED && errorNumber == ERROR_failed_connection_initialisation) {
    		printf("Looks like there is no server running, terminate!\n");
    	}
    }
    
    /*
     * Callback for current channels being announced to the client after connecting to a server.
     *
     * Parameters:
     *   serverConnectionHandlerID - Server connection handler ID
     *   channelID                 - ID of the announced channel
     *   channelParentID           - ID of the parent channel
     */
    void onNewChannelEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 channelParentID) {
        /* Query channel name from channel ID */
        char* name;
        unsigned int error;
    
        printf("onNewChannelEvent: %llu %llu %llu\n", (unsigned long long)serverConnectionHandlerID, (unsigned long long)channelID, (unsigned long long)channelParentID);
        if((error = ts3client_getChannelVariableAsString(serverConnectionHandlerID, channelID, CHANNEL_NAME, &name)) == ERROR_ok) {
            printf("New channel: %llu %s \n", (unsigned long long)channelID, name);
            ts3client_freeMemory(name);  /* Release dynamically allocated memory only if function succeeded */
        } else {
            char* errormsg;
            if(ts3client_getErrorMessage(error, &errormsg) == ERROR_ok) {
                printf("Error getting channel name in onNewChannelEvent: %s\n", errormsg);
                ts3client_freeMemory(errormsg);
            }
        }
    }
    
    /*
     * Callback for just created channels.
     *
     * Parameters:
     *   serverConnectionHandlerID - Server connection handler ID
     *   channelID                 - ID of the announced channel
     *   channelParentID           - ID of the parent channel
     *   invokerID                 - ID of the client who created the channel
     *   invokerName               - Name of the client who created the channel
     */
    void onNewChannelCreatedEvent(uint64 serverConnectionHandlerID, uint64 channelID, uint64 channelParentID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) {
        char* name;
    
        /* Query channel name from channel ID */
        if(ts3client_getChannelVariableAsString(serverConnectionHandlerID, channelID, CHANNEL_NAME, &name) != ERROR_ok)
            return;
        printf("New channel created: %s\n", name);
        ts3client_freeMemory(name);  /* Release dynamically allocated memory only if function succeeded */
    }
    
    /*
     * Callback when a channel was deleted.
     *
     * Parameters:
     *   serverConnectionHandlerID - Server connection handler ID
     *   channelID                 - ID of the deleted channel
     *   invokerID                 - ID of the client who deleted the channel
     *   invokerName               - Name of the client who deleted the channel
     */
    void onDelChannelEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier) {
    	printf("Channel ID %llu deleted by %s (%u)\n", (unsigned long long)channelID, invokerName, invokerID);
    }
    
    /*
     * Called when a client joins, leaves or moves to another channel.
     *
     * Parameters:
     *   serverConnectionHandlerID - Server connection handler ID
     *   clientID                  - ID of the moved client
     *   oldChannelID              - ID of the old channel left by the client
     *   newChannelID              - ID of the new channel joined by the client
     *   visibility                - Visibility of the moved client. See the enum Visibility in clientlib_publicdefinitions.h
     *                               Values: ENTER_VISIBILITY, RETAIN_VISIBILITY, LEAVE_VISIBILITY
     */
    void onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage) {
    	printf("ClientID %u moves from channel %llu to %llu with message %s\n", clientID, (unsigned long long)oldChannelID, (unsigned long long)newChannelID, moveMessage);
    }
    
    /*
     * Callback for other clients in current and subscribed channels being announced to the client.
     *
     * Parameters:
     *   serverConnectionHandlerID - Server connection handler ID
     *   clientID                  - ID of the announced client
     *   oldChannelID              - ID of the subscribed channel where the client left visibility
     *   newChannelID              - ID of the subscribed channel where the client entered visibility
     *   visibility                - Visibility of the announced client. See the enum Visibility in clientlib_publicdefinitions.h
     *                               Values: ENTER_VISIBILITY, RETAIN_VISIBILITY, LEAVE_VISIBILITY
     */
    void onClientMoveSubscriptionEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility) {
        char* name;
    
        /* Query client nickname from ID */
        if(ts3client_getClientVariableAsString(serverConnectionHandlerID, clientID, CLIENT_NICKNAME, &name) != ERROR_ok)
            return;
        printf("New client: %s\n", name);
        ts3client_freeMemory(name);  /* Release dynamically allocated memory only if function succeeded */
    }
    
    /*
     * Called when a client drops his connection.
     *
     * Parameters:
     *   serverConnectionHandlerID - Server connection handler ID
     *   clientID                  - ID of the moved client
     *   oldChannelID              - ID of the channel the leaving client was previously member of
     *   newChannelID              - 0, as client is leaving
     *   visibility                - Always LEAVE_VISIBILITY
     *   timeoutMessage            - Optional message giving the reason for the timeout
     */
    void onClientMoveTimeoutEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* timeoutMessage) {
    	printf("ClientID %u timeouts with message %s\n",clientID, timeoutMessage);
    }
    
    /*
     * This event is called when a client starts or stops talking.
     *
     * Parameters:
     *   serverConnectionHandlerID - Server connection handler ID
     *   status                    - 1 if client starts talking, 0 if client stops talking
     *   isReceivedWhisper         - 1 if this event was caused by whispering, 0 if caused by normal talking
     *   clientID                  - ID of the client who announced the talk status change
     */
    void onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int status, int isReceivedWhisper, anyID clientID) {
        char* name;
    
        /* Query client nickname from ID */
        if(ts3client_getClientVariableAsString(serverConnectionHandlerID, clientID, CLIENT_NICKNAME, &name) != ERROR_ok)
            return;
        if(status == STATUS_TALKING) {
            printf("Client \"%s\" starts talking.\n", name);
        } else {
            printf("Client \"%s\" stops talking.\n", name);
        }
        ts3client_freeMemory(name);  /* Release dynamically allocated memory only if function succeeded */
    }
    
    void onServerErrorEvent(uint64 serverConnectionHandlerID, const char* errorMessage, unsigned int error, const char* returnCode, const char* extraMessage) {
    	printf("Error for server %llu: %s %s\n", (unsigned long long)serverConnectionHandlerID, errorMessage, extraMessage);
    }
    
    #define tryTS3Call(func, ...)\
    	if(errCode = func(##__VA_ARGS__) != ERROR_ok) {\
    		char* errorMsg;\
    		if(ts3client_getErrorMessage(errCode, &errorMsg) == ERROR_ok) {\
    			gLua->Push(false);\
    			gLua->Push((double)errCode);\
    			gLua->Push(errorMsg);\
    			ts3client_freeMemory(errorMsg);\
    			return 3;\
    		}\
    		gLua->Push(false);\
    		gLua->Push(-1.0f);\
    		gLua->Push("Unknown error");\
    		return 3;\
    	}
    
    LUA_FUNCTION( lTS3GetVersion ) {
    	char* verTemp;
    	unsigned int errCode;
    	tryTS3Call(ts3client_getClientLibVersion, &verTemp);
    	gLua->Push(verTemp);
    	ts3client_freeMemory(verTemp);
    	return 1;
    }
    
    LUA_FUNCTION( lTS3Disconnect ) {
    	if(!connectionHandler) {
    		gLua->Push(false);
    		gLua->Push(-1.0f);
    		gLua->Push("Not connected");
    		return 3;
    	}
    	const char* leaveMsg = "disconnected";
    	if(gLua->Top() > 0) {
    		gLua->CheckType(1, Type::STRING);
    		leaveMsg = gLua->GetString();
    	}
    	unsigned int errCode;
    	tryTS3Call(ts3client_stopConnection, connectionHandler, leaveMsg)
    	tryTS3Call(ts3client_destroyServerConnectionHandler, connectionHandler)
    
    	connectionHandler = NULL;
    	gLua->Push(true);
    	return 1;
    }
    
    LUA_FUNCTION( lTS3Connect ) {
    	if(connectionHandler && isConnected) {
    		gLua->Push(false);
    		gLua->Push(-1.0f);
    		gLua->Push("Already connected");
    		return 3;
    	}
    	gLua->CheckType(1, Type::STRING);//host
    	gLua->CheckType(2, Type::NUMBER);//port
    	gLua->CheckType(3, Type::STRING);//username
    	int top = gLua->Top();
    	bool usePass, useChannelPass, useDefaultChannel = false;
    	char* channelPath[9];
    	memset(channelPath, NULL, 9);
    	switch(top) {
    		case 6:
    			gLua->CheckType(6, Type::STRING);//password
    			usePass = true;
    		case 5:
    			if(gLua->GetType(5) == Type::STRING) {
    				useChannelPass = true;
    			}
    		case 4:
    			if(gLua->GetType(4) == Type::TABLE) {
    				ILuaObject* lTbl = gLua->GetObject(4);
    				char idx[2] = {'\0', '\0'};
    				ILuaObject* tblMember;
    				char errMsg[128];
    				for(int i = '1'; '9' > i;i++) {
    					idx[0] = (char)i;
    					if(tblMember = lTbl->GetMember(idx)) {
    						if(!tblMember->isString()) {
    							sprintf(errMsg, "Invalid value for channel path table, expected string got %s at key %c", lTbl->GetTypeName(), i);
    							gLua->Error(errMsg);
    							return 0;
    						}
    						const char* str = tblMember->GetString();
    						if(!strcmp(str, "")) {
    							sprintf(errMsg, "Invalid value for channel path table, got empty string at key %c", i);
    							gLua->Error(errMsg);
    							return 0;
    						}
    						channelPath[i-49] = (char*)malloc(strlen(str)+1);
    						strcpy(channelPath[i-49], str);
    					}
    					else
    						break;
    				}
    
    			}
    			useDefaultChannel = true;
    	}
    	unsigned int errCode;
    	char* identity;
    	TS3LOG("creating connection handler\n");
    	if(!connectionHandler)
    		tryTS3Call(ts3client_spawnNewServerConnectionHandler, 0, &connectionHandler);
    
    	/*char* mode;
    		TS3LOG("getting default capture mode\n");
    	tryTS3Call(ts3client_getDefaultCaptureMode, &mode);
    
    	char** captureDevice;
    		TS3LOG("getting default capture device\n");
    	tryTS3Call(ts3client_getDefaultCaptureDevice, mode, &captureDevice);*/
    
    		TS3LOG("opening capture device\n");
    	tryTS3Call(ts3client_openCaptureDevice, connectionHandler, "", NULL)
    	
    		TS3LOG("opening playback device\n");
    	tryTS3Call(ts3client_openPlaybackDevice, connectionHandler, "", NULL)
    		TS3LOG("creating identity device\n");
    	tryTS3Call(ts3client_createIdentity, &identity)
    		TS3LOG("connecting\n");
    	tryTS3Call(
    		ts3client_startConnection,
    		connectionHandler,
    		identity,
    		gLua->GetString(1),
    		(unsigned int)gLua->GetNumber(2),
    		gLua->GetString(3),
    		useDefaultChannel ? const_cast<const char **>(channelPath) : NULL,
    		useChannelPass ? gLua->GetString(5) : "",
    		usePass ? gLua->GetString(6) : ""
    	)
    	isConnected = true;
    	gLua->Push(true);
    	return 1;
    }
    
    LUA_FUNCTION( lTS3Init ) {
    	if(isInitialized) {
    		gLua->Push(false);
    		gLua->Push(-1.0f);
    		gLua->Push("Already initialized");
    		return 3;
    	}
    	unsigned int errCode;
    	tryTS3Call(ts3client_initClientLib, &handlerFuncs, NULL, LogType_FILE | LogType_CONSOLE | LogType_USERLOGGING, NULL, "ts3logs/")
    	gLua->Push(true);
    	isInitialized = true;
    	return 1;
    }
    
    int Open( lua_State *L )
    {
    	gLua = Lua();
    
    	debugFile = fopen("ts3debug.txt", "w");
    
    
    	/* Initialize all callbacks with NULL */
    	memset(&handlerFuncs, 0, sizeof(struct ClientUIFunctions));
    
    	/* Callback function pointers */
    	/* It is sufficient to only assign those callback functions you are using. When adding more callbacks, add those function pointers here. */
    	handlerFuncs.onConnectStatusChangeEvent    = onConnectStatusChangeEvent;
    	handlerFuncs.onNewChannelEvent             = onNewChannelEvent;
    	handlerFuncs.onNewChannelCreatedEvent      = onNewChannelCreatedEvent;
    	handlerFuncs.onDelChannelEvent             = onDelChannelEvent;
    	handlerFuncs.onClientMoveEvent             = onClientMoveEvent;
    	handlerFuncs.onClientMoveSubscriptionEvent = onClientMoveSubscriptionEvent;
    	handlerFuncs.onClientMoveTimeoutEvent      = onClientMoveTimeoutEvent;
    	handlerFuncs.onTalkStatusChangeEvent       = onTalkStatusChangeEvent;
    	handlerFuncs.onServerErrorEvent            = onServerErrorEvent;
    
    	ILuaObject* ts3 = gLua->GetNewTable();
    	ts3->SetMember("init", lTS3Init);
    	ts3->SetMember("connect", lTS3Connect);
    	ts3->SetMember("disconnect", lTS3Disconnect);
    	ts3->SetMember("getVersion", lTS3GetVersion);
    
    	gLua->SetGlobal("teamspeak", ts3);
    
    	ts3->UnReference();
    	return 0;
    }
    
    int Close( lua_State *L )
    {
    	fclose(debugFile);
    	ts3client_stopConnection(connectionHandler, "disconnected");
    	ts3client_destroyServerConnectionHandler(connectionHandler);
    	ts3client_destroyClientLib();
    	return 0;
    }

  2. #2
    Join Date
    December 2009
    Location
    Germany
    Posts
    7
    Nevermind, I had 2 parameters swapped.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. [On Todo] Query API: servergroupbyclientid returns help for servergroupsbyclientid
    By nikeee in forum Bug Reports [EN/DE]
    Replies: 11
    Last Post: December 9th, 2014, 01:30 PM
  2. Replies: 9
    Last Post: September 28th, 2014, 04:30 PM
  3. PluginSDK getClientID returns ERROR_ok when not connected.
    By SilentStorm in forum Bug Reports [EN/DE]
    Replies: 1
    Last Post: January 26th, 2012, 11:23 AM
  4. [No Bug] [PluginSDK] requestDeleteFile always returns 0x806
    By SilentStorm in forum Bug Reports [EN/DE]
    Replies: 1
    Last Post: April 6th, 2011, 08:13 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •